Ffmpeg 如何保存视频中间的图像?

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

我需要做一个视频缩略图,以寻求一个视频的25%,并保存图像。这是我现在正在做的,但它只保存黑色图像

#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流,您可能需要对其进行颜色转换