#include "asterisk.h"
#include "console_video.h"
#include "asterisk/frame.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | _cm |
struct | video_codec_desc |
struct | video_dec_desc |
Defines | |
#define | H261_MIN_LEN 10 |
#define | H263_MIN_LEN 6 |
#define | HAVE_NAL(x) (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1) |
#define | N_DEC_IN 3 |
Typedefs | |
typedef int(*) | decoder_decap_f (struct fbuf_t *b, uint8_t *data, int len) |
extract the bitstream from RTP frames and store in the fbuf. return 0 if ok, 1 on error | |
typedef int(*) | decoder_decode_f (struct video_dec_desc *v, struct fbuf_t *b) |
actually call the decoder | |
typedef int(*) | decoder_init_f (AVCodecContext *enc_ctx) |
inizialize the decoder | |
typedef ast_frame *(*) | encoder_encap_f (struct fbuf_t *, int mtu, struct ast_frame **tail) |
encapsulate the bistream in RTP frames | |
typedef int(*) | encoder_encode_f (struct video_out_desc *v) |
actually call the encoder | |
typedef int(*) | encoder_init_f (AVCodecContext *v) |
initialize the encoder | |
Functions | |
static struct ast_frame * | create_video_frame (uint8_t *start, uint8_t *end, int format, int head, struct ast_frame *prev) |
static struct video_dec_desc * | dec_init (uint32_t the_ast_format) |
static struct video_dec_desc * | dec_uninit (struct video_dec_desc *v) |
uninitialize the descriptor for remote video stream | |
static int | fbuf_append (struct fbuf_t *b, uint8_t *src, int len, int sbit, int ebit) |
static int | ffmpeg_decode (struct video_dec_desc *v, struct fbuf_t *b) |
static int | ffmpeg_encode (struct video_out_desc *v) |
static int | h261_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h261_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h261_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h263_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h263_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h263_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h263p_decap (struct fbuf_t *b, uint8_t *data, int len) |
extract the bitstreem from the RTP payload. This is format dependent. For h263+, the format is defined in RFC 2429 and basically has a fixed 2-byte header as follows: 5 bits RR reserved, shall be 0 1 bit P indicate a start/end condition, in which case the payload should be prepended by two zero-valued bytes. 1 bit V there is an additional VRC header after this header 6 bits PLEN length in bytes of extra picture header 3 bits PEBIT how many bits to be ignored in the last byte | |
static int | h263p_enc_init (AVCodecContext *enc_ctx) |
initialization of h263p | |
static struct ast_frame * | h263p_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h264_dec_init (AVCodecContext *dec_ctx) |
static int | h264_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h264_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h264_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static struct video_codec_desc * | map_video_codec (int fmt) |
static enum CodecID | map_video_format (uint32_t ast_format, int rw) |
map an asterisk format into an ffmpeg one | |
static int | mpeg4_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | mpeg4_decode (struct video_dec_desc *v, struct fbuf_t *b) |
static int | mpeg4_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | mpeg4_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
Variables | |
static struct video_codec_desc | h261_codec |
static struct video_codec_desc | h263_codec |
static struct video_codec_desc | h263p_codec |
static struct video_codec_desc | h264_codec |
static struct video_codec_desc | mpeg4_codec |
static struct video_codec_desc * | supported_codecs [] |
static struct _cm | video_formats [] |
#define H261_MIN_LEN 10 |
Referenced by h261_encap().
#define H263_MIN_LEN 6 |
Referenced by h263_encap().
#define HAVE_NAL | ( | x | ) | (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1) |
Referenced by h264_encap().
#define N_DEC_IN 3 |
typedef int(*) decoder_decap_f(struct fbuf_t *b, uint8_t *data, int len) |
typedef int(*) decoder_decode_f(struct video_dec_desc *v, struct fbuf_t *b) |
typedef int(*) decoder_init_f(AVCodecContext *enc_ctx) |
typedef struct ast_frame*(*) encoder_encap_f(struct fbuf_t *, int mtu, struct ast_frame **tail) |
typedef int(*) encoder_encode_f(struct video_out_desc *v) |
typedef int(*) encoder_init_f(AVCodecContext *v) |
static struct ast_frame* create_video_frame | ( | uint8_t * | start, | |
uint8_t * | end, | |||
int | format, | |||
int | head, | |||
struct ast_frame * | prev | |||
) | [static] |
Build an ast_frame for a given chunk of data, and link it into the queue, with possibly 'head' bytes at the beginning to fill in some fields later.
Definition at line 228 of file vcodecs.c.
References ast_calloc, AST_FRAME_VIDEO, ast_free, AST_LIST_NEXT, ast_log(), AST_MALLOCD_DATA, AST_MALLOCD_HDR, ast_frame::data, f, len(), and LOG_WARNING.
Referenced by h261_encap(), h263_encap(), h263p_encap(), h264_encap(), and mpeg4_encap().
00230 { 00231 int len = end-start; 00232 uint8_t *data; 00233 struct ast_frame *f; 00234 00235 data = ast_calloc(1, len+head); 00236 f = ast_calloc(1, sizeof(*f)); 00237 if (f == NULL || data == NULL) { 00238 ast_log(LOG_WARNING, "--- frame error f %p data %p len %d format %d\n", 00239 f, data, len, format); 00240 if (f) 00241 ast_free(f); 00242 if (data) 00243 ast_free(data); 00244 return NULL; 00245 } 00246 memcpy(data+head, start, len); 00247 f->data.ptr = data; 00248 f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR; 00249 //f->has_timing_info = 1; 00250 //f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts); 00251 f->datalen = len+head; 00252 f->frametype = AST_FRAME_VIDEO; 00253 f->subclass = format; 00254 f->samples = 0; 00255 f->offset = 0; 00256 f->src = "Console"; 00257 f->delivery.tv_sec = 0; 00258 f->delivery.tv_usec = 0; 00259 f->seqno = 0; 00260 AST_LIST_NEXT(f, frame_list) = NULL; 00261 00262 if (prev) 00263 AST_LIST_NEXT(prev, frame_list) = f; 00264 00265 return f; 00266 }
static struct video_dec_desc* dec_init | ( | uint32_t | the_ast_format | ) | [static] |
Definition at line 1203 of file vcodecs.c.
References ast_calloc, ast_log(), video_dec_desc::codec, dec_uninit(), LOG_WARNING, map_video_codec(), and map_video_format().
01204 { 01205 enum CodecID codec; 01206 struct video_dec_desc *v = ast_calloc(1, sizeof(*v)); 01207 if (v == NULL) 01208 return NULL; 01209 01210 v->discard = 1; 01211 01212 v->d_callbacks = map_video_codec(the_ast_format); 01213 if (v->d_callbacks == NULL) { 01214 ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", the_ast_format); 01215 return dec_uninit(v); 01216 } 01217 01218 codec = map_video_format(v->d_callbacks->format, CM_RD); 01219 01220 v->codec = avcodec_find_decoder(codec); 01221 if (!v->codec) { 01222 ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec); 01223 return dec_uninit(v); 01224 } 01225 /* 01226 * Initialize the codec context. 01227 */ 01228 v->dec_ctx = avcodec_alloc_context(); 01229 if (!v->dec_ctx) { 01230 ast_log(LOG_WARNING, "Cannot allocate the decoder context\n"); 01231 return dec_uninit(v); 01232 } 01233 /* XXX call dec_init() ? */ 01234 if (avcodec_open(v->dec_ctx, v->codec) < 0) { 01235 ast_log(LOG_WARNING, "Cannot open the decoder context\n"); 01236 av_free(v->dec_ctx); 01237 v->dec_ctx = NULL; 01238 return dec_uninit(v); 01239 } 01240 01241 v->parser = av_parser_init(codec); 01242 if (!v->parser) { 01243 ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n"); 01244 return dec_uninit(v); 01245 } 01246 01247 v->d_frame = avcodec_alloc_frame(); 01248 if (!v->d_frame) { 01249 ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n"); 01250 return dec_uninit(v); 01251 } 01252 v->dec_in_cur = &v->dec_in[0]; /* buffer for incoming frames */ 01253 v->dec_in_dpy = NULL; /* nothing to display */ 01254 01255 return v; /* ok */ 01256 }
static struct video_dec_desc* dec_uninit | ( | struct video_dec_desc * | v | ) | [static] |
uninitialize the descriptor for remote video stream
Definition at line 1171 of file vcodecs.c.
References ast_free, video_dec_desc::codec, video_dec_desc::d_callbacks, video_dec_desc::d_frame, video_dec_desc::dec_ctx, video_dec_desc::dec_in, video_dec_desc::dec_out, video_dec_desc::discard, fbuf_free(), N_DEC_IN, and video_dec_desc::parser.
Referenced by dec_init().
01172 { 01173 int i; 01174 01175 if (v == NULL) /* not initialized yet */ 01176 return NULL; 01177 if (v->parser) { 01178 av_parser_close(v->parser); 01179 v->parser = NULL; 01180 } 01181 if (v->dec_ctx) { 01182 avcodec_close(v->dec_ctx); 01183 av_free(v->dec_ctx); 01184 v->dec_ctx = NULL; 01185 } 01186 if (v->d_frame) { 01187 av_free(v->d_frame); 01188 v->d_frame = NULL; 01189 } 01190 v->codec = NULL; /* only a reference */ 01191 v->d_callbacks = NULL; /* forget the decoder */ 01192 v->discard = 1; /* start in discard mode */ 01193 for (i = 0; i < N_DEC_IN; i++) 01194 fbuf_free(&v->dec_in[i]); 01195 fbuf_free(&v->dec_out); 01196 ast_free(v); 01197 return NULL; /* error, in case someone cares */ 01198 }
static int fbuf_append | ( | struct fbuf_t * | b, | |
uint8_t * | src, | |||
int | len, | |||
int | sbit, | |||
int | ebit | |||
) | [static] |
Definition at line 273 of file vcodecs.c.
References ast_calloc, ast_log(), ast_realloc, fbuf_t::data, fbuf_t::ebit, LOG_WARNING, fbuf_t::size, and fbuf_t::used.
Referenced by h261_decap(), h263_decap(), h263p_decap(), h264_decap(), and mpeg4_decap().
00275 { 00276 /* 00277 * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE, 00278 * and also wants 0 as a buffer terminator to prevent trouble. 00279 */ 00280 int need = len + FF_INPUT_BUFFER_PADDING_SIZE; 00281 int i; 00282 uint8_t *dst, mask; 00283 00284 if (b->data == NULL) { 00285 b->size = need; 00286 b->used = 0; 00287 b->ebit = 0; 00288 b->data = ast_calloc(1, b->size); 00289 } else if (b->used + need > b->size) { 00290 b->size = b->used + need; 00291 b->data = ast_realloc(b->data, b->size); 00292 } 00293 if (b->data == NULL) { 00294 ast_log(LOG_WARNING, "alloc failure for %d, discard\n", 00295 b->size); 00296 return 1; 00297 } 00298 if (b->used == 0 && b->ebit != 0) { 00299 ast_log(LOG_WARNING, "ebit not reset at start\n"); 00300 b->ebit = 0; 00301 } 00302 dst = b->data + b->used; 00303 i = b->ebit + sbit; /* bits to ignore around */ 00304 if (i == 0) { /* easy case, just append */ 00305 /* do everything in the common block */ 00306 } else if (i == 8) { /* easy too, just handle the overlap byte */ 00307 mask = (1 << b->ebit) - 1; 00308 /* update the last byte in the buffer */ 00309 dst[-1] &= ~mask; /* clear bits to ignore */ 00310 dst[-1] |= (*src & mask); /* append new bits */ 00311 src += 1; /* skip and prepare for common block */ 00312 len --; 00313 } else { /* must shift the new block, not done yet */ 00314 ast_log(LOG_WARNING, "must handle shift %d %d at %d\n", 00315 b->ebit, sbit, b->used); 00316 return 1; 00317 } 00318 memcpy(dst, src, len); 00319 b->used += len; 00320 b->ebit = ebit; 00321 b->data[b->used] = 0; /* padding */ 00322 return 0; 00323 }
static int ffmpeg_decode | ( | struct video_dec_desc * | v, | |
struct fbuf_t * | b | |||
) | [static] |
Definition at line 482 of file vcodecs.c.
References ast_log(), video_dec_desc::d_frame, fbuf_t::data, video_dec_desc::dec_ctx, fbuf_t::ebit, len(), LOG_NOTICE, video_dec_desc::parser, and fbuf_t::used.
00483 { 00484 uint8_t *src = b->data; 00485 int srclen = b->used; 00486 int full_frame = 0; 00487 00488 if (srclen == 0) /* no data */ 00489 return 0; 00490 while (srclen) { 00491 uint8_t *data; 00492 int datalen, ret; 00493 int len = av_parser_parse(v->parser, v->dec_ctx, &data, &datalen, src, srclen, 0, 0); 00494 00495 src += len; 00496 srclen -= len; 00497 /* The parser might return something it cannot decode, so it skips 00498 * the block returning no data 00499 */ 00500 if (data == NULL || datalen == 0) 00501 continue; 00502 ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame, data, datalen); 00503 if (full_frame == 1) /* full frame */ 00504 break; 00505 if (ret < 0) { 00506 ast_log(LOG_NOTICE, "Error decoding\n"); 00507 break; 00508 } 00509 } 00510 if (srclen != 0) /* update b with leftover data */ 00511 memmove(b->data, src, srclen); 00512 b->used = srclen; 00513 b->ebit = 0; 00514 return full_frame; 00515 }
static int ffmpeg_encode | ( | struct video_out_desc * | v | ) | [static] |
Definition at line 461 of file vcodecs.c.
References ast_log(), fbuf_t::data, LOG_WARNING, fbuf_t::size, and fbuf_t::used.
00462 { 00463 struct fbuf_t *b = &v->enc_out; 00464 int i; 00465 00466 b->used = avcodec_encode_video(v->enc_ctx, b->data, b->size, v->enc_in_frame); 00467 i = avcodec_encode_video(v->enc_ctx, b->data + b->used, b->size - b->used, NULL); /* delayed frames ? */ 00468 if (i > 0) { 00469 ast_log(LOG_WARNING, "have %d more bytes\n", i); 00470 b->used += i; 00471 } 00472 return 0; 00473 }
static int h261_decap | ( | struct fbuf_t * | b, | |
uint8_t * | data, | |||
int | len | |||
) | [static] |
Definition at line 827 of file vcodecs.c.
References ast_log(), fbuf_append(), and LOG_WARNING.
00828 { 00829 int ebit, sbit; 00830 00831 if (len < 8) { 00832 ast_log(LOG_WARNING, "invalid framesize %d\n", len); 00833 return 1; 00834 } 00835 sbit = (data[0] >> 5) & 7; 00836 ebit = (data[0] >> 2) & 7; 00837 len -= 4; 00838 data += 4; 00839 return fbuf_append(b, data, len, sbit, ebit); 00840 }
static int h261_enc_init | ( | AVCodecContext * | enc_ctx | ) | [static] |
Definition at line 702 of file vcodecs.c.
00703 { 00704 /* It is important to set rtp_payload_size = 0, otherwise 00705 * ffmpeg in h261 mode will produce output that it cannot parse. 00706 * Also try to send I frames more frequently than with other codecs. 00707 */ 00708 enc_ctx->rtp_payload_size = 0; /* important - ffmpeg fails otherwise */ 00709 00710 return 0; 00711 }
static struct ast_frame* h261_encap | ( | struct fbuf_t * | b, | |
int | mtu, | |||
struct ast_frame ** | tail | |||
) | [static] |
Definition at line 729 of file vcodecs.c.
References AST_FORMAT_H261, create_video_frame(), fbuf_t::data, f, first, H261_MIN_LEN, len(), ast_frame::subclass, and fbuf_t::used.
00731 { 00732 uint8_t *d = b->data; 00733 int start = 0, i, len = b->used; 00734 struct ast_frame *f, *cur = NULL, *first = NULL; 00735 const int pheader_len = 4; 00736 uint8_t h261_hdr[4]; 00737 uint8_t *h = h261_hdr; /* shorthand */ 00738 int sbit = 0, ebit = 0; 00739 00740 #define H261_MIN_LEN 10 00741 if (len < H261_MIN_LEN) /* unreasonably small */ 00742 return NULL; 00743 00744 memset(h261_hdr, '\0', sizeof(h261_hdr)); 00745 00746 /* Similar to the code in h263_encap, but the marker there is longer. 00747 * Start a few bytes within the bitstream to avoid hitting the marker 00748 * twice. Note we might access the buffer at len, but this is ok because 00749 * the caller has it oversized. 00750 */ 00751 for (i = H261_MIN_LEN, start = 0; start < len - 1; start = i, i += 4) { 00752 #if 0 /* test - disable packetization */ 00753 i = len; /* wrong... */ 00754 #else 00755 int found = 0, found_ebit = 0; /* last GBSC position found */ 00756 for (; i < len ; i++) { 00757 uint8_t x, rpos, lpos; 00758 if (d[i] != 0) /* cannot be in a GBSC */ 00759 continue; 00760 x = d[i+1]; 00761 if (x == 0) /* next is equally good */ 00762 continue; 00763 /* See if around us we find 15 '0' bits for the GBSC. 00764 * Look for the first bit set on the right, and then 00765 * see if we have enough 0 on the left. 00766 * We are guaranteed to end before rpos == 0 00767 */ 00768 for (rpos = 0x80, ebit = 7; rpos; ebit--, rpos >>= 1) 00769 if (x & rpos) /* found the '1' bit in GBSC */ 00770 break; 00771 x = d[i-1]; /* now look behind */ 00772 for (lpos = (rpos >> 1); lpos ; lpos >>= 1) 00773 if (x & lpos) /* too early, not a GBSC */ 00774 break; 00775 if (lpos) /* as i said... */ 00776 continue; 00777 /* now we have a GBSC starting somewhere in d[i-1], 00778 * but it might be not byte-aligned. Just remember it. 00779 */ 00780 if (i - start > mtu) /* too large, stop now */ 00781 break; 00782 found_ebit = ebit; 00783 found = i; 00784 i += 4; /* continue forward */ 00785 } 00786 if (i >= len) { /* trim if we went too forward */ 00787 i = len; 00788 ebit = 0; /* hopefully... should ask the bitstream ? */ 00789 } 00790 if (i - start > mtu && found) { 00791 /* use the previous GBSC, hope is within the mtu */ 00792 i = found; 00793 ebit = found_ebit; 00794 } 00795 #endif /* test */ 00796 if (i - start < 4) /* XXX too short ? */ 00797 continue; 00798 /* This frame is up to offset i (not inclusive). 00799 * We do not split it yet even if larger than MTU. 00800 */ 00801 f = create_video_frame(d + start, d+i, AST_FORMAT_H261, 00802 pheader_len, cur); 00803 00804 if (!f) 00805 break; 00806 /* recompute header with I=0, V=1 */ 00807 h[0] = ( (sbit & 7) << 5 ) | ( (ebit & 7) << 2 ) | 1; 00808 memmove(f->data.ptr, h, 4); /* copy the h261 header */ 00809 if (ebit) /* not aligned, restart from previous byte */ 00810 i--; 00811 sbit = (8 - ebit) & 7; 00812 ebit = 0; 00813 if (!cur) 00814 first = f; 00815 cur = f; 00816 } 00817 if (cur) 00818 cur->subclass |= 1; // RTP Marker 00819 00820 *tail = cur; 00821 return first; 00822 }
static int h263_decap | ( | struct fbuf_t * | b, | |
uint8_t * | data, | |||
int | len | |||
) | [static] |
Definition at line 671 of file vcodecs.c.
References ast_log(), fbuf_append(), and LOG_WARNING.
00672 { 00673 if (len < 4) { 00674 ast_log(LOG_WARNING, "invalid framesize %d\n", len); 00675 return 1; /* error */ 00676 } 00677 00678 if ( (data[0] & 0x80) == 0) { 00679 len -= 4; 00680 data += 4; 00681 } else { 00682 ast_log(LOG_WARNING, "unsupported mode 0x%x\n", 00683 data[0]); 00684 return 1; 00685 } 00686 return fbuf_append(b, data, len, 0, 0); /* XXX no bit alignment support yet */ 00687 }
static int h263_enc_init | ( | AVCodecContext * | enc_ctx | ) | [static] |
Definition at line 530 of file vcodecs.c.
00531 { 00532 /* XXX check whether these are supported */ 00533 enc_ctx->flags |= CODEC_FLAG_H263P_UMV; 00534 enc_ctx->flags |= CODEC_FLAG_H263P_AIC; 00535 enc_ctx->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; 00536 enc_ctx->flags |= CODEC_FLAG_AC_PRED; 00537 00538 return 0; 00539 }
static struct ast_frame* h263_encap | ( | struct fbuf_t * | b, | |
int | mtu, | |||
struct ast_frame ** | tail | |||
) | [static] |
Definition at line 575 of file vcodecs.c.
References AST_FORMAT_H263, ast_log(), create_video_frame(), fbuf_t::data, f, first, H263_MIN_LEN, len(), LOG_WARNING, ast_frame::subclass, and fbuf_t::used.
00577 { 00578 uint8_t *d = b->data; 00579 int start = 0, i, len = b->used; 00580 struct ast_frame *f, *cur = NULL, *first = NULL; 00581 const int pheader_len = 4; /* Use RFC-2190 Mode A */ 00582 uint8_t h263_hdr[12]; /* worst case, room for a type c header */ 00583 uint8_t *h = h263_hdr; /* shorthand */ 00584 00585 #define H263_MIN_LEN 6 00586 if (len < H263_MIN_LEN) /* unreasonably small */ 00587 return NULL; 00588 00589 memset(h263_hdr, '\0', sizeof(h263_hdr)); 00590 /* Now set the header bytes. Only type A by now, 00591 * and h[0] = h[2] = h[3] = 0 by default. 00592 * PTYPE starts 30 bits in the picture, so the first useful 00593 * bit for us is bit 36 i.e. within d[4] (0 is the msbit). 00594 * SRC = d[4] & 0x1c goes into data[1] & 0xe0 00595 * I = d[4] & 0x02 goes into data[1] & 0x10 00596 * U = d[4] & 0x01 goes into data[1] & 0x08 00597 * S = d[5] & 0x80 goes into data[1] & 0x04 00598 * A = d[5] & 0x40 goes into data[1] & 0x02 00599 * R = 0 goes into data[1] & 0x01 00600 * Optimizing it, we have 00601 */ 00602 h[1] = ( (d[4] & 0x1f) << 3 ) | /* SRC, I, U */ 00603 ( (d[5] & 0xc0) >> 5 ); /* S, A, R */ 00604 00605 /* now look for the next PSC or GOB header. First try to hit 00606 * a '0' byte then look around for the 0000 0000 0000 0000 1 pattern 00607 * which is both in the PSC and the GBSC. 00608 */ 00609 for (i = H263_MIN_LEN, start = 0; start < len; start = i, i += 3) { 00610 //ast_log(LOG_WARNING, "search at %d of %d/%d\n", i, start, len); 00611 for (; i < len ; i++) { 00612 uint8_t x, rpos, lpos; 00613 int rpos_i; /* index corresponding to rpos */ 00614 if (d[i] != 0) /* cannot be in a GBSC */ 00615 continue; 00616 if (i > len - 1) 00617 break; 00618 x = d[i+1]; 00619 if (x == 0) /* next is equally good */ 00620 continue; 00621 /* see if around us we can make 16 '0' bits for the GBSC. 00622 * Look for the first bit set on the right, and then 00623 * see if we have enough 0 on the left. 00624 * We are guaranteed to end before rpos == 0 00625 */ 00626 for (rpos = 0x80, rpos_i = 8; rpos; rpos >>= 1, rpos_i--) 00627 if (x & rpos) /* found the '1' bit in GBSC */ 00628 break; 00629 x = d[i-1]; /* now look behind */ 00630 for (lpos = rpos; lpos ; lpos >>= 1) 00631 if (x & lpos) /* too early, not a GBSC */ 00632 break; 00633 if (lpos) /* as i said... */ 00634 continue; 00635 /* now we have a GBSC starting somewhere in d[i-1], 00636 * but it might be not byte-aligned 00637 */ 00638 if (rpos == 0x80) { /* lucky case */ 00639 i = i - 1; 00640 } else { /* XXX to be completed */ 00641 ast_log(LOG_WARNING, "unaligned GBSC 0x%x %d\n", 00642 rpos, rpos_i); 00643 } 00644 break; 00645 } 00646 /* This frame is up to offset i (not inclusive). 00647 * We do not split it yet even if larger than MTU. 00648 */ 00649 f = create_video_frame(d + start, d+i, AST_FORMAT_H263, 00650 pheader_len, cur); 00651 00652 if (!f) 00653 break; 00654 memmove(f->data.ptr, h, 4); /* copy the h263 header */ 00655 /* XXX to do: if not aligned, fix sbit and ebit, 00656 * then move i back by 1 for the next frame 00657 */ 00658 if (!cur) 00659 first = f; 00660 cur = f; 00661 } 00662 00663 if (cur) 00664 cur->subclass |= 1; // RTP Marker 00665 00666 *tail = cur; 00667 return first; 00668 }
static int h263p_decap | ( | struct fbuf_t * | b, | |
uint8_t * | data, | |||
int | len | |||
) | [static] |
extract the bitstreem from the RTP payload. This is format dependent. For h263+, the format is defined in RFC 2429 and basically has a fixed 2-byte header as follows: 5 bits RR reserved, shall be 0 1 bit P indicate a start/end condition, in which case the payload should be prepended by two zero-valued bytes. 1 bit V there is an additional VRC header after this header 6 bits PLEN length in bytes of extra picture header 3 bits PEBIT how many bits to be ignored in the last byte
XXX the code below is not complete.
Definition at line 433 of file vcodecs.c.
References ast_log(), fbuf_append(), and LOG_WARNING.
00434 { 00435 int PLEN; 00436 00437 if (len < 2) { 00438 ast_log(LOG_WARNING, "invalid framesize %d\n", len); 00439 return 1; 00440 } 00441 PLEN = ( (data[0] & 1) << 5 ) | ( (data[1] & 0xf8) >> 3); 00442 00443 if (PLEN > 0) { 00444 data += PLEN; 00445 len -= PLEN; 00446 } 00447 if (data[0] & 4) /* bit P */ 00448 data[0] = data[1] = 0; 00449 else { 00450 data += 2; 00451 len -= 2; 00452 } 00453 return fbuf_append(b, data, len, 0, 0); /* ignore trail bits */ 00454 }
static int h263p_enc_init | ( | AVCodecContext * | enc_ctx | ) | [static] |
initialization of h263p
Definition at line 335 of file vcodecs.c.
00336 { 00337 /* modes supported are 00338 - Unrestricted Motion Vector (annex D) 00339 - Advanced Prediction (annex F) 00340 - Advanced Intra Coding (annex I) 00341 - Deblocking Filter (annex J) 00342 - Slice Structure (annex K) 00343 - Alternative Inter VLC (annex S) 00344 - Modified Quantization (annex T) 00345 */ 00346 enc_ctx->flags |=CODEC_FLAG_H263P_UMV; /* annex D */ 00347 enc_ctx->flags |=CODEC_FLAG_AC_PRED; /* annex f ? */ 00348 enc_ctx->flags |=CODEC_FLAG_H263P_SLICE_STRUCT; /* annex k */ 00349 enc_ctx->flags |= CODEC_FLAG_H263P_AIC; /* annex I */ 00350 00351 return 0; 00352 }
static struct ast_frame* h263p_encap | ( | struct fbuf_t * | b, | |
int | mtu, | |||
struct ast_frame ** | tail | |||
) | [static] |
Definition at line 360 of file vcodecs.c.
References AST_FORMAT_H263_PLUS, ast_log(), create_video_frame(), ast_frame::data, fbuf_t::data, f, first, len(), LOG_WARNING, MIN, ast_frame::subclass, and fbuf_t::used.
00362 { 00363 struct ast_frame *cur = NULL, *first = NULL; 00364 uint8_t *d = b->data; 00365 int len = b->used; 00366 int l = len; /* size of the current fragment. If 0, must look for a psc */ 00367 00368 for (;len > 0; len -= l, d += l) { 00369 uint8_t *data; 00370 struct ast_frame *f; 00371 int i, h; 00372 00373 if (len >= 3 && d[0] == 0 && d[1] == 0 && d[2] >= 0x80) { 00374 /* we are starting a new block, so look for a PSC. */ 00375 for (i = 3; i < len - 3; i++) { 00376 if (d[i] == 0 && d[i+1] == 0 && d[i+2] >= 0x80) { 00377 l = i; 00378 break; 00379 } 00380 } 00381 } 00382 if (l > mtu || l > len) { /* psc not found, split */ 00383 l = MIN(len, mtu); 00384 } 00385 if (l < 1 || l > mtu) { 00386 ast_log(LOG_WARNING, "--- frame error l %d\n", l); 00387 break; 00388 } 00389 00390 if (d[0] == 0 && d[1] == 0) { /* we start with a psc */ 00391 h = 0; 00392 } else { /* no psc, create a header */ 00393 h = 2; 00394 } 00395 00396 f = create_video_frame(d, d+l, AST_FORMAT_H263_PLUS, h, cur); 00397 if (!f) 00398 break; 00399 00400 data = f->data.ptr; 00401 if (h == 0) { /* we start with a psc */ 00402 data[0] |= 0x04; // set P == 1, and we are done 00403 } else { /* no psc, create a header */ 00404 data[0] = data[1] = 0; // P == 0 00405 } 00406 00407 if (!cur) 00408 first = f; 00409 cur = f; 00410 } 00411 00412 if (cur) 00413 cur->subclass |= 1; // RTP Marker 00414 00415 *tail = cur; /* end of the list */ 00416 return first; 00417 }
static int h264_dec_init | ( | AVCodecContext * | dec_ctx | ) | [static] |
static int h264_decap | ( | struct fbuf_t * | b, | |
uint8_t * | data, | |||
int | len | |||
) | [static] |
Definition at line 1046 of file vcodecs.c.
References ast_log(), fbuf_append(), LOG_WARNING, and type.
01047 { 01048 /* Start Code Prefix (Annex B in specification) */ 01049 uint8_t scp[] = { 0x00, 0x00, 0x00, 0x01 }; 01050 int retval = 0; 01051 int type, ofs = 0; 01052 01053 if (len < 2) { 01054 ast_log(LOG_WARNING, "--- invalid len %d\n", len); 01055 return 1; 01056 } 01057 /* first of all, check if the packet has F == 0 */ 01058 if (data[0] & 0x80) { 01059 ast_log(LOG_WARNING, "--- forbidden packet; nal: %02x\n", 01060 data[0]); 01061 return 1; 01062 } 01063 01064 type = data[0] & 0x1f; 01065 switch (type) { 01066 case 0: 01067 case 31: 01068 ast_log(LOG_WARNING, "--- invalid type: %d\n", type); 01069 return 1; 01070 case 24: 01071 case 25: 01072 case 26: 01073 case 27: 01074 case 29: 01075 ast_log(LOG_WARNING, "--- encapsulation not supported : %d\n", type); 01076 return 1; 01077 case 28: /* FU-A Unit */ 01078 if (data[1] & 0x80) { // S == 1, import F and NRI from next 01079 data[1] &= 0x1f; /* preserve type */ 01080 data[1] |= (data[0] & 0xe0); /* import F & NRI */ 01081 retval = fbuf_append(b, scp, sizeof(scp), 0, 0); 01082 ofs = 1; 01083 } else { 01084 ofs = 2; 01085 } 01086 break; 01087 default: /* From 1 to 23 (Single NAL Unit) */ 01088 retval = fbuf_append(b, scp, sizeof(scp), 0, 0); 01089 } 01090 if (!retval) 01091 retval = fbuf_append(b, data + ofs, len - ofs, 0, 0); 01092 if (retval) 01093 ast_log(LOG_WARNING, "result %d\n", retval); 01094 return retval; 01095 }
static int h264_enc_init | ( | AVCodecContext * | enc_ctx | ) | [static] |
Definition at line 926 of file vcodecs.c.
00927 { 00928 enc_ctx->flags |= CODEC_FLAG_TRUNCATED; 00929 //enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; 00930 //enc_ctx->flags2 |= CODEC_FLAG2_FASTPSKIP; 00931 /* TODO: Maybe we need to add some other flags */ 00932 enc_ctx->rtp_mode = 0; 00933 enc_ctx->rtp_payload_size = 0; 00934 enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate; 00935 return 0; 00936 }
static struct ast_frame* h264_encap | ( | struct fbuf_t * | b, | |
int | mtu, | |||
struct ast_frame ** | tail | |||
) | [static] |
Definition at line 959 of file vcodecs.c.
References AST_FORMAT_H264, ast_log(), create_video_frame(), ast_frame::data, fbuf_t::data, f, first, HAVE_NAL, LOG_WARNING, MIN, and fbuf_t::used.
00961 { 00962 struct ast_frame *f = NULL, *cur = NULL, *first = NULL; 00963 uint8_t *d, *start = b->data; 00964 uint8_t *end = start + b->used; 00965 00966 /* Search the first start code prefix - ITU-T H.264 sec. B.2, 00967 * and move start right after that, on the NAL header byte. 00968 */ 00969 #define HAVE_NAL(x) (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1) 00970 for (start += 4; start < end; start++) { 00971 int ty = start[0] & 0x1f; 00972 if (HAVE_NAL(start) && ty != 0 && ty != 31) 00973 break; 00974 } 00975 /* if not found, or too short, we just skip the next loop and are done. */ 00976 00977 /* Here follows the main loop to create frames. Search subsequent start 00978 * codes, and then possibly fragment the unit into smaller fragments. 00979 */ 00980 for (;start < end - 4; start = d) { 00981 int size; /* size of current block */ 00982 uint8_t hdr[2]; /* add-on header when fragmenting */ 00983 int ty = 0; 00984 00985 /* now search next nal */ 00986 for (d = start + 4; d < end; d++) { 00987 ty = d[0] & 0x1f; 00988 if (HAVE_NAL(d)) 00989 break; /* found NAL */ 00990 } 00991 /* have a block to send. d past the start code unless we overflow */ 00992 if (d >= end) { /* NAL not found */ 00993 d = end + 4; 00994 } else if (ty == 0 || ty == 31) { /* found but invalid type, skip */ 00995 ast_log(LOG_WARNING, "skip invalid nal type %d at %d of %d\n", 00996 ty, d - (uint8_t *)b->data, b->used); 00997 continue; 00998 } 00999 01000 size = d - start - 4; /* don't count the end */ 01001 01002 if (size < mtu) { // test - don't fragment 01003 // Single NAL Unit 01004 f = create_video_frame(start, d - 4, AST_FORMAT_H264, 0, cur); 01005 if (!f) 01006 break; 01007 if (!first) 01008 first = f; 01009 01010 cur = f; 01011 continue; 01012 } 01013 01014 // Fragmented Unit (Mode A: no DON, very weak) 01015 hdr[0] = (*start & 0xe0) | 28; /* mark as a fragmentation unit */ 01016 hdr[1] = (*start++ & 0x1f) | 0x80 ; /* keep type and set START bit */ 01017 size--; /* skip the NAL header */ 01018 while (size) { 01019 uint8_t *data; 01020 int frag_size = MIN(size, mtu); 01021 01022 f = create_video_frame(start, start+frag_size, AST_FORMAT_H264, 2, cur); 01023 if (!f) 01024 break; 01025 size -= frag_size; /* skip this data block */ 01026 start += frag_size; 01027 01028 data = f->data.ptr; 01029 data[0] = hdr[0]; 01030 data[1] = hdr[1] | (size == 0 ? 0x40 : 0); /* end bit if we are done */ 01031 hdr[1] &= ~0x80; /* clear start bit for subsequent frames */ 01032 if (!first) 01033 first = f; 01034 cur = f; 01035 } 01036 } 01037 01038 if (cur) 01039 cur->subclass |= 1; // RTP Marker 01040 01041 *tail = cur; 01042 01043 return first; 01044 }
static struct video_codec_desc* map_video_codec | ( | int | fmt | ) | [static] |
Definition at line 1157 of file vcodecs.c.
References ast_log(), format, LOG_WARNING, name, and supported_codecs.
Referenced by dec_init().
01158 { 01159 int i; 01160 01161 for (i = 0; supported_codecs[i]; i++) 01162 if (fmt == supported_codecs[i]->format) { 01163 ast_log(LOG_WARNING, "using %s for format 0x%x\n", 01164 supported_codecs[i]->name, fmt); 01165 return supported_codecs[i]; 01166 } 01167 return NULL; 01168 }
static enum CodecID map_video_format | ( | uint32_t | ast_format, | |
int | rw | |||
) | [static] |
map an asterisk format into an ffmpeg one
Definition at line 1133 of file vcodecs.c.
References _cm::ast_format, _cm::codec, _cm::rw, and video_formats.
Referenced by dec_init().
01134 { 01135 struct _cm *i; 01136 01137 for (i = video_formats; i->ast_format != 0; i++) 01138 if (ast_format & i->ast_format && rw & i->rw && rw & i->rw) 01139 return i->codec; 01140 return CODEC_ID_NONE; 01141 }
static int mpeg4_decap | ( | struct fbuf_t * | b, | |
uint8_t * | data, | |||
int | len | |||
) | [static] |
Definition at line 893 of file vcodecs.c.
References fbuf_append().
00894 { 00895 return fbuf_append(b, data, len, 0, 0); 00896 }
static int mpeg4_decode | ( | struct video_dec_desc * | v, | |
struct fbuf_t * | b | |||
) | [static] |
Definition at line 898 of file vcodecs.c.
References ast_log(), video_dec_desc::d_frame, fbuf_t::data, ast_frame::datalen, video_dec_desc::dec_ctx, fbuf_t::ebit, LOG_NOTICE, and fbuf_t::used.
00899 { 00900 int full_frame = 0, datalen = b->used; 00901 int ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame, 00902 b->data, datalen); 00903 if (ret < 0) { 00904 ast_log(LOG_NOTICE, "Error decoding\n"); 00905 ret = datalen; /* assume we used everything. */ 00906 } 00907 datalen -= ret; 00908 if (datalen > 0) /* update b with leftover bytes */ 00909 memmove(b->data, b->data + ret, datalen); 00910 b->used = datalen; 00911 b->ebit = 0; 00912 return full_frame; 00913 }
static int mpeg4_enc_init | ( | AVCodecContext * | enc_ctx | ) | [static] |
Definition at line 854 of file vcodecs.c.
00855 { 00856 #if 0 00857 //enc_ctx->flags |= CODEC_FLAG_LOW_DELAY; /*don't use b frames ?*/ 00858 enc_ctx->flags |= CODEC_FLAG_AC_PRED; 00859 enc_ctx->flags |= CODEC_FLAG_H263P_UMV; 00860 enc_ctx->flags |= CODEC_FLAG_QPEL; 00861 enc_ctx->flags |= CODEC_FLAG_4MV; 00862 enc_ctx->flags |= CODEC_FLAG_GMC; 00863 enc_ctx->flags |= CODEC_FLAG_LOOP_FILTER; 00864 enc_ctx->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; 00865 #endif 00866 enc_ctx->rtp_payload_size = 0; /* important - ffmpeg fails otherwise */ 00867 return 0; 00868 }
static struct ast_frame* mpeg4_encap | ( | struct fbuf_t * | b, | |
int | mtu, | |||
struct ast_frame ** | tail | |||
) | [static] |
Definition at line 871 of file vcodecs.c.
References AST_FORMAT_MP4_VIDEO, create_video_frame(), fbuf_t::data, f, first, len(), MIN, and fbuf_t::used.
00873 { 00874 struct ast_frame *f, *cur = NULL, *first = NULL; 00875 uint8_t *d = b->data; 00876 uint8_t *end = d + b->used; 00877 int len; 00878 00879 for (;d < end; d += len, cur = f) { 00880 len = MIN(mtu, end - d); 00881 f = create_video_frame(d, d + len, AST_FORMAT_MP4_VIDEO, 0, cur); 00882 if (!f) 00883 break; 00884 if (!first) 00885 first = f; 00886 } 00887 if (cur) 00888 cur->subclass |= 1; 00889 *tail = cur; 00890 return first; 00891 }
struct video_codec_desc h261_codec [static] |
struct video_codec_desc h263_codec [static] |
struct video_codec_desc h263p_codec [static] |
struct video_codec_desc h264_codec [static] |
struct video_codec_desc mpeg4_codec [static] |
struct video_codec_desc* supported_codecs[] [static] |
struct _cm video_formats[] [static] |