#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 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_frame * | create_video_frame (uint8_t *start, uint8_t *end, int format, int head, struct ast_frame *prev) |
static struct video_dec_desc * | dec_init (uint32_t the_ast_format) |
static struct video_dec_desc * | dec_uninit (struct video_dec_desc *v) |
uninitialize the descriptor for remote video stream | |
static int | fbuf_append (struct fbuf_t *b, uint8_t *src, int len, int sbit, int ebit) |
static int | ffmpeg_decode (struct video_dec_desc *v, struct fbuf_t *b) |
static int | ffmpeg_encode (struct video_out_desc *v) |
static int | h261_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h261_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h261_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h263_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h263_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h263_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h263p_decap (struct fbuf_t *b, uint8_t *data, int len) |
extract the bitstreem from the RTP payload. This is format dependent. For h263+, the format is defined in RFC 2429 and basically has a fixed 2-byte header as follows: 5 bits RR reserved, shall be 0 1 bit P indicate a start/end condition, in which case the payload should be prepended by two zero-valued bytes. 1 bit V there is an additional VRC header after this header 6 bits PLEN length in bytes of extra picture header 3 bits PEBIT how many bits to be ignored in the last byte | |
static int | h263p_enc_init (AVCodecContext *enc_ctx) |
initialization of h263p | |
static struct ast_frame * | h263p_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static int | h264_dec_init (AVCodecContext *dec_ctx) |
static int | h264_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | h264_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | h264_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
static struct video_codec_desc * | map_video_codec (int fmt) |
static enum CodecID | map_video_format (uint32_t ast_format, int rw) |
map an asterisk format into an ffmpeg one | |
static int | mpeg4_decap (struct fbuf_t *b, uint8_t *data, int len) |
static int | mpeg4_decode (struct video_dec_desc *v, struct fbuf_t *b) |
static int | mpeg4_enc_init (AVCodecContext *enc_ctx) |
static struct ast_frame * | mpeg4_encap (struct fbuf_t *b, int mtu, struct ast_frame **tail) |
Variables | |
static struct video_codec_desc | h261_codec |
static struct video_codec_desc | h263_codec |
static struct video_codec_desc | h263p_codec |
static struct video_codec_desc | h264_codec |
static struct video_codec_desc | mpeg4_codec |
static struct video_codec_desc * | supported_codecs [] |
static struct _cm | video_formats [] |
#define H261_MIN_LEN 10 |
Referenced by h261_encap().
#define H263_MIN_LEN 6 |
Referenced by h263_encap().
#define HAVE_NAL | ( | x | ) | (x[-4] == 0 && x[-3] == 0 && x[-2] == 0 && x[-1] == 1) |
Referenced by h264_encap().
#define N_DEC_IN 3 |
Definition at line 88 of file vcodecs.c.
Referenced by dec_uninit().
typedef int(* decoder_decap_f)(struct fbuf_t *b, uint8_t *data, int len) |
typedef int(* decoder_decode_f)(struct video_dec_desc *v, struct fbuf_t *b) |
typedef int(* decoder_init_f)(AVCodecContext *enc_ctx) |
typedef struct ast_frame*(* encoder_encap_f)(struct fbuf_t *, int mtu, struct ast_frame **tail) |
typedef int(* encoder_encode_f)(struct video_out_desc *v) |
typedef int(* encoder_init_f)(AVCodecContext *v) |
static struct ast_frame* create_video_frame | ( | uint8_t * | start, |
uint8_t * | end, | ||
int | format, | ||
int | head, | ||
struct ast_frame * | prev | ||
) | [static, 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.
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] |
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] |
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; }
struct video_codec_desc h261_codec [static] |
struct video_codec_desc h263_codec [static] |
struct video_codec_desc h263p_codec [static] |
struct video_codec_desc h264_codec [static] |
struct video_codec_desc mpeg4_codec [static] |
struct video_codec_desc* supported_codecs[] [static] |
struct _cm video_formats[] [static] |