Mon Mar 19 11:30:56 2012

Asterisk developer's documentation


vcodecs.c File Reference

#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_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 88 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 50 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 53 of file vcodecs.c.

typedef int(*) decoder_init_f(AVCodecContext *enc_ctx)

inizialize the decoder

Definition at line 45 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 41 of file vcodecs.c.

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

actually call the encoder

Definition at line 38 of file vcodecs.c.

typedef int(*) encoder_init_f(AVCodecContext *v)

initialize the encoder

Definition at line 35 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]

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, 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.ptr = 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.ptr;
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]

Definition at line 934 of file vcodecs.c.

00935 {
00936    dec_ctx->flags |= CODEC_FLAG_TRUNCATED;
00937 
00938    return 0;
00939 }

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.ptr;
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 }


Variable Documentation

struct video_codec_desc h261_codec [static]

Definition at line 838 of file vcodecs.c.

struct video_codec_desc h263_codec [static]

Definition at line 685 of file vcodecs.c.

struct video_codec_desc h263p_codec [static]

Definition at line 513 of file vcodecs.c.

struct video_codec_desc h264_codec [static]

Definition at line 1093 of file vcodecs.c.

struct video_codec_desc mpeg4_codec [static]

Definition at line 911 of file vcodecs.c.

struct video_codec_desc* supported_codecs[] [static]

Definition at line 1140 of file vcodecs.c.

Referenced by map_video_codec().

struct _cm video_formats[] [static]

Definition at line 1116 of file vcodecs.c.

Referenced by map_video_format().


Generated on Mon Mar 19 11:30:56 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7