[Libav-user] How to encode JPEG images as video frames

Kelly Schrock kellyschrock at gmail.com
Thu Jul 21 07:05:01 CEST 2011


Hi,

I'm generating a video file from a collection of JPEG images, or rather
trying to. I can generate a video, but it's not playable by any but the most
forgiving of media players (e.g. mplayer, etc.). My problem seems to be with
the way I'm trying to add images to the video. My encoding function is very
similar to the video_encode_example() function from api-example.c in FFmpeg,
except for the loop below.

Here's the main loop where I'm trying to add frames to the video. I tried
passing the frame returned from open_image() to avcodec_encode_video(), but
I get a -1 return value. I'm a bit stumped about how to encode a video that
will be playable by most players. Any help would be greatly appreciated.

    DIR *dir = opendir(path);
    if (dir != NULL) {

        for(struct dirent *ent = readdir(dir); ent != NULL; ent =
readdir(dir)) {
            fflush(stdout);

            char filename[256];
            sprintf(filename, "%s/%s", path, ent->d_name);
            log(filename);

            const char * ext = strrchr(filename, '.');
            if((!ext) || (strcmp(ext, ".jpg"))) {
                continue;
            }

            long bufSize = 0L;
            AVFrame * frame = open_image(filename, width, height, &bufSize);
            if(frame) {
                //
                // This hack works, but is obviously wrong
                //
                picture->data[0] = frame->data[0];
                picture->data[1] = frame->data[1];
                picture->data[2] = frame->data[2];

                picture->linesize[0] = frame->linesize[0];
                picture->linesize[1] = frame->linesize[1];
                picture->linesize[2] = frame->linesize[2];

                out_size = avcodec_encode_video(c, outbuf, outbuf_size,
picture);

                log("encoding frame %3d (size=%5d)\n", i++, out_size);

                if(out_size < 0) {
                    log("Error encoding frame");
                    return -6;
                }

                fwrite(outbuf, 1, out_size, f);

                av_free(frame);
            }
            else {
                log("Couldn't open image");
                return -5;
            }
        }

        closedir(dir);
    }
    else {
        log("Couldn't open directory");
        return -4;
    }

Here's my open_image() function:

AVFrame* open_image(const char* imageFileName, int width, int height, long *
bufSize)
{
    AVFormatContext *pFormatCtx;

    if(av_open_input_file(&pFormatCtx, imageFileName, NULL, 0, NULL)!=0)
    {
        log("Can't open image file '%s'\n", imageFileName);
        return NULL;
    }

    AVCodecContext *pCodecCtx = pFormatCtx->streams[0]->codec;
    pCodecCtx->width = width;
    pCodecCtx->height = height;
    pCodecCtx->pix_fmt = PIX_FMT_YUV420P;

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

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
    {
        log("Could not open codec");
        return NULL;
    }

    AVFrame *pFrame = avcodec_alloc_frame();
    if (!pFrame)
    {
        log("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);

    // ***
    *bufSize = numBytes;
    // ***

    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;

        int ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
&packet);
        if (ret > 0)
        {
            pFrame->quality = 1;
            return pFrame;
        }
        else {
            log("Error [%d] while decoding frame: %s\n", ret,
strerror(AVERROR(ret)));
        }
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20110721/fb20940a/attachment.html>


More information about the Libav-user mailing list