Hi all,

To start making my hand dirty with ffmpeg, i tried to adapt the sample
available on the site to the git version of ffmpeg
(using avcodec_decode_video2, sws_alloc_context, sws_init_context and
sws_scale), but the only thing i obtain at the end is a serie of really nice
black pictures.

When viewing the file in hex format, i obtain the good values for the header
(P6.512 512.255) butthen, the the image is filled with 0x00 until the end
(which explains the black).
I must be missing something.


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"

static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);

int main(int argc, char *argv[]) {
  AVFormatContext *pFormatCtx;
  int             i, videoStream;
  AVCodecContext  *pCodecCtx;
  AVCodec         *pCodec;
  AVFrame         *pFrame;
  AVFrame         *pFrameRGB;
  AVPacket        packet;
  int             frameFinished;
  int             numBytes;
  uint8_t         *buffer;

  if(argc < 2) {
    printf("Please provide a movie file\n");
    return -1;
  }

  // Register all formats and codecs
  av_register_all();

  // Open video file
  if(av_open_input_file(&pFormatCtx,  argv[1], NULL, 0, NULL)!=0)
    return -1; // Couldn't open file

  // Retrieve stream information
  if(av_find_stream_info(pFormatCtx)<0)
    return -1; // Couldn't find stream information

  // Dump information about file onto standard error
  dump_format(pFormatCtx, 0, argv[1], false);

  // Find the first video stream
  videoStream=-1;
  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==CODEC_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)
    return -1; // Codec not found

  // Open codec
  if(avcodec_open(pCodecCtx, pCodec)<0)
    return -1; // Could not open codec

  // Hack to correct wrong frame rates that seem to be generated by some
codecs
  if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
    pCodecCtx->time_base.den=1000;

  // 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=malloc(numBytes);

  // Assign appropriate parts of buffer to image planes in pFrameRGB
  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) {
    static struct SwsContext * img_convert_ctx;
    // Convert the image into YUV format that SDL uses
    //if(img_convert_ctx == NULL) {
      img_convert_ctx = sws_alloc_context();

      av_set_int(img_convert_ctx, "srcw", pCodecCtx->width);
      av_set_int(img_convert_ctx, "srch", pCodecCtx->height);
      av_set_int(img_convert_ctx, "dstw", pCodecCtx->width);
      av_set_int(img_convert_ctx, "dsth", pCodecCtx->height);
      av_set_int(img_convert_ctx, "src_format", pCodecCtx->pix_fmt);
      av_set_int(img_convert_ctx, "dst_format", PIX_FMT_RGB24);
      av_set_int(img_convert_ctx, "sws_flags", SWS_BICUBIC);

      av_set_int(img_convert_ctx, "src_range", 1);
      av_set_int(img_convert_ctx, "dst_range", 1);


      if (sws_init_context(img_convert_ctx, NULL, NULL) < 0) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
      }
      //}
    sws_scale(img_convert_ctx, (const uint8_t * const*)pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
pFrameRGB->linesize);

    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
  free(buffer);
  av_free(pFrameRGB);

  // Free the YUV frame
  av_free(pFrame);

  // Close the codec
  avcodec_close(pCodecCtx);

  // Close the video file
  av_close_input_file(pFormatCtx);

  return 0;
}

static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
  FILE *pFile;
  char szFilename[32];
  int  y;

  // Open file
  sprintf(szFilename, "test/frame%d.ppm", iFrame);
  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);
  }



Thanks in advance :)
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to