Hello,

Still struggling with this one. I've changed a bit the approach; what I've
noticed is that the AVFrame's created in the api-example.c (with random
generated content) are well encoded. So my approach now is to create
AVFrames just like in the api example the fill them in with the information
from the source JPEGs(and of course with format conversion), I am using
sws_scale for this. But now I am getting segmentation fault when calling
sws_scale. I've well checked my pointers they have valid values before
entering the sws_scale call. But I'm not sure I am calling it as I should:

void copyFrame(AVCodecContext *destContext, AVFrame* dest,
        AVCodecContext *srcContext, AVFrame* source) {
    static struct SwsContext *swsContext;

    swsContext = sws_getContext(srcContext->width,
srcContext->height,PIX_FMT_YUVJ420P,
            destContext->width, destContext->height, PIX_FMT_YUV420P,
            SWS_FAST_BILINEAR, NULL, NULL, NULL);

    sws_scale(swsContext, source->data, source->linesize, 0,
srcContext->height, dest->data, dest->linesize);

    sws_freeContext(swsContext);
}

destContext is the context used for encoding; dest is the AVFrame to be
encoded.
srcContext is the context used for decoding the JPEGs; source is the
AVFrame the result of reading one JPG file.

I attach the new version for source code.

Thanks in advance for any helpful info you might have.

Best regards,
Florin.

On Thu, Jun 14, 2012 at 8:56 PM, Florin Bratu <[email protected]> wrote:

> Hello,
>
> I have a problem while using the ffmpeg development libraries. What I want
> to achieve is to create a video file from a sequence of images. The effect
> should be as similar as the one of issuing the ffmpeg command:
> $ ffmpeg -i test_%d.jpg -vcodec h263 -s 352x288 out.mp4
> However, I need to achieve this programatically as I need to integrate it
> in a bigger application.
>
> As a start I thought of a simple approach: I read each image as an AVFrame
> and I encode it in the final video. I've quickly hacked an implementation
> of this approach, you can find the source code at the end of the email.
>
> However, when I compile and run it, I get the following error:
> [h263 @ 0x8058020] Error, Invalid timestamp=0, last=0
>
> I get this error for each AVFrame I try to encode, starting with the
> second one, the first one is(or seems to be) correctly encoded.
>
> What can I do to overcome this issue? While searching through ffmpeg
> source code I found out that this error is related to PTS, so I tried a
> quick fix of setting it like this:
>   picture->pts = i;
>
> but unfortunately I still get the same error! seems like the new pts value
> is not even taken into account!
>
> Do you have any ideas how to overcome this error? Am I doing something
> wrong?
>
> I am new to ffmpeg development and to the libav-users mailing list, so
> please pardon my hackish way of using ffmpeg. And feel free to point me any
> other better ways I could use ffmpeg(apart from the obvious refactoring
> this code could benefit from) hopefully in time I will arrive to cleanly
> master its power.
>
> Best regards,
> Florin.
>
> <code>
> #include <libavcodec/avcodec.h>
> #include <libavformat/avformat.h>
>
> #include <stdio.h>
>
> #define W_VIDEO 320
> #define H_VIDEO 240
>
> AVFrame* OpenImage(const char* imageFileName)
> {
>     AVFormatContext *pFormatCtx;
>
>     int ret = av_open_input_file(&pFormatCtx, imageFileName, NULL, 0,
> NULL);
>     if(ret!=0)
>     {
>         printf("Can't open image file '%s': code %d, %s\n",
>             imageFileName, ret, strerror(AVERROR(ret)));
>         return NULL;
>     }
>
>     dump_format(pFormatCtx, 0, imageFileName, 0);
>
>     AVCodecContext *pCodecCtx;
>
>     pCodecCtx = pFormatCtx->streams[0]->codec;
>     pCodecCtx->width = W_VIDEO;
>     pCodecCtx->height = H_VIDEO;
>     pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
>
>     // Find the decoder for the video stream
>     AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
>     if (!pCodec)
>     {
>         printf("Codec not found\n");
>         return NULL;
>     }
>
>     // Open codec
>     if(avcodec_open(pCodecCtx, pCodec)<0)
>     {
>         printf("Could not open codec\n");
>         return NULL;
>     }
>
>     //
>     AVFrame *pFrame;
>
>     pFrame = avcodec_alloc_frame();
>
>     if (!pFrame)
>     {
>         printf("Can't allocate memory for AVFrame\n");
>         return NULL;
>     }
>
>     int frameFinished;
>     int numBytes;
>
>     // Determine required buffer size and allocate buffer
>     numBytes = avpicture_get_size(PIX_FMT_YUVJ420P, pCodecCtx->width,
> pCodecCtx->height);
>     uint8_t *buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
>
>     avpicture_fill((AVPicture *) pFrame, buffer, PIX_FMT_YUVJ420P,
> pCodecCtx->width, pCodecCtx->height);
>
>     // Read frame
>
>     AVPacket packet;
>
>     int framesNumber = 0;
>     while (av_read_frame(pFormatCtx, &packet) >= 0)
>     {
>         if(packet.stream_index != 0)
>             continue;
>
>         ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
> &packet);
>         if (ret > 0)
>         {
>             printf("Frame is decoded, size %d\n", ret);
>             pFrame->quality = 4;
>         // Free the packet that was allocated by av_read_frame
>         av_free_packet(&packet);
>             return pFrame;
>         }
>         else
>             printf("Error [%d] while decoding frame: %s\n", ret,
> strerror(AVERROR(ret)));
>     }
>
>   // close codec
>   avcodec_close(pCodecCtx);
>
>   // Close the video file
>   av_close_input_file(pFormatCtx);
>
>     return pFrame;
> }
>
>
> int main(int argc, char *argv[])
>     {
>      AVCodec *codec;
>      AVCodecContext *c= NULL;
>      int i, out_size, size, x, y, outbuf_size;
>      FILE *f;
>      uint8_t *outbuf;
>      char* vidFileName = argv[1];
>
>      printf("Video encoding\n");
>
> /* must be called before using avcodec lib */
>   avcodec_init();
>
>   /* register all the codecs */
>   avcodec_register_all();
>   av_register_all();
>
>      /* find the mpeg1 video encoder */
>      codec = avcodec_find_encoder(CODEC_ID_H263);
>      if (!codec) {
>          fprintf(stderr, "codec not found\n");
>          exit(1);
>      }
>
>      c= avcodec_alloc_context();
>
>      /* put sample parameters */
>      c->bit_rate = 400000;
>      /* resolution must be a multiple of two */
>      c->width = 352;
>      c->height = 288;
>      /* frames per second */
>      c->time_base= (AVRational){1,25};
>      c->gop_size = 10; /* emit one intra frame every ten frames */
>      c->pix_fmt = PIX_FMT_YUV420P;
>
>      /* open it */
>      if (avcodec_open(c, codec) < 0) {
>          fprintf(stderr, "could not open codec\n");
>          exit(1);
>      }
>
>      f = fopen(vidFileName, "wb");
>      if (!f) {
>          fprintf(stderr, "could not open %s\n", vidFileName);
>          exit(1);
>      }
>
>      /* alloc image and output buffer */
>      outbuf_size = 100000;
>      outbuf = malloc(outbuf_size);
>      AVFrame *picture;
>
>      for(i=2;i<argc;i++) {
>          fflush(stdout);
>      printf("encoding file %s \n", argv[i]);
>          /* load the image to be encoded*/
>      picture = OpenImage(argv[i]);
> //     The above line was my initial attempt to fix, but to no avail
> //     picture->pts = i;
>
>          /* encode the image */
>          out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
>          printf("encoding frame %3d (size=%5d)\n", i, out_size);
>          fwrite(outbuf, 1, out_size, f);
>      }
>
>      /* 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, out_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");
>     }
> </code>
>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

#include <stdio.h>

#define W_VIDEO 320
#define H_VIDEO 240

AVFrame* createBufferFrame(AVCodecContext *c) {
     int size = c->width * c->height;
     uint8_t *picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */

     AVFrame *picture= avcodec_alloc_frame();

     picture->data[0] = picture_buf;
     picture->data[1] = picture->data[0] + size;
     picture->data[2] = picture->data[1] + size / 4;
     picture->linesize[0] = c->width;
     picture->linesize[1] = c->width / 2;
     picture->linesize[2] = c->width / 2;

	return picture;
}

void freeBufferFrame(AVFrame* picture) {
	free(picture->data[0]);
	av_free(picture);
}

void copyFrame(AVCodecContext *destContext, AVFrame* dest,
		AVCodecContext *srcContext, AVFrame* source) {
	// do some sws_scale magic
	static struct SwsContext *swsContext;

	swsContext = sws_getContext(srcContext->width, srcContext->height,PIX_FMT_YUVJ420P,
			destContext->width, destContext->height, PIX_FMT_YUV420P,
			SWS_FAST_BILINEAR, NULL, NULL, NULL);

	sws_scale(swsContext, source->data, source->linesize, 0, srcContext->height, dest->data, dest->linesize);

	sws_freeContext(swsContext);
}

int loadFromFile(const char* imageFileName, AVFrame* realPicture,
			AVCodecContext* videoContext)
{
    AVFormatContext *pFormatCtx;

    int ret = av_open_input_file(&pFormatCtx, imageFileName, NULL, 0, NULL);
    if(ret!=0)
    {
        printf("Can't open image file '%s': code %d, %s\n",
	        imageFileName, ret, strerror(AVERROR(ret)));
        return -1;
    }       

    dump_format(pFormatCtx, 0, imageFileName, 0);

    AVCodecContext *pCodecCtx;

    pCodecCtx = pFormatCtx->streams[0]->codec;
    pCodecCtx->width = W_VIDEO;
    pCodecCtx->height = H_VIDEO;
    pCodecCtx->pix_fmt = PIX_FMT_YUV420P;

    // Find the decoder for the video stream
    AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (!pCodec)
    {
        printf("Codec not found\n");
        return -1;
    }

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
    {
        printf("Could not open codec\n");
        return -1;
    }

    // 
    AVFrame *pFrame;

    pFrame = avcodec_alloc_frame();

    if (!pFrame)
    {
        printf("Can't allocate memory for AVFrame\n");
        return -1;
    }

    int frameFinished;
    int numBytes;

    // Determine required buffer size and allocate buffer
    numBytes = avpicture_get_size(PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);
    uint8_t *buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));

    avpicture_fill((AVPicture *) pFrame, buffer, PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);

    // Read frame

    AVPacket packet;

    int framesNumber = 0;
    while (av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if(packet.stream_index != 0)
            continue;

        ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
        if (ret > 0)
        {
            printf("Frame is decoded, size %d\n", ret);
            // now, load the useful info into realPicture
            copyFrame(videoContext, realPicture, pCodecCtx, pFrame);
            // Free the packet that was allocated by av_read_frame
            av_free_packet(&packet);
            return 0;
        }
        else
            printf("Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret)));
    }

  //av_free(buffer);
  av_free(pFrame);

  // close codec
  avcodec_close(pCodecCtx);

  // Close the video file
  av_close_input_file(pFormatCtx);

    return 0;
}


int main(int argc, char *argv[]) 
    {
     AVCodec *codec;
     AVCodecContext *c= NULL;
     int i, out_size, outbuf_size;
     FILE *f;
     uint8_t *outbuf;
     char* vidFileName = argv[1];

     printf("Video encoding\n");

/* must be called before using avcodec lib */
  avcodec_init();

  /* register all the codecs */
  avcodec_register_all();
  av_register_all();

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

     c= avcodec_alloc_context();

     /* put sample parameters */
     c->bit_rate = 400000;
     /* resolution must be a multiple of two */
     c->width = 352;
     c->height = 288;
     /* frames per second */
     c->time_base= (AVRational){1,25};
     c->gop_size = 10; /* emit one intra frame every ten frames */
     c->pix_fmt = PIX_FMT_YUV420P;

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

     f = fopen(vidFileName, "wb");
     if (!f) {
         fprintf(stderr, "could not open %s\n", vidFileName);
         exit(1);
     }

     /* alloc image and output buffer */
     outbuf_size = 100000;
     outbuf = malloc(outbuf_size);
	AVFrame *realPicture = createBufferFrame(c);

     for(i=2;i<argc;i++) {
         fflush(stdout);
	 printf("encoding file %s \n", argv[i]);
         /* load the image to be encoded from file*/
	     loadFromFile(argv[i],realPicture, c);
 
         /* encode the image */
         out_size = avcodec_encode_video(c, outbuf, outbuf_size, realPicture);
         printf("encoding frame %3d (size=%5d)\n", i, out_size);
         fwrite(outbuf, 1, out_size, f);
     }

     /* 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, out_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);
	freeBufferFrame(realPicture);

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

_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to