FFmpeg: avcodec_encode_video () и изображения JPEG - PullRequest
2 голосов
/ 20 июля 2011

Я пытаюсь закодировать серию файлов .jpg в видео, используя библиотеку ffmpeg, и я не могу заставить кадры кодировать.(Я должен использовать библиотеку ffmpeg, и использование ffmpeg из командной строки в моем случае не вариант.)

За исключением части, в которой я пытаюсь открыть файлы JPG как AVFrames, мой кодболее или менее то же самое, что и в api-example.c из библиотеки ffmpeg.Когда я заполняю фреймы, как в примере, все работает как положено.В приведенном ниже коде я не могу кодировать какие-либо кадры.Очевидно, проблема связана с тем, как я открываю файлы 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 Ответ

1 голос
/ 02 февраля 2012

Какую именно ошибку вы получаете?Изучите контекст Encoding после его открытия, чтобы увидеть поддерживаемые форматы пикселей. Возможно, вам придется использовать sws_scale для преобразования в формат, поддерживаемый кодировщиком.

...