ffmpeg结合SDL编写播放器(三)
2024-09-05 17:49:18
接下来是解析影片的帧
/***
project.c
***/
#include<stdio.h>
#include<libavcodec/avcodec.h>
#include<libavformat/avformat.h>
#include<libswscale/swscale.h> void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[];
int y; //open file
sprintf(szFilename,"frame%d.ppm",iFrame);
pFile = fopen(szFilename, "wb");
if (NULL == pFile)
return; //write header
fprintf(pFile, "P6\n%d %d\n255\n",width,height); //write pixel data
for (y = ; y < height; y++)
{
fwrite(pFrame->data[] + y * pFrame->linesize[],
, width * , 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 < )
{
printf("Please provide a movie file\n");
return -;
} //register all formats and codecs
av_register_all(); //open video file
if (avformat_open_input(&pFormatCtx,argv[], NULL, NULL) != )
{
return -; //couldn't open file
} //retrive stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < )
{
return -; //couldn't find stream information
} //dump information about file onto standard error
av_dump_format(pFormatCtx, , argv[], ); //find the first video stream
videoStream = -;
for (i = ; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
} if (videoStream == -)
{
return -; //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!\n");
return -; //Codec not found
} //open codec
if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) < )
{
return -; //Could not open codec
} //Allcocate an AVFrame structure
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
if (pFrameRGB == NULL)
{
return -;
} //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 = ;
while (av_read_frame(pFormatCtx, &packet) >= )
{
//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,
,
pCodecCtx->height,
pFrameRGB->data,
pFrameRGB->linesize
); //Save the frame to disk
SaveFrame(pFrameRGB,pCodecCtx->width,
pCodecCtx->height,i);
printf("decde %d frame\n",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 ;
}
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图片。
最新文章
- MFC-简单的函数使用
- SpringBoot源码解析:AOP思想以及相应的应用
- android 获取当前系统时间
- hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)这题有点意思
- When you’re nearly 40 and unmarried, and you realize you’re going to be okay
- 【转】C++及java在内存分配上的区别
- Cocos2d-x3.0TestCpp文件夹笔记(二)
- 清橙A1484
- 面试题19:包含min函数的栈
- 在centOS7.2安装配置zabbix监控
- VR全景智慧城市-VR大时代
- html加载和解析流程
- 201521123059 《Java程序设计》第十二周学习总结
- vue-axios基本用法
- [原创]FPGA JTAG工具设计(一)
- MongoDB系列----mongostat
- pycharm与python环境配置
- SQL server 多个字段设为主键
- web前端(9)—— CSS属性
- eolinker——添加项目成员