gcc main.c -o a.out -I$HOME/ffmpeg_build/include -L$HOME/ffmpeg_build/lib -lavformat -lavcodec -lavutil -lswscale -lavfilter -lswresample -lavdevice -lfdk-aac -lx264 -lx265 -lpthread -lm -lz -lva -lva-drm -lva-x11 -lX11 -lXext -lvdpau -lSDL2 -lpng && ./a.out
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/imgutils.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/mathematics.h"
#include <png.h>
int main()
{
AVFormatContext *pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, "../video_resources/test.mp4", NULL, NULL) != 0)
{
printf("Couldn't open input stream.\r\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\r\n");
return -1;
}
int videoStream = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
printf("Didn't find a video stream.\r\n");
return -1;
}
AVCodecParameters *pCodecPar = pFormatCtx->streams[videoStream]->codecpar;
AVCodec *pCodec = avcodec_find_decoder(pCodecPar->codec_id);
if (pCodec == NULL)
{
printf("Codec not found.\r\n");
return -1;
}
AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(pCodecCtx, pCodecPar) < 0)
{
printf("Couldn't copy codec context.\r\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Couldn't open codec.\r\n");
return -1;
}
AVFrame *pFrame = av_frame_alloc();
AVFrame *pFrameRGB = av_frame_alloc();
AVPacket packet;
int frameFinished;
int i = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
if (packet.stream_index == videoStream)
{
avcodec_send_packet(pCodecCtx, &packet);
frameFinished = avcodec_receive_frame(pCodecCtx, pFrame);
if (frameFinished == 0)
{
if(i > 10){
char filename[1024];
sprintf(filename, "frame%d.png", i);
FILE *fp = fopen(filename, "wb");
if (fp == NULL)
{
printf("open file error\r\n");
return -1;
}
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL)
{
printf("png_create_write_struct error\r\n");
return -1;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
printf("png_create_info_struct error\r\n");
return -1;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
printf("setjmp error\r\n");
return -1;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, pCodecCtx->width, pCodecCtx->height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
uint8_t *out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1));
if(out_buffer == NULL)
{
printf("av_malloc error\r\n");
return -1;
}
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
struct SwsContext *img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{
printf("sws_getContext error\r\n");
return -1;
}
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
sws_freeContext(img_convert_ctx);
png_bytep row_pointers[pCodecCtx->height];
for (int i = 0; i < pCodecCtx->height; i++)
{
row_pointers[i] = pFrameRGB->data[0] + i * pFrameRGB->linesize[0];
}
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
printf("save frame%d.png\r\n", i);
fclose(fp);
}
i++;
printf("frame%d\r\n", i);
}
}
av_packet_unref(&packet);
}
return 0;
}