[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