[Libav-user] get RGB values from ffmpeg frame

Malik Cissé mc at enciris.com
Tue Nov 20 10:06:31 CET 2012


Hi Navin,

You don't need RGB for bitmap. AFAIK BMP pictures can also embed YUV4:2:0
Here is a h264 decoding code that works fine. It may help you extracting the right parts.




//#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "avcodec/avcodec.h"

static int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
  int info;
  int i;

  info = 1;
  for (i = 0; i < zeros_in_startcode; i++)
    if(Buf[i] != 0)
      info = 0;

  if(Buf[i] != 1)
    info = 0;
  return info;
}

int getNextNal(FILE* inpf, unsigned char* Buf)
{
	int pos = 0;
	while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);

	int StartCodeFound = 0;
	int info2 = 0;
	int info3 = 0;

	while (!StartCodeFound)
	{
		if (feof (inpf))
		{
			return -1;
		}
		Buf[pos++] = fgetc (inpf);
		info3 = FindStartCode(&Buf[pos-4], 3);
		if(info3 != 1)
			info2 = FindStartCode(&Buf[pos-3], 2);
		StartCodeFound = (info2 == 1 || info3 == 1);
	}
	fseek (inpf, -4, SEEK_CUR);
	return pos - 4;
}

int main()
{
	int i;
	FILE * inpf;
	FILE * outf;
	inpf = fopen("test.264", "rb");
	outf = fopen("out1_720x576.yuv", "wb");
	int nalLen = 0;
	unsigned char* Buf = (unsigned char*)calloc ( 1000000, sizeof(char));
	unsigned char* Buf1 = (unsigned char*)calloc ( 1000000, sizeof(char));
	int width = 720;
	int height = 576;
	//unsigned char yuvData[352 * 240 * 3];


	AVCodec *codec;			  // Codec
    AVCodecContext *c;		  // Codec Context
    AVFrame *picture;		  // Frame	

	avcodec_init(); 
	avcodec_register_all(); 
	codec = avcodec_find_decoder(CODEC_ID_H264);

	if (!codec)  {
		return 0; 
	} 
		//allocate codec context
    c = avcodec_alloc_context(); 
	if(!c){
		return 0;
	}
	//open codec
    if (avcodec_open(c, codec) < 0) {
		return 0; 
	} 

	//allocate frame buffer
    picture   = avcodec_alloc_frame();
	if(!picture){
		return 0;
	}

	while(!feof(inpf))
	{
		//printf("cntr: %d\n", cntr++);
		nalLen = getNextNal(inpf, Buf);

		//try to decode this frame
		int  got_picture, result; 
		result= avcodec_decode_video(c, picture, &got_picture, Buf, nalLen); 
		if(result > 0)
		{
			//fwrite(picture->data[0],1,width*height,outf);
			//fwrite(picture->data[1],1,width*height/4,outf);
			//fwrite(picture->data[2],1,width*height/4,outf);
			
#if 0 //this is also ok!
			for(i=0; i<c->height; i++)
				fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf );
			for(i=0; i<c->height/2; i++)
				fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf );
			for(i=0; i<c->height/2; i++)
				fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf );
#endif 

			//http://ffmpeg.org/doxygen/trunk/group__lavc__picture.html#g99bc554a84681f7ee6422a384007a4ca
			//Copy pixel data from an AVPicture into a buffer, always assume a linesize alignment of 1.
			avpicture_layout((AVPicture *)picture, c->pix_fmt, c->width, c->height, Buf1, c->width*c->height*1.5);
			fwrite(Buf1, c->width*c->height*1.5, 1, outf);
				
		}
	}
	
	if(c) {
		avcodec_close(c); 
		av_free(c);
		c = NULL;
	} 
	if(picture) {
		av_free(picture);
		picture = NULL;
	} 
	return 1;
}
Malik,


-----Original Message-----
From: libav-user-bounces at ffmpeg.org [mailto:libav-user-bounces at ffmpeg.org] On Behalf Of Navin
Sent: 20 November 2012 09:49
To: libav-user at ffmpeg.org
Subject: Re: [Libav-user] get RGB values from ffmpeg frame

Been trying these techniques, but I keep getting crashes. Help please?:

         avpicture_fill((AVPicture*) frame2, frame2_buffer, PIX_FMT_RGB24, width2, height2);
         //printf("data = %d, %d, %d, %d \n",frame2->data[0],frame2->data[1],frame2->data[2],frame2->data[3]);
         //printf("linesize = %d %d %d\n",frame2->linesize[0], 
frame2->linesize[1], frame2->linesize[2]);
         //printf("width = %d\n", pCodecCtx->width);
         //printf("height = %d\n", pCodecCtx->height);
         //std::cin.get();

         int linesize = frame2->linesize[0];
         for(int xx = 0; xx < (linesize * width1)-1; xx += 3)
         {
             int r = frame2->data[0][xx];//int r = frame2->data[0][xx];
             int g = frame2->data[0][xx+1];
             int b = frame2->data[0][xx+2];
             printf("xx=%d                 r=%d, g=%d, b=%d \n",xx, r, 
g, b);
         }
         printf("frame%d done----------------",i++);
         //for(int xx = 0; xx < width1; xx = xx + 3)
         //{
         //    for(int yy = 0; yy < height1; ++yy)
         //    {
         //        //int p = xx*3 + yy*frame2->linesize[0];
         //        //int p = xx * 3 + yy * linesize;
         //        printf("yy=%d xx=%d",yy,xx);
         //        int p = yy * linesize + xx;
         //        printf("p=%d\n",p);
         //        int r = frame2->data[0][p];
         //        int g = frame2->data[0][p+1];
         //        int b = frame2->data[0][p+2];
         //        printf("[r=%d, g=%d, b=%d ]\n", r, g, b);
         //    }//for
         //}//for

Nav

On 11/20/2012 8:52 AM, Nav wrote:
> Hi! Glad to be part of this mailing list.
> What I wanted to create, was a program which would receive a streaming 
> video, and when it decodes a frame of the video into either a bitmap 
> format or just pure RGB (perhaps stored in a char array), it would 
> notify another program that it has received a frame, and the other 
> program would take the RGB values and display it.
> I've already asked this question here: 
> http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=805
> and rogerdpack told me to post my question on the libav mailing list.
> I have been through many websites, but they either use img_convert 
> (which doesn't work) or sws_scale, which crashes when I try to use it 
> with RGB.
> Could anyone help with a complete piece of code which can give me the 
> RGB values of a frame?
>
> This is a part of the YUV conversion that I tried initially.
>
>   i=0;
>   while(av_read_frame(pFormatCtx, &packet) >= 0)
>   {
>     // Is this a packet from the video stream?
>     if(packet.stream_index==videoStream)
>     {
>     // Decode video frame
>     avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
>
>     // Did we get a video frame?
>     if(frameFinished)
>     {
>         // Convert the image into YUV format that SDL uses
>         sws_scale( sws_ctx, (uint8_t const * const *)pFrame->data,
> pFrame->linesize, 0, pCodecCtx->height, pict.data, pict.linesize );
>
>
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org
http://ffmpeg.org/mailman/listinfo/libav-user


More information about the Libav-user mailing list