[Ffmpeg-devel] Re: img_convert crashes

Mohnhaupt, Denis Denis.Mohnhaupt
Thu Aug 24 09:05:40 CEST 2006


Hi Luca, Anders,

 

thanks for your help.

 

for better clarification i will paste the full code at the end of this
mail.

This is an interface used by an Ada95 core application and encapsules
the functionality of the ffmpeg libraries. first it calls video_init(),
then later open_video() and get_video_dimensions() (where xbuffer and
ybuffer will be initialized as well) and then regularily
get_next_frame() is called where the buffer to the openGL_Texture used
in Ada is set.

 

Anders: this is a very good idea, I will try this after I (we) have
found out, why img_convert crashes on certain videos.

 

Regards,

Denis

 

 

 

#include <stdbool.h>

#include "avcodec.h"

#include "avformat.h"

#include "avutil.h"

 

#include <stdio.h>

 

#define GL_TEX_WIDTH 1024  //this could/should be changed to be set via
function by the server core to support different (i.e. smaller) texture
sizes

#define GL_TEX_HEIGHT 1024

 

 

AVFormatContext *pFormatCtx;

int             i, videoStream;

AVCodecContext  *pCodecCtx;

AVCodec         *pCodec;

AVFrame         *pFrame; 

AVFrame         *pFrameRGB;

int             numBytes;

int             framecounter;

 

int xbuffer, ybuffer;  //these ensure that no video woth greater
dimensions than the texture will be written to the texture buffer

 

 

void video_init()

{

              // Register all formats and codecs

    av_register_all();        

}

 

 

int open_video(char video_file[])

{

              //todo: check if video is open, close video and re-init
variables

    if(av_open_input_file(&pFormatCtx, video_file, NULL, 0, NULL)!=0)

    {

      printf("Unable to open file %s\n", video_file);

      return 1; // Couldn't open file

    }

    

       // Retrieve stream information

    if(av_find_stream_info(pFormatCtx)<0)

            {

                        printf("Couldn't find stream information in file
%s\n", video_file);

        return 2; // Couldn't find stream information

      }

 

    // Dump information about file onto standard error

                        printf("Video file info:\n");

    dump_format(pFormatCtx, 0, video_file, false);

 

    // Find the first video stream

    videoStream=-1;

    for(i=0; i<pFormatCtx->nb_streams; i++)

    {

        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)

        {

            videoStream=i;

            printf("Found video stream in stream #%d\n", i);

            break;

        }

    }

        

    if(videoStream==-1)

            {

                        printf("Couldn't find a video stream in this
file\n");

        return 3; // Didn't find a video stream

      }

 

    // Get a pointer to the codec context for the video stream

    pCodecCtx=pFormatCtx->streams[videoStream]->codec;

 

    // Find the decoder for the video stream

    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);

    if(pCodec==NULL)

    {

            printf("Unknown codec id: %d\n", pCodecCtx->codec_id);

      return 4; // Codec not found

    }

    else

    {

      printf("Found codec \"%s\"\n", pCodec->name);        

    }

 

    // Inform the codec that we can handle truncated bitstreams -- i.e.,

    // bitstreams where frame boundaries can fall in the middle of
packets

    if(pCodec->capabilities & CODEC_CAP_TRUNCATED)

        pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;

 

    // Open codec

    if(avcodec_open(pCodecCtx, pCodec)<0)

    {

        printf("Couldn't open codec\n");

        return 5; // Could not open codec

    }

 

    // Hack to correct wrong frame rates that seem to be generated by
some 

    // codecs

//    if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)

//        pCodecCtx->frame_rate_base=1000;

 

    // Allocate video frame

    pFrame=avcodec_alloc_frame();

 

    // Allocate an AVFrame structure

    pFrameRGB=avcodec_alloc_frame();

    if(pFrameRGB==NULL)

    {

        printf("AVFrame structure alloc failed");

        return 6;

    }

 

    // Determine required buffer size and allocate buffer

    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,

        pCodecCtx->height);

    uint8_t buffer[numBytes];

    

    if(pCodecCtx->width < GL_TEX_WIDTH)

            xbuffer = pCodecCtx->width;

    else

            xbuffer = GL_TEX_WIDTH;

            

    if(pCodecCtx->height < GL_TEX_HEIGHT)

            ybuffer = pCodecCtx->height;

    else

            ybuffer = GL_TEX_HEIGHT;

 

    // Assign appropriate parts of buffer to image planes in pFrameRGB

    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,

        pCodecCtx->width, pCodecCtx->height);

        

    framecounter =0;

    return 0;

}

 

void get_video_dimensions(int *xsize, int *ysize, int *success)

{

            //todo: check if video was opened, or is check for pCodecCtx
sufficient?

  if(pCodecCtx != NULL)

            {

              *xsize = pCodecCtx->width;

              *ysize = pCodecCtx->height;

              

              *success = 0;

            }

            else

              *success = 1;

}

 

void SaveFrame(unsigned char pixels[], int width, int height, int
iFrame)

{

    FILE *pFile;

    char szFilename[32];

    int  y;

 

    // Open file

    sprintf(szFilename, "frame%04d.ppm", iFrame);

    //printf("-----Saving frame%4d.ppm-----\n",iFrame);

    pFile=fopen(szFilename, "wb");

    if(pFile==NULL)

        return;

 

    // Write header

    fprintf(pFile, "P6\n%d %d\n255\n", width, height);

 

    // Write pixel data

    for(y=0; y<height; y++)

        fwrite(&pixels[(y*width*3)], 1, width*3, pFile);

 

    // Close file

    fclose(pFile);

}

 

void get_next_frame(int *success, unsigned char picture[])

{

    int frameFinished;

    static AVPacket packet;

    int line=0;

    int byte=0;

    int lineInv;

    bool bIsVideo;

    float fY, fU, fV, fR, fG, fB;

    int r, g, b;

 

                        printf("reading next frame...\n");

    while((av_read_frame(pFormatCtx, &packet)>=0) )

    {

                                               bIsVideo = false;

        // Is this a packet from the video stream?

        if(packet.stream_index==videoStream)

        {

                        bIsVideo = true;

                                               printf("decoding
frame...\n");

            // Decode video frame

            avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, 

                packet.data, packet.size);

            printf("found video packet in video stream %d; framecounter:
%d\n", packet.stream_index, framecounter);

    

            // Did we get a video frame?

            if(frameFinished)

            {

                // Convert the image from its native format to RGB

 
printf("Frame done, pixelformat is: %d\n", pCodecCtx->pix_fmt);

 
printf("Pixelformat for 24bit RGB is %d\n", PIX_FMT_RGB24);

 
printf("Pixelformat PIX_FMT_YUV420P is %d\n", PIX_FMT_YUV420P);

 


 
//convert image data to rgb if necessary and write it into the output
buffer for ada

 
switch(pCodecCtx->pix_fmt)

 
{

 
case PIX_FMT_RGB24: 

 
{

 
printf("copying frame directly to texture buffer...\n");

                    for(line = 0; line < ybuffer; line = line +1)

                    {

                        lineInv = ybuffer - line - 1; //the picture is
y-inverted we have to flip lines

                          for(byte = 0; byte < (xbuffer*3); byte = byte
+ 1)

                          {

                            picture[byte + (lineInv*xbuffer*3)] =
(unsigned char) *(pFrame->data[0]+(line*pFrame->linesize[0])+byte);

                            //memcopy could probably accellerate this

                      }

                    }

                    break;

 
}

 

 
default: //for unknown pixel formats we use the standard routine and
hope, it will not crash

 
{

 
printf("attempting to convert frame to RGB...\n");


               

                    img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,

                        (AVPicture*)pFrame, pCodecCtx->pix_fmt,
pCodecCtx->width,

                        pCodecCtx->height);

                              

 
printf("copying frame to texture buffer...\n");

                              for(line = 0; line < ybuffer; line = line
+1)

                    {

                          

                          lineInv = ybuffer - line - 1; //the picture is
y-inverted we have to flip lines

                          for(byte = 0; byte < (xbuffer*3); byte++)

                          {

                            picture[byte + (lineInv*xbuffer*3)] =
(unsigned char)
*(pFrameRGB->data[0]+(line*pFrameRGB->linesize[0])+byte);

                        }

                    }   

 
}

 
}

 


 
printf("attempting to convert frame to RGB...\n");


               

           }

        }

    

        // Free the packet that was allocated by av_read_frame

        av_free_packet(&packet);

        if(frameFinished && bIsVideo)

        {

          framecounter++;

            break; //we got our video frame

        }

    }

    

    if(frameFinished<0)

    {

      printf("error or eof\n");

    }

    printf("get_next_frame complete: %d\n", framecounter);   

    *success = frameFinished; 

    return;

}

 

 

 

void video_close()

{

    av_free(pFrameRGB);

 

    // Free the YUV frame

    av_free(pFrame);

 

    // Close the codec

    avcodec_close(pCodecCtx);

 

    // Close the video file

    av_close_input_file(pFormatCtx);        

}

 

 





More information about the ffmpeg-devel mailing list