various rearrangements and renaming of console_video stuff

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@95262 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Luigi Rizzo
2007-12-28 22:37:40 +00:00
parent c540b02f6f
commit 14c09c5bea
4 changed files with 230 additions and 212 deletions

View File

@@ -8,7 +8,7 @@
#include "asterisk/frame.h"
struct video_out_desc;
struct video_in_desc;
struct video_dec_desc;
struct fbuf_t;
/*
@@ -34,7 +34,7 @@ typedef int (*decoder_init_f)(AVCodecContext *enc_ctx);
typedef int (*decoder_decap_f)(struct fbuf_t *b, uint8_t *data, int len);
/*! \brief actually call the decoder */
typedef int (*decoder_decode_f)(struct video_in_desc *v, struct fbuf_t *b);
typedef int (*decoder_decode_f)(struct video_dec_desc *v, struct fbuf_t *b);
struct video_codec_desc {
const char *name; /* format name */
@@ -47,6 +47,35 @@ struct video_codec_desc {
decoder_decode_f dec_run;
};
/*
* Descriptor for the incoming stream, with multiple buffers for the bitstream
* extracted from the RTP packets, RTP reassembly info, and a frame buffer
* for the decoded frame (buf).
* The descriptor is allocated as the first frame comes in.
*
* Incoming payload is stored in one of the dec_in[] buffers, which are
* emptied by the video thread. These buffers are organized in a circular
* queue, with dec_in_cur being the buffer in use by the incoming stream,
* and dec_in_dpy is the one being displayed. When the pointers need to
* be changed, we synchronize the access to them with dec_lock.
* When the list is full dec_in_cur = NULL (we cannot store new data),
* when the list is empty dec_in_dpy = NULL (we cannot display frames).
*/
struct video_dec_desc {
struct video_codec_desc *d_callbacks; /* decoder callbacks */
AVCodecContext *dec_ctx; /* information about the codec in the stream */
AVCodec *codec; /* reference to the codec */
AVFrame *d_frame; /* place to store the decoded frame */
AVCodecParserContext *parser;
uint16_t next_seq; /* must be 16 bit */
int discard; /* flag for discard status */
#define N_DEC_IN 3 /* number of incoming buffers */
struct fbuf_t *dec_in_cur; /* buffer being filled in */
struct fbuf_t *dec_in_dpy; /* buffer to display */
struct fbuf_t dec_in[N_DEC_IN]; /* incoming bitstream, allocated/extended in fbuf_append() */
struct fbuf_t dec_out; /* decoded frame, no buffer (data is in AVFrame) */
};
#ifdef debugging_only
/* some debugging code to check the bitstream:
@@ -170,6 +199,8 @@ void dump_buf(struct fbuf_t *b)
ast_log(LOG_WARNING, "%s\n", buf);
}
#endif /* debugging_only */
/*
* Here starts the glue code for the various supported video codecs.
* For each of them, we need to provide routines for initialization,
@@ -327,7 +358,7 @@ static int ffmpeg_encode(struct video_out_desc *v)
* proper frames. After that, if we have a valid frame, we decode it
* until the entire frame is processed.
*/
static int ffmpeg_decode(struct video_in_desc *v, struct fbuf_t *b)
static int ffmpeg_decode(struct video_dec_desc *v, struct fbuf_t *b)
{
uint8_t *src = b->data;
int srclen = b->used;
@@ -743,7 +774,7 @@ static int mpeg4_decap(struct fbuf_t *b, uint8_t *data, int len)
return fbuf_append(b, data, len, 0, 0);
}
static int mpeg4_decode(struct video_in_desc *v, struct fbuf_t *b)
static int mpeg4_decode(struct video_dec_desc *v, struct fbuf_t *b)
{
int full_frame = 0, datalen = b->used;
int ret = avcodec_decode_video(v->dec_ctx, v->d_frame, &full_frame,
@@ -1015,4 +1046,89 @@ static struct video_codec_desc *map_video_codec(int fmt)
return NULL;
}
/*! \brief uninitialize the descriptor for remote video stream */
static struct video_dec_desc *dec_uninit(struct video_dec_desc *v)
{
int i;
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 */
}
/*
* initialize ffmpeg resources used for decoding frames from the network.
*/
static struct video_dec_desc *dec_init(uint32_t the_ast_format)
{
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 */
}
/*------ end codec specific code -----*/