<div>Hello,</div><div><br></div><div>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:</div>
<div>$ ffmpeg -i test_%d.jpg -vcodec h263 -s 352x288 out.mp4<br></div><div>However, I need to achieve this programatically as I need to integrate it in a bigger application.</div><div><br></div><div>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.<br></div>
<div><br></div><div>However, when I compile and run it, I get the following error: </div><div>[h263 @ 0x8058020] Error, Invalid timestamp=0, last=0<br></div><div><br></div><div>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. <br></div><div><br></div><div>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:</div>
<div> picture->pts = i;<br><br></div><div>but unfortunately I still get the same error! seems like the new pts value is not even taken into account!<br></div><div><br></div><div>Do you have any ideas how to overcome this error? Am I doing something wrong?</div>
<div><br></div><div>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.</div>
<div><br></div><div>Best regards,</div>Florin.<br><br><code><br>#include <libavcodec/avcodec.h><br>#include <libavformat/avformat.h><br><br>#include <stdio.h><br><br>#define W_VIDEO 320<br>#define H_VIDEO 240<br>
<br>AVFrame* OpenImage(const char* imageFileName)<br>{<br> AVFormatContext *pFormatCtx;<br><br> int ret = av_open_input_file(&pFormatCtx, imageFileName, NULL, 0, NULL);<br> if(ret!=0)<br> {<br> printf("Can't open image file '%s': code %d, %s\n",<br>
imageFileName, ret, strerror(AVERROR(ret)));<br> return NULL;<br> } <br><br> dump_format(pFormatCtx, 0, imageFileName, 0);<br><br> AVCodecContext *pCodecCtx;<br><br> pCodecCtx = pFormatCtx->streams[0]->codec;<br>
pCodecCtx->width = W_VIDEO;<br> pCodecCtx->height = H_VIDEO;<br> pCodecCtx->pix_fmt = PIX_FMT_YUV420P;<br><br> // Find the decoder for the video stream<br> AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);<br>
if (!pCodec)<br> {<br> printf("Codec not found\n");<br> return NULL;<br> }<br><br> // Open codec<br> if(avcodec_open(pCodecCtx, pCodec)<0)<br> {<br> printf("Could not open codec\n");<br>
return NULL;<br> }<br><br> // <br> AVFrame *pFrame;<br><br> pFrame = avcodec_alloc_frame();<br><br> if (!pFrame)<br> {<br> printf("Can't allocate memory for AVFrame\n");<br> return NULL;<br>
}<br><br> int frameFinished;<br> int numBytes;<br><br> // Determine required buffer size and allocate buffer<br> numBytes = avpicture_get_size(PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);<br>
uint8_t *buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));<br><br> avpicture_fill((AVPicture *) pFrame, buffer, PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);<br><br> // Read frame<br><br>
AVPacket packet;<br><br> int framesNumber = 0;<br> while (av_read_frame(pFormatCtx, &packet) >= 0)<br> {<br> if(packet.stream_index != 0)<br> continue;<br><br> ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);<br>
if (ret > 0)<br> {<br> printf("Frame is decoded, size %d\n", ret);<br> pFrame->quality = 4;<br> // Free the packet that was allocated by av_read_frame<br> av_free_packet(&packet);<br>
return pFrame;<br> }<br> else<br> printf("Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret)));<br> }<br><br> // close codec<br> avcodec_close(pCodecCtx);<br>
<br> // Close the video file<br> av_close_input_file(pFormatCtx);<br><br> return pFrame;<br>}<br><br><br>int main(int argc, char *argv[]) <br> {<br> AVCodec *codec;<br> AVCodecContext *c= NULL;<br> int i, out_size, size, x, y, outbuf_size;<br>
FILE *f;<br> uint8_t *outbuf;<br> char* vidFileName = argv[1];<br><br> printf("Video encoding\n");<br><br>/* must be called before using avcodec lib */<br> avcodec_init();<br><br> /* register all the codecs */<br>
avcodec_register_all();<br> av_register_all();<br><br> /* find the mpeg1 video encoder */<br> codec = avcodec_find_encoder(CODEC_ID_H263);<br> if (!codec) {<br> fprintf(stderr, "codec not found\n");<br>
exit(1);<br> }<br><br> c= avcodec_alloc_context();<br><br> /* put sample parameters */<br> c->bit_rate = 400000;<br> /* resolution must be a multiple of two */<br> c->width = 352;<br>
c->height = 288;<br> /* frames per second */<br> c->time_base= (AVRational){1,25};<br> c->gop_size = 10; /* emit one intra frame every ten frames */<br> c->pix_fmt = PIX_FMT_YUV420P;<br><br>
/* open it */<br> if (avcodec_open(c, codec) < 0) {<br> fprintf(stderr, "could not open codec\n");<br> exit(1);<br> }<br><br> f = fopen(vidFileName, "wb");<br> if (!f) {<br>
fprintf(stderr, "could not open %s\n", vidFileName);<br> exit(1);<br> }<br><br> /* alloc image and output buffer */<br> outbuf_size = 100000;<br> outbuf = malloc(outbuf_size);<br>
AVFrame *picture;<br><br> for(i=2;i<argc;i++) {<br> fflush(stdout);<br> printf("encoding file %s \n", argv[i]);<br> /* load the image to be encoded*/<br> picture = OpenImage(argv[i]); <br>
// The above line was my initial attempt to fix, but to no avail<br>// picture->pts = i;<br> <br> /* encode the image */<br> out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);<br>
printf("encoding frame %3d (size=%5d)\n", i, out_size);<br> fwrite(outbuf, 1, out_size, f);<br> }<br><br> /* get the delayed frames */<br> for(; out_size; i++) {<br> fflush(stdout);<br>
<br> out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);<br> printf("write frame %3d (size=%5d)\n", i, out_size);<br> fwrite(outbuf, 1, out_size, f);<br> }<br><br> /* add sequence end code to have a real mpeg file */<br>
outbuf[0] = 0x00;<br> outbuf[1] = 0x00;<br> outbuf[2] = 0x01;<br> outbuf[3] = 0xb7;<br> fwrite(outbuf, 1, 4, f);<br> fclose(f);<br> free(outbuf);<br><br> avcodec_close(c);<br> av_free(c);<br>
av_free(picture);<br> printf("\n");<br> }<br></code><br>