Ffmpeg 如何保存视频中间的图像?
我需要做一个视频缩略图,以寻求一个视频的25%,并保存图像。这是我现在正在做的,但它只保存黑色图像Ffmpeg 如何保存视频中间的图像?,ffmpeg,Ffmpeg,我需要做一个视频缩略图,以寻求一个视频的25%,并保存图像。这是我现在正在做的,但它只保存黑色图像 #include <stdio.h> #include <libavformat/avformat.h> #include <libavutil/dict.h> int main (int argc, char **argv) { av_register_all(); AVFormatContext *pFormatCtx = avfor
#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
int main (int argc, char **argv)
{
av_register_all();
AVFormatContext *pFormatCtx = avformat_alloc_context();
int res;
res = avformat_open_input(&pFormatCtx, "test.mp4", NULL, NULL);
if (res) {
return res;
}
avformat_find_stream_info(pFormatCtx, NULL);
int64_t duration = pFormatCtx->duration;
// Find the first video stream
int videoStream=-1;
for(int i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
}
if(videoStream==-1) {
return -1;
}
AVCodecContext *pCodecCtxOrig = NULL;
// Get a pointer to the codec context for the video stream
pCodecCtxOrig=pFormatCtx->streams[videoStream]->codec;
AVCodec *pCodec = NULL;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtxOrig->codec_id);
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
}
AVCodecContext *pCodecCtx = NULL;
// Copy context
pCodecCtx = avcodec_alloc_context3(pCodec);
if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {
fprintf(stderr, "Couldn't copy codec context");
return -1; // Error copying codec context
}
// Open codec
if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
return -1; // Could not open codec
}
AVFrame *pFrame = NULL;
pFrame=av_frame_alloc();
AVFrame *pFrameRGB = NULL;
pFrameRGB=av_frame_alloc();
// Determine required buffer size and allocate buffer
int numBytes=avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
uint8_t *buffer = NULL;
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
res = avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
if (res<0) {
return;
}
// I've set this number randomly
res = av_seek_frame(pFormatCtx, videoStream, 20.0, AVSEEK_FLAG_FRAME);
if (res<0) {
return;
}
AVPacket packet;
while(1) {
av_read_frame(pFormatCtx, &packet);
if(packet.stream_index==videoStream) {
int frameFinished;
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished) {
SaveFrame(pFrameRGB, pCodecCtx->width,
pCodecCtx->height);
break;
}
}
}
avformat_close_input(&pFormatCtx);
return 0;
}
void SaveFrame(AVFrame *pFrame, int width, int height) {
FILE *pFile;
char szFilename[] = "frame.ppm";
int y;
// Open file
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(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
// Close file
fclose(pFile);
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
av_寄存器_all();
AVFormatContext*pFormatCtx=avformat_alloc_context();
国际关系;
res=avformat\u open\u输入(&pFormatCtx,“test.mp4”,NULL,NULL);
如果(res){
返回res;
}
avformat_find_stream_info(pFormatCtx,NULL);
int64_t duration=pFormatCtx->duration;
//查找第一个视频流
int videoStream=-1;
对于(int i=0;inb_流;i++){
如果(pFormatCtx->streams[i]->codec->codec\u type==AVMEDIA\u type\u VIDEO){
视频流=i;
打破
}
}
如果(视频流==-1){
返回-1;
}
AVCodecContext*pCodecCtxOrig=NULL;
//获取指向视频流的编解码器上下文的指针
pCodecCtxOrig=pFormatCtx->streams[videoStream]->编解码器;
AVCodec*pCodec=NULL;
//查找视频流的解码器
pCodec=avcodec\u find\u解码器(pCodecCtxOrig->codec\u id);
if(pCodec==NULL){
fprintf(stderr,“不支持的编解码器!\n”);
return-1;//找不到编解码器
}
AVCodecContext*pCodecCtx=NULL;
//复制上下文
pCodecCtx=avcodec\u alloc\u context3(pCodec);
if(avcodec\u copy\u上下文(pCodecCtx,pCodecCtxOrig)!=0){
fprintf(stderr,“无法复制编解码器上下文”);
return-1;//复制编解码器上下文时出错
}
//开放式编解码器
如果(avcodec_open2(pCodecCtx,pCodec,NULL)宽度,
pCodecCtx->高度);
uint8_t*buffer=NULL;
缓冲区=(uint8_t*)av_malloc(numBytes*sizeof(uint8_t));
//将缓冲区的适当部分指定给pFrameRGB中的图像平面
//请注意,pFrameRGB是一个AVFrame,但AVFrame是一个超集
//AVPicture的应用
res=avpicture_fill((avpicture*)pFrameRGB、缓冲器、AV_PIX_FMT_RGB24、,
PCODECTX->宽度,PCODECTX->高度);
如果(res这里有一篇关于av_seek_框架的文章:
此外,在使用avpicture_fill初始化pFrameRGB后,您从未将其设置为新值
您可能会更改为:
avcodec_decode_video2(pCodecCtx, pFrameRGB, &frameFinished, &packet);
此外,我不确定您当前的代码是否保证您甚至可以处理RGB流,您可能需要对其进行颜色转换…这是一篇关于av_seek_frame的文章:
此外,在使用avpicture_fill初始化pFrameRGB后,您从未将其设置为新值
您可能会更改为:
avcodec_decode_video2(pCodecCtx, pFrameRGB, &frameFinished, &packet);
此外,我不确定您当前的代码是否保证您甚至可以处理RGB流,您可能需要对其进行颜色转换