FFmpeg:avcodec_encode_video()和JPEG图像

时间:2011-07-20 03:12:04

标签: c linux video ffmpeg jpeg

我正在尝试使用ffmpeg库将一系列.jpg文件编码为视频,而我似乎无法获得要编码的帧。 (我必须使用ffmpeg库,在我的情况下使用命令行中的ffmpeg不是一个选项。)

除了我试图将JPG文件作为AVFrames打开的​​部分之外,我的代码与ffmpeg库中的api-example.c中的代码大致相同。当我像示例那样填充框架时,一切都按预期工作。在下面的代码中,我无法编码任何帧。显然问题与我打开JPG文件的方式有关,但我无法弄清楚是什么。

我正在打开这样的图像:

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);
        }
    }
}

...并试图像这样编码:

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;
}

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

1 个答案:

答案 0 :(得分:1)

你得到的错误究竟是什么?打开后检查编码上下文以查看支持的像素格式,您可能必须使用sws_scale转换为编码器支持的格式。