简体   繁体   中英

FFmpeg: avcodec_encode_video() and JPEG images

I'm trying to encode a series of.jpg files into a video using the ffmpeg library, and I can't seem to get the frames to encode. (I have to use the ffmpeg library, and using ffmpeg from a command line is not an option in my case.)

Except for the part where I'm trying to open JPG files as AVFrames, my code is more or less the same thing as found in api-example.c from the ffmpeg library. When I populate the frames as the example does, everything works as expected. In the code below, I fail to encode any frames. Obviously the trouble is related to how I'm opening the JPG files, but I can't figure out what.

I'm opening the image like this:

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)
    {
        printf("Can't open image file '%s'\n", imageFileName);
        return NULL;
    }       

    AVCodecContext *pCodecCtx;

    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)
    {
        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 = avcodec_alloc_frame();
    if (!pFrame)
    {
        LOGV(TAG, "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)
        {
            sprintf(buf, "Frame is decoded, size %d", ret);
            LOGV(TAG, buf);
            pFrame->quality = 4;
            return pFrame;
        }
        else {
            // printf("Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret)));
            sprintf(buf, "Error %d decoding frame: %s", ret, strerror(AVERROR(ret)));
            LOGV(TAG, buf);
        }
    }
}

...and attempting to encode them like this:

DIR * dir = opendir(path);
int i = 0;

if (dir != NULL) {

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

        printf("%s/%s", path, ent->d_name);
        LOGV(TAG, filename);

        // If not a jpg file, pass it over
        const char * ext = strrchr(filename, '.');
        if((!ext) || (strcmp(ext, ".jpg"))) {
            continue;
        }

        /*** NOTE: Is this where I've gone wrong? Bufsize is set in open_image based on av_picture_size() */
        long bufSize = 0L;
        AVFrame * frame = open_image(filename, width, height, &bufSize);
        if(frame) {
            // This is what it needs to do, and it does not work.
            // Causes:
            // Wrong format?
            // Wrong buffer size?
            uint8_t * picBuf = (uint8_t *)malloc(bufSize);

            out_size = avcodec_encode_video(c, picBuf, bufSize, frame);

            printf("encoding frame %3d (size=%5d)\n", i++, out_size);
            /** On the first image, out_size is 0. On the next, it's -1, and fails. */

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

            fwrite(picBuf, 1, bufSize, f);

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

    closedir(dir);
} 
else {
    printf("Couldn't open directory %s\n", path);
    return -4;
}

Could someone point me in the right direction?

What exactly is the error you are getting? Examine the Encoding context after opening it to see it's supported pixel formats, you might have to use sws_scale to convert to a format the encoder supports.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM