[Libav-user] Muxing MPEG-4 motion imagery into a MPEG-2 Transport Stream
Mark Fonnemann
markf78 at yahoo.com
Wed Jul 20 02:05:58 CEST 2011
Hello-
I am modifying an existing program that currently takes RGB imagery, converts to YUV420P, encodes into MPEG-4, and then writes the raw output buffer to a file. this code works correctly.
however, requirements have changed and now i must take this same single imagery stream, still convert to YUV420P, still encode to mpeg-4, but now mux into a mpeg-2 TS. i cannot find any examples online of how to do this with libav. all the examples in the doc/examples directory are writing to a file on disk where as i only need to keep the TS packets in memory until i send them out via UDP. any help would be greatly appreciated.
mark.
here's some sample code of what i have currently (not optimized by any means!):
<pre>
public init()
{
int framewidth = (*mFrameQueue)[0]->getIplImage()->width;
int frameheight = (*mFrameQueue)[0]->getIplImage()->height;
video_outbuf_size = 2000000;
video_outbuf = (uint8_t *) malloc(video_outbuf_size);
oc = av_alloc_format_context();
if(!oc)
{
// error handling
}
oc->oformat = guess_format("mp4",NULL,NULL);
st = av_new_stream(oc, 0);
if (!st)
{
// error handling
}
c = st->codec;
c->codec_type = CODEC_TYPE_VIDEO;
c->codec_id = CODEC_ID_MPEG4;
/* put sample parameters */
c->global_quality = FF_QP2LAMBDA;
c->bit_rate = 200000;
/* resolution must be a multiple of two */
c->width = framewidth;
c->height = frameheight;
/* frames per second */
c->time_base.den = 25;
c->time_base.num = 1;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = PIX_FMT_YUV420P;
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
c->flags |= CODEC_FLAG_QSCALE;
c->max_b_frames = 0;
if(av_set_parameters(oc, NULL) < 0)
{
// error handling
}
codec = avcodec_find_encoder(c->codec_id);
int result = avcodec_open(c, codec);
if (result < 0)
{
// error handling
}
}
void doGetNextFrame()
{
AVFrame *tmp_picture;
tmp_picture = avcodec_alloc_frame();
unsigned int size = avpicture_get_size(c->pix_fmt, c->width, c->height);
uint8_t *picture_buf = (uint8_t *) malloc(size);
int fillres = avpicture_fill((AVPicture *)tmp_picture, picture_buf, c->pix_fmt, c->width, c->height);
int out_size = 0;
// scale the image... omitted the doSwsConvert function which
// simply does a sws_convert
bool success = doSwsConvert(dst_picture, (*mFrameQueue)[0]->getIplImage(), c->pix_fmt);
dst_picture->quality = FF_QP2LAMBDA;
// returns a negative value on error
out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, dst_picture);
// write to a destination buffer fTo which is written to a file
memcpy(fTo, video_outbuf, out_size);
av_free(tmp_picture);
delete[] picture_buf;
}
</pre>
More information about the Libav-user
mailing list