[Libav-user] timestamp error
Florin Bratu
killerappzz at gmail.com
Thu Jun 14 20:56:39 CEST 2012
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>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20120614/dedfc742/attachment.html>
More information about the Libav-user
mailing list