video generation using ffmpeg

2020-03-07 06:23发布

问题:

I am trying to generate video from set of image using ffmpeg library. Using following code, I am able to generate the video on simulator but when I run it on device, it produces strange green effect in video. I followed Encoding images to video with ffmpeg url. Can anybody help me out or if can provide code snippet, will be really appreciated.

//here is the code..

(void)createVideoFromImages 
{
  NSString *fileName2 = [Utilities documentsPath:[NSString stringWithFormat:@"test.mov"]];
  NSLog(@"filename: %@",fileName2);

  //Register all formats and codecs

  AVCodec *codec;

  //avcodec_register_all();
  //avdevice_register_all();

  av_register_all();


  AVCodecContext *c= NULL; 
  int i, out_size, size, outbuf_size;
  FILE *f;
  AVFrame *picture;
  uint8_t *outbuf;

  printf("Video encoding\n");

  /* find the mpeg video encoder */
  codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
  if (!codec) 
  {
    fprintf(stderr, "codec not found\n");
    exit(1);
  }

  c= avcodec_alloc_context();
  picture= avcodec_alloc_frame();

  /* put sample parameters */
  c->bit_rate = 400000;
  /* resolution must be a multiple of two */
  c->width = 256;
  c->height = 256;//258;

  /* frames per second */
  c->time_base= (AVRational){1,25};
  c->gop_size = 10; /* emit one intra frame every ten frames */
  c->max_b_frames=1;
  c->pix_fmt =  PIX_FMT_YUV420P;//PIX_FMT_YUV420P;

  /* open it */
  if (avcodec_open(c, codec) < 0) {
    fprintf(stderr, "could not open codec\n");
    exit(1);
  }

  const char* filename_cstr = [fileName2 cStringUsingEncoding:NSUTF8StringEncoding];
  f = fopen(filename_cstr, "wb");
  if (!f) {
    fprintf(stderr, "could not open %s\n", fileName2);
    exit(1);
  }

  /* alloc image and output buffer */
  outbuf_size = 100000;
  outbuf = malloc(outbuf_size);
  size = c->width * c->height;

  #pragma mark -
  AVFrame* outpic = avcodec_alloc_frame();
  int nbytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);

  NSLog(@"bytes: %d",nbytes);

  //create buffer for the output image
  uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes);

  for(i=100;i<104;i++) 
  {
    fflush(stdout);

    int numBytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);
    NSLog(@"numBytes: %d",numBytes);
    uint8_t *buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

    UIImage *image;

    image = [UIImage imageWithContentsOfFile:[Utilities bundlePath:[NSString stringWithFormat:@"%d.png",i]]];


    /*
    if(i>=98)//for video images
    {
       NSLog(@"i: %d",i);
       image = [UIImage imageWithContentsOfFile:[Utilities documentsPath:[NSString stringWithFormat:@"image0098.png"]]]; ///@"image0098.png"]];
       //[NSString stringWithFormat:@"%d.png", i]];
    }
    else //for custom image
    {
       image = [UIImage imageWithContentsOfFile:[Utilities bundlePath:[NSString stringWithFormat:@"image%04d.png", i]]];
       //[UIImage imageNamed:[NSString stringWithFormat:@"%d.png", i]];//@"image%04d.png",i]];
    }*/

    CGImageRef newCgImage = [image CGImage];

    NSLog(@"No. of Bits per component: %d",CGImageGetBitsPerComponent([image CGImage]));
    NSLog(@"No. of Bits per pixel: %d",CGImageGetBitsPerPixel([image CGImage]));
    NSLog(@"No. of Bytes per row: %d",CGImageGetBytesPerRow([image CGImage]));


    CGDataProviderRef dataProvider = CGImageGetDataProvider(newCgImage);
    CFDataRef bitmapData = CGDataProviderCopyData(dataProvider);
    buffer = (uint8_t *)CFDataGetBytePtr(bitmapData);   

    struct SwsContext* fooContext;

    avpicture_fill((AVPicture*)picture, buffer, PIX_FMT_RGBA, c->width, c->height);

    avpicture_fill((AVPicture*)outpic, outbuffer, PIX_FMT_YUV420P, c->width, c->height);

    fooContext= sws_getContext(c->width, c->height, 
       PIX_FMT_RGBA, 
        c->width, c->height, 
        PIX_FMT_YUV420P, 
        SWS_FAST_BILINEAR , NULL, NULL, NULL);

//}

  //perform the conversion

  NSLog(@"linesize: %d", picture->linesize[0]);

  sws_scale(fooContext, picture->data, picture->linesize, 0, c->height, outpic->data, outpic->linesize);

  // Here is where I try to convert to YUV

  /* encode the image */
  out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic);
  printf("encoding frame %d (size=%d)\n", i, out_size);
  fwrite(outbuf, 1, out_size, f);

  NSLog(@"%d",sizeof(f));

  free(buffer);
  buffer = NULL;      

  }

  /* get the delayed frames */
  for( ; out_size; i++) 
  {
    fflush(stdout);
    out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
    printf("write frame %3d (size=%5d)\n", i, out_size);
    fwrite(outbuf, 1, outbuf_size, f);      
  }

  /* add sequence end code to have a real mpeg file */
  outbuf[0] = 0x00;
  outbuf[1] = 0x00;
  outbuf[2] = 0x01;
  outbuf[3] = 0xb7;
  fwrite(outbuf, 1, 4, f);

  fclose(f);
  free(outbuf);

  avcodec_close(c);
  av_free(c);
  av_free(picture);
  printf("\n");

}