› Foros › Multiplataforma › Desarrollo
void Video::play(char *file) {
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
// Register all formats and codecs
av_register_all();
// Open video file
int err=av_open_input_file(&pFormatCtx, file, NULL, 0, NULL);
if(err!=0) {
System->err->printf("Couldn't open file (%d)", err);
return ; // Couldn't open file
}
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0) {
System->err->print("Couldn't find stream info");
return ; // Couldn't find stream information
}
// Find the first video stream
videoStream=-1;
for(i=0; i<(int)pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoStream=i;
break;
}
if(videoStream==-1) {
System->err->print("Couldn't find video stream");
return ; // 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) {
System->err->print("Couldn't find codec");
return ; // Codec not found
}
// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0) {
System->err->print("Couldn't open codec");
return ; // Could not open codec
}
// Hack to correct wrong frame rates that seem to be generated by some codecs
if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
pCodecCtx->time_base.den=1000;
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return ;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_ARGB, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)malloc(numBytes);
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
System->err->print("reading frames");
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
System->err->print("video frame");
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
// Did we get a video frame?
if(frameFinished)
{
static struct SwsContext *img_convert_ctx;
// Convert the image into YUV format that SDL uses
System->err->print("convert to RGB");
if(img_convert_ctx == NULL) {
int w = pCodecCtx->width;
int h = pCodecCtx->height;
img_convert_ctx = sws_getContext(w, h,
pCodecCtx->pix_fmt,
w, h, PIX_FMT_RGB24, SWS_BICUBIC,
NULL, NULL, NULL);
if(img_convert_ctx == NULL) {
System->err->print("Cannot initialize the conversion context!\n");
return;
}
}
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
System->err->print("saving frame");
// Show the frame
if(i==50) break;
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
free(buffer);
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);
}