[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