使用ffmpeg库从avi文件捕获JPEG帧。如何打开捕获的文件?

时间:2013-11-18 02:27:46

标签: ffmpeg

这是我在ffmpeg教程网站上找到的代码:

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
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); // szFilenam = frame4.ppm
  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, char **argv[])
{
    AVFormatContext *pFormatCtx = NULL;
    int             i, videoStream;
    AVCodecContext  *pCodecCtx = NULL;
    AVCodec         *pCodec = NULL;
    AVFrame         *pFrame = NULL; 
    AVFrame         *pFrameRGB = NULL;
    AVPacket        packet;
    int             frameFinished;
    int             numBytes;
    uint8_t         *buffer = NULL;

    AVDictionary    *optionsDict = NULL;
    struct SwsContext      *sws_ctx = NULL;


    // Register all formats and codecs
    av_register_all();

    // Open video file
    if(avformat_open_input(&pFormatCtx, "/root/dhquan/AVI/turning_pages.avi", NULL, NULL)!=0)
        return -1; // couldn't open file

    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
        return -1; // couldn't find stream information
                   // This function populates pFormatCtx->streams with the proper 

    // dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, "/root/dhquan/AVI/turning_pages.avi", 0);

    // Find the first video stream
    videoStream = -1;
    for(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; // didn'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 -1;
        }

    // Open Codec
        if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0)
            return -1; // Could not open codec

    // Allocate video frame
        pFrame = avcodec_alloc_frame();

    // Allocate an AVFrame structure
         pFrameRGB=avcodec_alloc_frame();
        if(pFrameRGB==NULL)
            return -1;
    // Determine required buffer size and allocate buffer
         numBytes=avpicture_get_size(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,
        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 AVPicture
  avpicture_fill((AVPicture *)pFrameRGB, buffer, 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 the video stream?
    if(packet.stream_index==videoStream) {
      // Decode video frame
      avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, 
               &packet);

      // Did we 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
    if(++i<=5)
      SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, 
            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;
  //getch();
}

符合:      sprintf(szFilename,“frame%d.ppm”,iFrame);

我换成了帧%d.jpg。它在我的文件夹中创建.jpg文件。但我无法读懂它。怎么打开这个文件?请帮帮我。

2 个答案:

答案 0 :(得分:1)

这就是我们在Web服务器上执行此操作的方式。以下php代码将从mp4创建一个640x480 jpeg,前提是你安装了ffmpeg,输出文件夹可以被ffmpeg写入,我还没有在.avi上测试过它

// the input movie file
$video_file = some.mp4;

// the frame to capture
$thumb_position = 60;

// the output .jpg file
$output_file = 'folder/some.jpg'

// form the ffmpeg command
$cmd = "ffmpeg -y -i $video_file -ss $thumb_position -q 1 -b:v 3024k -vframes 1 -s 640x480 -r 1 -f mjpeg $output_file";

// run command and capture ffmpeg response
$output = '';
@exec("$cmd 2>&1",$output); 

// display ffmpeg response
foreach($output as $output1) echo "" . $output1 ."<br>\n";

答案 1 :(得分:0)

你需要做的两件事。

  1. 将文件扩展名更改回ppm
  2. 使用文件转换程序,例如ppm2tiff在ubuntu中,然后您可以将tiff转换为jpeg。或者您可以使用gimpimagemagick或任何其他netpbm兼容的图像实用程序。