Thu Oct 11 06:37:40 2012

Asterisk developer's documentation


vcodecs.c File Reference

#include "asterisk.h"
#include "console_video.h"
#include "asterisk/frame.h"
#include "asterisk/utils.h"

Include dependency graph for vcodecs.c:

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 struct 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_framecreate_video_frame (uint8_t *start, uint8_t *end, int format, int head, struct ast_frame *prev)
static struct video_dec_descdec_init (uint32_t the_ast_format)
static struct video_dec_descdec_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_frameh261_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_frameh263_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_frameh263p_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_frameh264_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail)
static struct video_codec_descmap_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_framempeg4_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_descsupported_codecs []
static struct _cm video_formats []


Define Documentation

#define H261_MIN_LEN   10

Referenced by h261_encap().

#define H263_MIN_LEN   6

Referenced by h263_encap().

#define HAVE_NAL (  )     (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1)

Referenced by h264_encap().

#define N_DEC_IN   3

Definition at line 92 of file vcodecs.c.

Referenced by dec_uninit().


Typedef Documentation

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

Definition at line 54 of file vcodecs.c.

typedef int(* decoder_decode_f)(struct video_dec_desc *v, struct fbuf_t *b)

actually call the decoder

Definition at line 57 of file vcodecs.c.

typedef int(* decoder_init_f)(AVCodecContext *enc_ctx)

inizialize the decoder

Definition at line 49 of file vcodecs.c.

typedef struct ast_frame*(* encoder_encap_f)(struct fbuf_t *, int mtu, struct ast_frame **tail)

encapsulate the bistream in RTP frames

Definition at line 45 of file vcodecs.c.

typedef int(* encoder_encode_f)(struct video_out_desc *v)

actually call the encoder

Definition at line 42 of file vcodecs.c.

typedef int(* encoder_init_f)(AVCodecContext *v)

initialize the encoder

Definition at line 39 of file vcodecs.c.


Function Documentation

static struct ast_frame* create_video_frame ( uint8_t *  start,
uint8_t *  end,
int  format,
int  head,
struct ast_frame prev 
) [static, read]

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, ast_frame::datalen, ast_frame::delivery, f, ast_frame::frametype, len(), LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, ast_frame::src, and ast_frame::subclass.

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, read]

Definition at line 1204 of file vcodecs.c.

References ast_calloc, ast_log(), 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_in_cur, video_dec_desc::dec_in_dpy, dec_uninit(), video_dec_desc::discard, video_codec_desc::format, LOG_WARNING, map_video_codec(), map_video_format(), and video_dec_desc::parser.

01205 {
01206    enum CodecID codec;
01207    struct video_dec_desc *v = ast_calloc(1, sizeof(*v));
01208    if (v == NULL)
01209       return NULL;
01210 
01211    v->discard = 1;
01212 
01213    v->d_callbacks = map_video_codec(the_ast_format);
01214    if (v->d_callbacks == NULL) {
01215       ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", the_ast_format);
01216       return dec_uninit(v);
01217    }
01218 
01219    codec = map_video_format(v->d_callbacks->format, CM_RD);
01220 
01221    v->codec = avcodec_find_decoder(codec);
01222    if (!v->codec) {
01223       ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
01224       return dec_uninit(v);
01225    }
01226    /*
01227     * Initialize the codec context.
01228     */
01229    v->dec_ctx = avcodec_alloc_context();
01230    if (!v->dec_ctx) {
01231       ast_log(LOG_WARNING, "Cannot allocate the decoder context\n");
01232       return dec_uninit(v);
01233    }
01234    /* XXX call dec_init() ? */
01235    if (avcodec_open(v->dec_ctx, v->codec) < 0) {
01236       ast_log(LOG_WARNING, "Cannot open the decoder context\n");
01237       av_free(v->dec_ctx);
01238       v->dec_ctx = NULL;
01239       return dec_uninit(v);
01240    }
01241 
01242    v->parser = av_parser_init(codec);
01243    if (!v->parser) {
01244       ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n");
01245       return dec_uninit(v);
01246    }
01247 
01248    v->d_frame = avcodec_alloc_frame();
01249    if (!v->d_frame) {
01250       ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n");
01251       return dec_uninit(v);
01252    }
01253         v->dec_in_cur = &v->dec_in[0]; /* buffer for incoming frames */
01254         v->dec_in_dpy = NULL;      /* nothing to display */
01255 
01256    return v;   /* ok */
01257 }

static struct video_dec_desc* dec_uninit ( struct video_dec_desc v  )  [static, read]

uninitialize the descriptor for remote video stream

Definition at line 1172 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().

01173 {
01174    int i;
01175 
01176    if (v == NULL)    /* not initialized yet */
01177       return NULL;
01178    if (v->parser) {
01179       av_parser_close(v->parser);
01180       v->parser = NULL;
01181    }
01182    if (v->dec_ctx) {
01183       avcodec_close(v->dec_ctx);
01184       av_free(v->dec_ctx);
01185       v->dec_ctx = NULL;
01186    }
01187    if (v->d_frame) {
01188       av_free(v->d_frame);
01189       v->d_frame = NULL;
01190    }
01191    v->codec = NULL;  /* only a reference */
01192    v->d_callbacks = NULL;     /* forget the decoder */
01193    v->discard = 1;      /* start in discard mode */
01194    for (i = 0; i < N_DEC_IN; i++)
01195       fbuf_free(&v->dec_in[i]);
01196    fbuf_free(&v->dec_out);
01197    ast_free(v);
01198    return NULL;   /* error, in case someone cares */
01199 }

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, read]

Definition at line 729 of file vcodecs.c.

References AST_FORMAT_H261, create_video_frame(), ast_frame::data, fbuf_t::data, f, first, H261_MIN_LEN, len(), ast_frame::ptr, 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, read]

Definition at line 575 of file vcodecs.c.

References AST_FORMAT_H263, ast_log(), create_video_frame(), ast_frame::data, fbuf_t::data, f, first, H263_MIN_LEN, len(), LOG_WARNING, ast_frame::ptr, 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, read]

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::ptr, 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]

Definition at line 938 of file vcodecs.c.

00939 {
00940    dec_ctx->flags |= CODEC_FLAG_TRUNCATED;
00941 
00942    return 0;
00943 }

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, read]

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, ast_frame::ptr, ast_frame::subclass, 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, read]

Definition at line 1158 of file vcodecs.c.

References ast_log(), format, LOG_WARNING, and name.

Referenced by dec_init().

01159 {
01160    int i;
01161 
01162    for (i = 0; supported_codecs[i]; i++)
01163       if (fmt == supported_codecs[i]->format) {
01164          ast_log(LOG_WARNING, "using %s for format 0x%x\n",
01165             supported_codecs[i]->name, fmt);
01166          return supported_codecs[i];
01167       }
01168    return NULL;
01169 }

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, and _cm::rw.

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) {
01139          return i->codec;
01140       }
01141    return CODEC_ID_NONE;
01142 }

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, read]

Definition at line 871 of file vcodecs.c.

References AST_FORMAT_MP4_VIDEO, create_video_frame(), fbuf_t::data, f, first, len(), MIN, ast_frame::subclass, 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 }


Variable Documentation

struct video_codec_desc h261_codec [static]

Definition at line 842 of file vcodecs.c.

struct video_codec_desc h263_codec [static]

Definition at line 689 of file vcodecs.c.

struct video_codec_desc h263p_codec [static]

Definition at line 517 of file vcodecs.c.

struct video_codec_desc h264_codec [static]

Definition at line 1097 of file vcodecs.c.

struct video_codec_desc mpeg4_codec [static]

Definition at line 915 of file vcodecs.c.

struct video_codec_desc* supported_codecs[] [static]

Definition at line 1145 of file vcodecs.c.

struct _cm video_formats[] [static]

Definition at line 1120 of file vcodecs.c.


Generated on Thu Oct 11 06:37:40 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6