Thu Apr 28 2011 17:14:03

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)    (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, 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 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, ast_frame::datalen, ast_frame::delivery, f, format, 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().

{
   int len = end-start;
   uint8_t *data;
   struct ast_frame *f;

   data = ast_calloc(1, len+head);
   f = ast_calloc(1, sizeof(*f));
   if (f == NULL || data == NULL) {
      ast_log(LOG_WARNING, "--- frame error f %p data %p len %d format %d\n",
            f, data, len, format);
      if (f)
         ast_free(f);
      if (data)
         ast_free(data);
      return NULL;
   }
   memcpy(data+head, start, len);
   f->data.ptr = data;
   f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR;
   //f->has_timing_info = 1;
   //f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
   f->datalen = len+head;
   f->frametype = AST_FRAME_VIDEO;
   f->subclass = format;
   f->samples = 0;
   f->offset = 0;
   f->src = "Console";
   f->delivery.tv_sec = 0;
   f->delivery.tv_usec = 0;
   f->seqno = 0;
   AST_LIST_NEXT(f, frame_list) = NULL;

   if (prev)
           AST_LIST_NEXT(prev, frame_list) = f;

   return f;
}
static struct video_dec_desc* dec_init ( uint32_t  the_ast_format) [static, read]

Definition at line 1199 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.

{
   enum CodecID codec;
   struct video_dec_desc *v = ast_calloc(1, sizeof(*v));
   if (v == NULL)
      return NULL;

   v->discard = 1;

   v->d_callbacks = map_video_codec(the_ast_format);
   if (v->d_callbacks == NULL) {
      ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", the_ast_format);
      return dec_uninit(v);
   }

   codec = map_video_format(v->d_callbacks->format, CM_RD);

   v->codec = avcodec_find_decoder(codec);
   if (!v->codec) {
      ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
      return dec_uninit(v);
   }
   /*
    * Initialize the codec context.
    */
   v->dec_ctx = avcodec_alloc_context();
   if (!v->dec_ctx) {
      ast_log(LOG_WARNING, "Cannot allocate the decoder context\n");
      return dec_uninit(v);
   }
   /* XXX call dec_init() ? */
   if (avcodec_open(v->dec_ctx, v->codec) < 0) {
      ast_log(LOG_WARNING, "Cannot open the decoder context\n");
      av_free(v->dec_ctx);
      v->dec_ctx = NULL;
      return dec_uninit(v);
   }

   v->parser = av_parser_init(codec);
   if (!v->parser) {
      ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n");
      return dec_uninit(v);
   }

   v->d_frame = avcodec_alloc_frame();
   if (!v->d_frame) {
      ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n");
      return dec_uninit(v);
   }
        v->dec_in_cur = &v->dec_in[0]; /* buffer for incoming frames */
        v->dec_in_dpy = NULL;      /* nothing to display */

   return v;   /* ok */
}
static struct video_dec_desc* dec_uninit ( struct video_dec_desc v) [static, read]

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().

{
   int i;

   if (v == NULL)    /* not initialized yet */
      return NULL;
   if (v->parser) {
      av_parser_close(v->parser);
      v->parser = NULL;
   }
   if (v->dec_ctx) {
      avcodec_close(v->dec_ctx);
      av_free(v->dec_ctx);
      v->dec_ctx = NULL;
   }
   if (v->d_frame) {
      av_free(v->d_frame);
      v->d_frame = NULL;
   }
   v->codec = NULL;  /* only a reference */
   v->d_callbacks = NULL;     /* forget the decoder */
   v->discard = 1;      /* start in discard mode */
   for (i = 0; i < N_DEC_IN; i++)
      fbuf_free(&v->dec_in[i]);
   fbuf_free(&v->dec_out);
   ast_free(v);
   return NULL;   /* error, in case someone cares */
}
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, len(), LOG_WARNING, fbuf_t::size, and fbuf_t::used.

Referenced by h261_decap(), h263_decap(), h263p_decap(), h264_decap(), and mpeg4_decap().

{
   /*
    * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE,
    * and also wants 0 as a buffer terminator to prevent trouble.
    */
   int need = len + FF_INPUT_BUFFER_PADDING_SIZE;
   int i;
   uint8_t *dst, mask;

   if (b->data == NULL) {
      b->size = need;
      b->used = 0;
      b->ebit = 0;
      b->data = ast_calloc(1, b->size);
   } else if (b->used + need > b->size) {
      b->size = b->used + need;
      b->data = ast_realloc(b->data, b->size);
   }
   if (b->data == NULL) {
      ast_log(LOG_WARNING, "alloc failure for %d, discard\n",
         b->size);
      return 1;
   }
   if (b->used == 0 && b->ebit != 0) {
      ast_log(LOG_WARNING, "ebit not reset at start\n");
      b->ebit = 0;
   }
   dst = b->data + b->used;
   i = b->ebit + sbit;  /* bits to ignore around */
   if (i == 0) {  /* easy case, just append */
      /* do everything in the common block */
   } else if (i == 8) { /* easy too, just handle the overlap byte */
      mask = (1 << b->ebit) - 1;
      /* update the last byte in the buffer */
      dst[-1] &= ~mask; /* clear bits to ignore */
      dst[-1] |= (*src & mask);  /* append new bits */
      src += 1;   /* skip and prepare for common block */
      len --;
   } else { /* must shift the new block, not done yet */
      ast_log(LOG_WARNING, "must handle shift %d %d at %d\n",
         b->ebit, sbit, b->used);
      return 1;
   }
   memcpy(dst, src, len);
   b->used += len;
   b->ebit = ebit;
   b->data[b->used] = 0;   /* padding */
   return 0;
}
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.

{
   uint8_t *src = b->data;
   int srclen = b->used;
   int full_frame = 0;

   if (srclen == 0)  /* no data */
      return 0;
   while (srclen) {
      uint8_t *data;
      int datalen, ret;
      int len = av_parser_parse(v->parser, v->dec_ctx, &data, &datalen, src, srclen, 0, 0);

      src += len;
      srclen -= len;
      /* The parser might return something it cannot decode, so it skips
       * the block returning no data
       */
      if (data == NULL || datalen == 0)
         continue;
      ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame, data, datalen);
      if (full_frame == 1) /* full frame */
         break;
      if (ret < 0) {
         ast_log(LOG_NOTICE, "Error decoding\n");
         break;
      }
   }
   if (srclen != 0)  /* update b with leftover data */
      memmove(b->data, src, srclen);
   b->used = srclen;
   b->ebit = 0;
   return full_frame;
}
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.

{
   struct fbuf_t *b = &v->enc_out;
   int i;

   b->used = avcodec_encode_video(v->enc_ctx, b->data, b->size, v->enc_in_frame);
   i = avcodec_encode_video(v->enc_ctx, b->data + b->used, b->size - b->used, NULL); /* delayed frames ? */
   if (i > 0) {
      ast_log(LOG_WARNING, "have %d more bytes\n", i);
      b->used += i;
   }
   return 0;
}
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.

{
   int ebit, sbit;

   if (len < 8) {
      ast_log(LOG_WARNING, "invalid framesize %d\n", len);
      return 1;
   }
   sbit = (data[0] >> 5) & 7;
   ebit = (data[0] >> 2) & 7;
   len -= 4;
   data += 4;
   return fbuf_append(b, data, len, sbit, ebit);
}
static int h261_enc_init ( AVCodecContext *  enc_ctx) [static]

Definition at line 698 of file vcodecs.c.

{
   /* It is important to set rtp_payload_size = 0, otherwise
    * ffmpeg in h261 mode will produce output that it cannot parse.
    * Also try to send I frames more frequently than with other codecs.
    */
   enc_ctx->rtp_payload_size = 0; /* important - ffmpeg fails otherwise */

   return 0;
}
static struct ast_frame* h261_encap ( struct fbuf_t b,
int  mtu,
struct ast_frame **  tail 
) [static, read]

Definition at line 725 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.

{
   uint8_t *d = b->data;
   int start = 0, i, len = b->used;
   struct ast_frame *f, *cur = NULL, *first = NULL;
   const int pheader_len = 4;
   uint8_t h261_hdr[4];
   uint8_t *h = h261_hdr;  /* shorthand */
   int sbit = 0, ebit = 0;

#define H261_MIN_LEN 10
   if (len < H261_MIN_LEN) /* unreasonably small */
      return NULL;

   memset(h261_hdr, '\0', sizeof(h261_hdr));

   /* Similar to the code in h263_encap, but the marker there is longer.
    * Start a few bytes within the bitstream to avoid hitting the marker
    * twice. Note we might access the buffer at len, but this is ok because
    * the caller has it oversized.
    */
   for (i = H261_MIN_LEN, start = 0; start < len - 1; start = i, i += 4) {
#if 0 /* test - disable packetization */
      i = len; /* wrong... */
#else
      int found = 0, found_ebit = 0;   /* last GBSC position found */
      for (; i < len ; i++) {
         uint8_t x, rpos, lpos;
         if (d[i] != 0)    /* cannot be in a GBSC */
            continue;
         x = d[i+1];
         if (x == 0) /* next is equally good */
            continue;
         /* See if around us we find 15 '0' bits for the GBSC.
          * Look for the first bit set on the right, and then
          * see if we have enough 0 on the left.
          * We are guaranteed to end before rpos == 0
          */
         for (rpos = 0x80, ebit = 7; rpos; ebit--, rpos >>= 1)
            if (x & rpos)  /* found the '1' bit in GBSC */
               break;
         x = d[i-1];    /* now look behind */
         for (lpos = (rpos >> 1); lpos ; lpos >>= 1)
            if (x & lpos)  /* too early, not a GBSC */
               break;
         if (lpos)      /* as i said... */
            continue;
         /* now we have a GBSC starting somewhere in d[i-1],
          * but it might be not byte-aligned. Just remember it.
          */
         if (i - start > mtu) /* too large, stop now */
            break;
         found_ebit = ebit;
         found = i;
         i += 4;  /* continue forward */
      }
      if (i >= len) {   /* trim if we went too forward */
         i = len;
         ebit = 0;   /* hopefully... should ask the bitstream ? */
      }
      if (i - start > mtu && found) {
         /* use the previous GBSC, hope is within the mtu */
         i = found;
         ebit = found_ebit;
      }
#endif /* test */
      if (i - start < 4)   /* XXX too short ? */
         continue;
      /* This frame is up to offset i (not inclusive).
       * We do not split it yet even if larger than MTU.
       */
      f = create_video_frame(d + start, d+i, AST_FORMAT_H261,
            pheader_len, cur);

      if (!f)
         break;
      /* recompute header with I=0, V=1 */
      h[0] = ( (sbit & 7) << 5 ) | ( (ebit & 7) << 2 ) | 1;
      memmove(f->data.ptr, h, 4);   /* copy the h261 header */
      if (ebit)   /* not aligned, restart from previous byte */
         i--;
      sbit = (8 - ebit) & 7;
      ebit = 0;
      if (!cur)
         first = f;
      cur = f;
   }
   if (cur)
      cur->subclass |= 1;  // RTP Marker

   *tail = cur;
   return first;
}
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.

{
   if (len < 4) {
      ast_log(LOG_WARNING, "invalid framesize %d\n", len);
      return 1;   /* error */
   }

   if ( (data[0] & 0x80) == 0) {
      len -= 4;
      data += 4;
   } else {
      ast_log(LOG_WARNING, "unsupported mode 0x%x\n",
         data[0]);
      return 1;
   }
   return fbuf_append(b, data, len, 0, 0);   /* XXX no bit alignment support yet */
}
static int h263_enc_init ( AVCodecContext *  enc_ctx) [static]

Definition at line 526 of file vcodecs.c.

{
   /* XXX check whether these are supported */
   enc_ctx->flags |= CODEC_FLAG_H263P_UMV;
   enc_ctx->flags |= CODEC_FLAG_H263P_AIC;
   enc_ctx->flags |= CODEC_FLAG_H263P_SLICE_STRUCT;
   enc_ctx->flags |= CODEC_FLAG_AC_PRED;

   return 0;
}
static struct ast_frame* h263_encap ( struct fbuf_t b,
int  mtu,
struct ast_frame **  tail 
) [static, read]

Definition at line 571 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.

{
   uint8_t *d = b->data;
   int start = 0, i, len = b->used;
   struct ast_frame *f, *cur = NULL, *first = NULL;
   const int pheader_len = 4; /* Use RFC-2190 Mode A */
   uint8_t h263_hdr[12];   /* worst case, room for a type c header */
   uint8_t *h = h263_hdr;  /* shorthand */

#define H263_MIN_LEN 6
   if (len < H263_MIN_LEN) /* unreasonably small */
      return NULL;

   memset(h263_hdr, '\0', sizeof(h263_hdr));
   /* Now set the header bytes. Only type A by now,
    * and h[0] = h[2] = h[3] = 0 by default.
    * PTYPE starts 30 bits in the picture, so the first useful
    * bit for us is bit 36 i.e. within d[4] (0 is the msbit).
    * SRC = d[4] & 0x1c goes into data[1] & 0xe0
    * I   = d[4] & 0x02 goes into data[1] & 0x10
    * U   = d[4] & 0x01 goes into data[1] & 0x08
    * S   = d[5] & 0x80 goes into data[1] & 0x04
    * A   = d[5] & 0x40 goes into data[1] & 0x02
    * R   = 0           goes into data[1] & 0x01
    * Optimizing it, we have
    */
   h[1] = ( (d[4] & 0x1f) << 3 ) |  /* SRC, I, U */
      ( (d[5] & 0xc0) >> 5 );    /* S, A, R */

   /* now look for the next PSC or GOB header. First try to hit
    * a '0' byte then look around for the 0000 0000 0000 0000 1 pattern
    * which is both in the PSC and the GBSC.
    */
   for (i = H263_MIN_LEN, start = 0; start < len; start = i, i += 3) {
      //ast_log(LOG_WARNING, "search at %d of %d/%d\n", i, start, len);
      for (; i < len ; i++) {
         uint8_t x, rpos, lpos;
         int rpos_i; /* index corresponding to rpos */
         if (d[i] != 0)    /* cannot be in a GBSC */
            continue;
         if (i > len - 1)
            break;
         x = d[i+1];
         if (x == 0) /* next is equally good */
            continue;
         /* see if around us we can make 16 '0' bits for the GBSC.
          * Look for the first bit set on the right, and then
          * see if we have enough 0 on the left.
          * We are guaranteed to end before rpos == 0
          */
         for (rpos = 0x80, rpos_i = 8; rpos; rpos >>= 1, rpos_i--)
            if (x & rpos)  /* found the '1' bit in GBSC */
               break;
         x = d[i-1];    /* now look behind */
         for (lpos = rpos; lpos ; lpos >>= 1)
            if (x & lpos)  /* too early, not a GBSC */
               break;
         if (lpos)      /* as i said... */
            continue;
         /* now we have a GBSC starting somewhere in d[i-1],
          * but it might be not byte-aligned
          */
         if (rpos == 0x80) {  /* lucky case */
            i = i - 1;
         } else { /* XXX to be completed */
            ast_log(LOG_WARNING, "unaligned GBSC 0x%x %d\n",
               rpos, rpos_i);
         }
         break;
      }
      /* This frame is up to offset i (not inclusive).
       * We do not split it yet even if larger than MTU.
       */
      f = create_video_frame(d + start, d+i, AST_FORMAT_H263,
            pheader_len, cur);

      if (!f)
         break;
      memmove(f->data.ptr, h, 4);   /* copy the h263 header */
      /* XXX to do: if not aligned, fix sbit and ebit,
       * then move i back by 1 for the next frame
       */
      if (!cur)
         first = f;
      cur = f;
   }

   if (cur)
      cur->subclass |= 1;  // RTP Marker

   *tail = cur;
   return first;
}
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.

{
   int PLEN;

   if (len < 2) {
      ast_log(LOG_WARNING, "invalid framesize %d\n", len);
      return 1;
   }
   PLEN = ( (data[0] & 1) << 5 ) | ( (data[1] & 0xf8) >> 3);

   if (PLEN > 0) {
      data += PLEN;
      len -= PLEN;
   }
   if (data[0] & 4)  /* bit P */
      data[0] = data[1] = 0;
   else {
      data += 2;
      len -= 2;
   }
   return fbuf_append(b, data, len, 0, 0);   /* ignore trail bits */
}
static int h263p_enc_init ( AVCodecContext *  enc_ctx) [static]

initialization of h263p

Definition at line 331 of file vcodecs.c.

{
   /* modes supported are
   - Unrestricted Motion Vector (annex D)
   - Advanced Prediction (annex F)
   - Advanced Intra Coding (annex I)
   - Deblocking Filter (annex J)
   - Slice Structure (annex K)
   - Alternative Inter VLC (annex S)
   - Modified Quantization (annex T)
   */
   enc_ctx->flags |=CODEC_FLAG_H263P_UMV; /* annex D */
   enc_ctx->flags |=CODEC_FLAG_AC_PRED; /* annex f ? */
   enc_ctx->flags |=CODEC_FLAG_H263P_SLICE_STRUCT; /* annex k */
   enc_ctx->flags |= CODEC_FLAG_H263P_AIC; /* annex I */

   return 0;
}
static struct ast_frame* h263p_encap ( struct fbuf_t b,
int  mtu,
struct ast_frame **  tail 
) [static, read]

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::ptr, ast_frame::subclass, and fbuf_t::used.

{
   struct ast_frame *cur = NULL, *first = NULL;
   uint8_t *d = b->data;
   int len = b->used;
   int l = len; /* size of the current fragment. If 0, must look for a psc */

   for (;len > 0; len -= l, d += l) {
      uint8_t *data;
      struct ast_frame *f;
      int i, h;

      if (len >= 3 && d[0] == 0 && d[1] == 0 && d[2] >= 0x80) {
         /* we are starting a new block, so look for a PSC. */
         for (i = 3; i < len - 3; i++) {
            if (d[i] == 0 && d[i+1] == 0 && d[i+2] >= 0x80) {
               l = i;
               break;
            }
         }
      }
      if (l > mtu || l > len) { /* psc not found, split */
         l = MIN(len, mtu);
      }
      if (l < 1 || l > mtu) {
         ast_log(LOG_WARNING, "--- frame error l %d\n", l);
         break;
      }
      
      if (d[0] == 0 && d[1] == 0) { /* we start with a psc */
         h = 0;
      } else { /* no psc, create a header */
         h = 2;
      }

      f = create_video_frame(d, d+l, AST_FORMAT_H263_PLUS, h, cur);
      if (!f)
         break;

      data = f->data.ptr;
      if (h == 0) {  /* we start with a psc */
         data[0] |= 0x04;  // set P == 1, and we are done
      } else { /* no psc, create a header */
         data[0] = data[1] = 0;  // P == 0
      }

      if (!cur)
         first = f;
      cur = f;
   }

   if (cur)
      cur->subclass |= 1; // RTP Marker

   *tail = cur;   /* end of the list */
   return first;
}
static int h264_dec_init ( AVCodecContext *  dec_ctx) [static]

Definition at line 934 of file vcodecs.c.

{
   dec_ctx->flags |= CODEC_FLAG_TRUNCATED;

   return 0;
}
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.

{
   /* Start Code Prefix (Annex B in specification) */
   uint8_t scp[] = { 0x00, 0x00, 0x00, 0x01 };
   int retval = 0;
   int type, ofs = 0;

   if (len < 2) {
      ast_log(LOG_WARNING, "--- invalid len %d\n", len);
      return 1;
   }
   /* first of all, check if the packet has F == 0 */
   if (data[0] & 0x80) {
      ast_log(LOG_WARNING, "--- forbidden packet; nal: %02x\n",
         data[0]);
      return 1;
   }

   type = data[0] & 0x1f;
   switch (type) {
   case 0:
   case 31:
      ast_log(LOG_WARNING, "--- invalid type: %d\n", type);
      return 1;
   case 24:
   case 25:
   case 26:
   case 27:
   case 29:
      ast_log(LOG_WARNING, "--- encapsulation not supported : %d\n", type);
      return 1;
   case 28: /* FU-A Unit */
      if (data[1] & 0x80) { // S == 1, import F and NRI from next
         data[1] &= 0x1f;  /* preserve type */
         data[1] |= (data[0] & 0xe0);  /* import F & NRI */
         retval = fbuf_append(b, scp, sizeof(scp), 0, 0);
         ofs = 1;
      } else {
         ofs = 2;
      }
      break;
   default: /* From 1 to 23 (Single NAL Unit) */
      retval = fbuf_append(b, scp, sizeof(scp), 0, 0);
   }
   if (!retval)
      retval = fbuf_append(b, data + ofs, len - ofs, 0, 0);
   if (retval)
      ast_log(LOG_WARNING, "result %d\n", retval);
   return retval;
}
static int h264_enc_init ( AVCodecContext *  enc_ctx) [static]

Definition at line 922 of file vcodecs.c.

{
   enc_ctx->flags |= CODEC_FLAG_TRUNCATED;
   //enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
   //enc_ctx->flags2 |= CODEC_FLAG2_FASTPSKIP;
   /* TODO: Maybe we need to add some other flags */
   enc_ctx->rtp_mode = 0;
   enc_ctx->rtp_payload_size = 0;
   enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate;
   return 0;
}
static struct ast_frame* h264_encap ( struct fbuf_t b,
int  mtu,
struct ast_frame **  tail 
) [static, read]

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, ast_frame::ptr, and fbuf_t::used.

{
   struct ast_frame *f = NULL, *cur = NULL, *first = NULL;
   uint8_t *d, *start = b->data;
   uint8_t *end = start + b->used;

   /* Search the first start code prefix - ITU-T H.264 sec. B.2,
    * and move start right after that, on the NAL header byte.
    */
#define HAVE_NAL(x) (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1)
   for (start += 4; start < end; start++) {
      int ty = start[0] & 0x1f;
      if (HAVE_NAL(start) && ty != 0 && ty != 31)
         break;
   }
   /* if not found, or too short, we just skip the next loop and are done. */

   /* Here follows the main loop to create frames. Search subsequent start
    * codes, and then possibly fragment the unit into smaller fragments.
    */
   for (;start < end - 4; start = d) {
   int size;      /* size of current block */
   uint8_t hdr[2];      /* add-on header when fragmenting */
   int ty = 0;

   /* now search next nal */
   for (d = start + 4; d < end; d++) {
      ty = d[0] & 0x1f;
      if (HAVE_NAL(d))
         break;   /* found NAL */
   }
   /* have a block to send. d past the start code unless we overflow */
   if (d >= end) {   /* NAL not found */
      d = end + 4;
   } else if (ty == 0 || ty == 31) { /* found but invalid type, skip */
      ast_log(LOG_WARNING, "skip invalid nal type %d at %d of %d\n",
         ty, d - (uint8_t *)b->data, b->used);
      continue;
   }

   size = d - start - 4;   /* don't count the end */

   if (size < mtu) { // test - don't fragment
      // Single NAL Unit
      f = create_video_frame(start, d - 4, AST_FORMAT_H264, 0, cur);
      if (!f)
         break;
      if (!first)
         first = f;

      cur = f;
      continue;
   }

   // Fragmented Unit (Mode A: no DON, very weak)
   hdr[0] = (*start & 0xe0) | 28;   /* mark as a fragmentation unit */
   hdr[1] = (*start++ & 0x1f) | 0x80 ; /* keep type and set START bit */
   size--;     /* skip the NAL header */
   while (size) {
      uint8_t *data;
      int frag_size = MIN(size, mtu);

      f = create_video_frame(start, start+frag_size, AST_FORMAT_H264, 2, cur);
      if (!f)
         break;
      size -= frag_size;   /* skip this data block */
      start += frag_size;

      data = f->data.ptr;
      data[0] = hdr[0];
      data[1] = hdr[1] | (size == 0 ? 0x40 : 0);   /* end bit if we are done */
      hdr[1] &= ~0x80;  /* clear start bit for subsequent frames */
      if (!first)
         first = f;
      cur = f;
   }
    }

   if (cur)
      cur->subclass |= 1;     // RTP Marker

   *tail = cur;

   return first;
}
static struct video_codec_desc* map_video_codec ( int  fmt) [static, read]

Definition at line 1153 of file vcodecs.c.

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

Referenced by dec_init().

{
   int i;

   for (i = 0; supported_codecs[i]; i++)
      if (fmt == supported_codecs[i]->format) {
         ast_log(LOG_WARNING, "using %s for format 0x%x\n",
            supported_codecs[i]->name, fmt);
         return supported_codecs[i];
      }
   return NULL;
}
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, and _cm::rw.

Referenced by dec_init().

{
   struct _cm *i;

   for (i = video_formats; i->ast_format != 0; i++)
      if (ast_format & i->ast_format && rw & i->rw && rw & i->rw)
         return i->codec;
   return CODEC_ID_NONE;
}
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().

{
   return fbuf_append(b, data, len, 0, 0);
}
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.

{
   int full_frame = 0, datalen = b->used;
   int ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame,
      b->data, datalen);
   if (ret < 0) {
      ast_log(LOG_NOTICE, "Error decoding\n");
      ret = datalen; /* assume we used everything. */
   }
   datalen -= ret;
   if (datalen > 0)  /* update b with leftover bytes */
      memmove(b->data, b->data + ret, datalen);
   b->used = datalen;
   b->ebit = 0;
   return full_frame;
}
static int mpeg4_enc_init ( AVCodecContext *  enc_ctx) [static]

Definition at line 850 of file vcodecs.c.

{
#if 0
   //enc_ctx->flags |= CODEC_FLAG_LOW_DELAY; /*don't use b frames ?*/
   enc_ctx->flags |= CODEC_FLAG_AC_PRED;
   enc_ctx->flags |= CODEC_FLAG_H263P_UMV;
   enc_ctx->flags |= CODEC_FLAG_QPEL;
   enc_ctx->flags |= CODEC_FLAG_4MV;
   enc_ctx->flags |= CODEC_FLAG_GMC;
   enc_ctx->flags |= CODEC_FLAG_LOOP_FILTER;
   enc_ctx->flags |= CODEC_FLAG_H263P_SLICE_STRUCT;
#endif
   enc_ctx->rtp_payload_size = 0; /* important - ffmpeg fails otherwise */
   return 0;
}
static struct ast_frame* mpeg4_encap ( struct fbuf_t b,
int  mtu,
struct ast_frame **  tail 
) [static, read]

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.

{
   struct ast_frame *f, *cur = NULL, *first = NULL;
   uint8_t *d = b->data;
   uint8_t *end = d + b->used;
   int len;

   for (;d < end; d += len, cur = f) {
      len = MIN(mtu, end - d);
      f = create_video_frame(d, d + len, AST_FORMAT_MP4_VIDEO, 0, cur);
      if (!f)
         break;
      if (!first)
         first = f;
   }
   if (cur)
      cur->subclass |= 1;
   *tail = cur;
   return first;
}

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.

struct _cm video_formats[] [static]

Definition at line 1116 of file vcodecs.c.