FFmpeg: avcodec_encode_video()和JPEG图像

时间:2022-11-25 21:19:22

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.)

我正在尝试使用ffmpeg库将一系列.jpg文件编码到一个视频中,但我似乎无法让这些帧进行编码。(我必须使用ffmpeg库,使用命令行中的ffmpeg不是我的选项。)

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.

除了尝试将JPG文件作为avframe打开的部分之外,我的代码与api示例中的代码差不多。来自ffmpeg库。当我像示例那样填充帧时,一切都按预期运行。在下面的代码中,我没有对任何帧进行编码。很明显,问题在于我如何打开JPG文件,但是我搞不清楚是什么。

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?

有人能给我指出正确的方向吗?

1 个解决方案

#1


1  

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.

你得到的错误是什么?在打开它以查看支持的像素格式之后,检查编码上下文,您可能需要使用sws_scale来转换成编码器支持的格式。

#1


1  

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.

你得到的错误是什么?在打开它以查看支持的像素格式之后,检查编码上下文,您可能需要使用sws_scale来转换成编码器支持的格式。