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