[Libav-user] Converting YUV 2 MPEG4

Matthew Einhorn moiein2000 at gmail.com
Thu Aug 4 10:48:34 CEST 2011


On Thu, Aug 4, 2011 at 4:26 AM,  <muratc15-ffmpeg at yahoo.de> wrote:
> Hello Matt, Hello people,
>
> thank you for your hint. I am trying this, but I have problems creating the required paramters. Here is my code:
>
> void YUVtoRGB_Converter::YUV2MP4ES(const uint8_t *YUVbuf, uint8_t *MP4buf, int MP4bufSize)
> {
>    AVCodec *codec;
>    AVCodecContext *c= NULL;
>    //uint8_t *extradata;
>    //int extradata_size;
>    int i, out_size, size, x, y, outbuf_size;
>        AVFrame *picture;
>        uint8_t *outbuf;
>    unsigned char *picture_buf;
>
>    //printf("Video encoding\n");
>
>        av_register_all();
>
>    /* find the mpeg4 video encoder */
>        codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
>    if (!codec) {
>        fprintf(stderr, "codec not found\n");
>        exit(1);
>    }
>
>        c = avcodec_alloc_context3(codec);
>    picture= avcodec_alloc_frame();
>
>    /* put sample parameters */
>    c->bit_rate = 400000;
>    /* resolution must be a multiple of two */
>    c->width = CAM_RESOLUTION_WIDTH;
>    c->height = CAM_RESOLUTION_HEIGHT;
>    /* frames per second */
>    //c->time_base= (AVRational){1,25};
>        c->time_base.num = 1;
>        c->time_base.den = FRAMERATE;
>    c->gop_size = 10; /* emit one intra frame every ten frames */
>    c->max_b_frames=1;
>    c->pix_fmt = PIX_FMT_YUV420P;
>
>    /* open it */
>    if (avcodec_open(c, codec) < 0) {
>       fprintf(stderr, "could not open codec\n");
>        exit(1);
>        }
>        /// --> here creating the required parameters
>        AVFormatContext *t = avformat_alloc_context();
>        AVDictionary **opt = NULL; // <-- this is the problem i think
>
>        f = fopen("test", "a+b");
>        if (!f) {
>                fprintf(stderr, "could not open %s\n", "test");
>                exit(1);
>        }
>        if (this->fileExists == false) {
>                  // here throws exception
>                  // Access violation reading location from 0xAddress
>                avformat_write_header(t, opt);
>                this->fileExists = true;
>        }
> //.... and so on.
>
> How can I get the "AVDictionary **opt" parameter properly?
>
You're writing to a format context which wasn't initialized with the
file to be written. Here's my example code:

int CEncodeFile::OpenFile(const char* szFilename, const SEncodeParams*
psEncodeParams, int* pnPicSizeInFmt,
	int anLinesizes[4])
{
	if (!szFilename || !psEncodeParams || !pnPicSizeInFmt || !anLinesizes)
		return BAD_PARAMS;

	*pnPicSizeInFmt= 0;
	EnterCriticalSection(&m_rFileSafe);

	if (m_pFormatCtx)	// File was already opened
	{
		LeaveCriticalSection(&m_rFileSafe);
		return FILE_OPEN;
	}

	// Save params internally
	m_sEncodeParams= *psEncodeParams;

	/* Auto detect the output format from the filename, otherwise use
provided format. */
	avformat_alloc_output_context2(&m_pFormatCtx, NULL, NULL, szFilename);
	if (!m_pFormatCtx)
	{
		avformat_alloc_output_context2(&m_pFormatCtx, NULL,
m_sEncodeParams.szOutFormat, szFilename);
	}
	if (!m_pFormatCtx)
	{
		LeaveCriticalSection(&m_rFileSafe);
		return E_NO_OUT_FORMAT;
	}

	/* Add the video stream using the default format codecs	and
initialize the codecs. */
	if (m_pFormatCtx->oformat->video_codec == CODEC_ID_NONE) // Format
doesn't have codec
	{
		LeaveCriticalSection(&m_rFileSafe);
		return E_CODEC_NOT_FOUND;
	}
	
	// Add the video stream where we'll save the pictures
	m_pAVStream = av_new_stream(m_pFormatCtx, 0);
	if (!m_pAVStream)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return E_NO_STREAM;
	}
	
	/* Set the codec of our stream.*/
	AVCodecContext* pCodecCtx = m_pAVStream->codec;
	pCodecCtx->codec_id = m_sEncodeParams.eCodecID;
	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
	/* Save parameters */
	pCodecCtx->bit_rate = m_sEncodeParams.nBitRate;
	/* resolution must be a multiple of two */
	pCodecCtx->width = m_sEncodeParams.nWidth;
	pCodecCtx->height = m_sEncodeParams.nHeight;

	/* Time base: this is the fundamental unit of time (in seconds) in terms
		of which frame timestamps are represented. for fixed-fps content,
		timebase should be 1/framerate and timestamp increments should be
		identically 1. */
	pCodecCtx->time_base.den = m_sEncodeParams.nFRNum;
	pCodecCtx->time_base.num = m_sEncodeParams.nFRDen;
	pCodecCtx->gop_size = 12; /* emit one intra frame every twelve frames
at most */
	pCodecCtx->pix_fmt = m_sEncodeParams.ePixelFmtOut;
	pCodecCtx->max_b_frames = 1;

	// Some formats want stream headers to be separate
	if(m_pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
		pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;

	/* Find the video encoder for this stream's codec. */
	AVCodec* pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
	if (!pCodec)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return E_CODEC_NOT_FOUND;
	}

	/* Initialize the codecCtx with the codec. */
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return E_CODEC_NO_OPEN;
	}

	// Raw picture format requires no copying so no buffer.
	if (!(m_pFormatCtx->oformat->flags & AVFMT_RAWPICTURE))
	{
		// Output buffer for the video file.
		m_nBuffer= max(m_sEncodeParams.nWidth*m_sEncodeParams.nHeight*6+1664,
1024*256);
		m_auchVideoOutBuf = (unsigned char*) av_malloc(m_nBuffer);
		if (!m_auchVideoOutBuf)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return ALLOC_MEMORY_ERROR;
		}
	}

	/* Allocate the picture for the encoded pic fmt. If the in/out format
are the same, incoming pics
		are saved in here. Otherwise, it first converted to out format and
then saved here. */
	m_pAVFrame =  avcodec_alloc_frame();
	if (!m_pAVFrame)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return ALLOC_MEMORY_ERROR;
	}

	/*	See avpicture_fill, av_image_fill_pointers, avpicture_layout, and
avpicture_get_size for how
		different pixfmts are stored in the linear buffer.
		avpicture_fill will be called on the data buffer of each incoming
picture so we don't need to allocate
		a buffer for incoming pics, just the frame. */
	/* if the output format is not the same as the input, then a temporary
		picture with input format is also needed. We also need to provide a
conversion context. */
	if (pCodecCtx->pix_fmt != m_sEncodeParams.ePixelFmtIn)
	{
		/*	Now prepre the buffers that will contain the output image. If the
input and output formats are the
			same we don't do this, because we'll fill the input buffer directly
with the input images. */
		if (av_image_alloc(m_pAVFrame->data, m_pAVFrame->linesize, pCodecCtx->width,
			pCodecCtx->height, pCodecCtx->pix_fmt, 1)<0)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return ALLOC_MEMORY_ERROR;
		}

		// Frame for input image, no buffer allocation because we use input
image directly.
		m_pAVFrameTmp= avcodec_alloc_frame();
		if (!m_pAVFrameTmp)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return ALLOC_MEMORY_ERROR;
		}
		// But we still need to know the linesizes of the input image for
the conversion.
		if (av_image_fill_linesizes(m_pAVFrameTmp->linesize,
m_sEncodeParams.ePixelFmtIn, pCodecCtx->width)<0)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return LINESIZES_ERROR;
		}
		// Get the conversion context
		m_pConvertCtx = sws_getCachedContext(NULL, pCodecCtx->width,
pCodecCtx->height, m_sEncodeParams.ePixelFmtIn,
			pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
		if (!m_pConvertCtx)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return NO_CONVERT_FMT;
		}

	}
	/* Now open the output file, if needed. */
	if (!(m_pFormatCtx->oformat->flags & AVFMT_NOFILE))
	{
		if (avio_open(&m_pFormatCtx->pb, szFilename, AVIO_FLAG_WRITE) < 0)
		{
			FinishUp();
			LeaveCriticalSection(&m_rFileSafe);
			return E_CANNOT_OPEN_FILE;
		}
	}

	/* Now return the required size of the buffer of the input image.
Note, this will include
		paddding and alignment. */
	AVPicture sAVFrameDummy;
	*pnPicSizeInFmt= avpicture_fill(&sAVFrameDummy, NULL,
m_sEncodeParams.ePixelFmtIn,
		pCodecCtx->width, pCodecCtx->height);
	m_nPicSizeInFmt= *pnPicSizeInFmt;	// Save it for later use in copying image
	if (av_image_fill_linesizes(anLinesizes, m_sEncodeParams.ePixelFmtIn,
pCodecCtx->width)<0)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return LINESIZES_ERROR;
	}

	/* Write the stream header, if any */
	if (avformat_write_header(m_pFormatCtx, NULL)<0)
	{
		FinishUp();
		LeaveCriticalSection(&m_rFileSafe);
		return E_HEADER_NO_WRITE;
	}

	m_nFrame= 0;
	m_bDone= false;
	LeaveCriticalSection(&m_rFileSafe);
	return 0;
}

Matt

> Thank you in advice.
>
> Cheers
> Murat
>
>
> --- Matthew Einhorn <moiein2000 at gmail.com> schrieb am Mi, 3.8.2011:
>
>> Von: Matthew Einhorn <moiein2000 at gmail.com>
>> Betreff: Re: [Libav-user] Converting YUV 2 MPEG4
>> An: "This list is about using libavcodec, libavformat, libavutil, libavdevice and libavfilter." <libav-user at ffmpeg.org>
>> Datum: Mittwoch, 3. August, 2011 14:50 Uhr
>> On Wed, Aug 3, 2011 at 9:37 AM,
>> <muratc15-ffmpeg at yahoo.de>
>> wrote:
>> > Hello boys and girls,
>> >
>> > I want to convert a YUV signal from my POE-camera into
>> a MPEG4 stream, for which I have used the libavcodec.lib
>>  library of yours.
>> >
>> > I am confused with the file-format headers for the
>> target video file. For an instance :
>> > out_size = avcodec_encode_video(c, outbuf,
>> outbuf_size,
>> > outpic);
>> > Is there no mpeg4 specific file format header
>> required, in the beginning of the video file? Or is the
>> library function handling this internally?
>> >
>> I use avformat_write_header() before starting to write
>> frames and
>> av_write_trailer() afterwords. I think this should do what
>> you want.
>>
>> Matt
>>
>>
>> > Cheers Murat
>> >
>> > _______________________________________________
>> > Libav-user mailing list
>> > Libav-user at ffmpeg.org
>> > http://ffmpeg.org/mailman/listinfo/libav-user
>> >
>> _______________________________________________
>> Libav-user mailing list
>> Libav-user at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/libav-user
>>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>


More information about the Libav-user mailing list