作者:辛勤的核桃4dr_797 | 来源:互联网 | 2023-07-25 20:51
篇首语:本文由编程笔记#小编为大家整理,主要介绍了ffmpeg结合SDL编写播放器相关的知识,希望对你有一定的参考价值。
接下来是解析影片的帧
/***
project.c
***/
#include
#include
#include
#include
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[32];
int y;
//open file
sprintf(szFilename,"frame%d.ppm",iFrame);
pFile = fopen(szFilename, "wb");
if (NULL == pFile)
return;
//write header
fprintf(pFile, "P6
%d %d
255
",width,height);
//write pixel data
for (y = 0; y )
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0],
1, width * 3, pFile);
}
//close file
fclose(pFile);
}
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVFrame *pFrameRGB = NULL;
AVPacket packet;
int i,videoStream;
int frameFinished;
int numBytes;
uint8_t *buffer = NULL;
AVDictionary *optiOnsDict= NULL;
struct SwsContext *sws_ctx = NULL;
if (argc <2)
{
printf("Please provide a movie file
");
return -1;
}
//register all formats and codecs
av_register_all();
//open video file
if (avformat_open_input(&pFormatCtx,argv[1], NULL, NULL) != 0)
{
return -1; //couldn‘t open file
}
//retrive stream information
if (avformat_find_stream_info(pFormatCtx, NULL) <0)
{
return -1; //couldn‘t find stream information
}
//dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);
//find the first video stream
videoStream = -1;
for (i = 0; i nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
return -1; //Don‘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)
{
fprintf(stderr,"Unsupported codec!
");
return -1; //Codec not found
}
//open codec
if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) <0)
{
return -1; //Could not open codec
}
//Allcocate an AVFrame structure
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
if (pFrameRGB == NULL)
{
return -1;
}
//Determine required buffer size and allocate buffer
numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
sws_ctx = sws_getContext
(
pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL, NULL, NULL
);
//Assign appropriate parts of buffer to image planes in pFrameRGB
//Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVFPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer,
AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
//Read frames and save first five frames to disk
i = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
//Is this a packet from video stream
if (packet.stream_index == videoStream)
{
//decode video frame
avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet);
//Did wo get a video frame
if (frameFinished)
{
//Convert the image from its native format to RGB
sws_scale(sws_ctx,
(uint8_t const * const *)pFrame->data,
pFrame->linesize,
0,
pCodecCtx->height,
pFrameRGB->data,
pFrameRGB->linesize
);
//Save the frame to disk
SaveFrame(pFrameRGB,pCodecCtx->width,
pCodecCtx->height,i);
printf("decde %d frame
",i);
i++;
}
}
//Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
//Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
//Free the YUV frame
av_free(pFrame);
//Close the codec
avcodec_close(pCodecCtx);
//Close the video file
avformat_close_input(&pFormatCtx);
return 0;
}
makefile如下:
//makefile
DIR_INC = -I/usr/local/include
DIR_LIB = -L/usr/local/lib
LIBS = -lavformat -lavcodec -lva-x11 -lva -lxcb-shm -lxcb-xfixes -lxcb-render -lxcb-shape -lxcb -lX11 -lasound -lz -lswresample -lswscale -lavutil -lm -pthread
FLAGS = -Wall -ggdb
project : project.c
gcc project.c ${FLAGS} ${DIR_INC} ${DIR_LIB} ${LIBS} -o project
.PHONY:clean
clean:
rm project
运行结果:
完成后有很多ppm文件,可以将ppm转为jpg:
编写一个脚本转化,内容如下:
/***
1.sh
***/
#!/bin/bash
ff=`ls *.ppm`
for f in $ff
do
file=`echo ${f%.*}`
ffmpeg -i "$file".ppm "$file".jpg
done
mkdir -p jpgs
mv *.jpg jpgs
rm *.ppm
运行脚本:
sh 1.sh
可以在当前文件夹下找到jpgs文件夹下找到所有转化的jpg图片。