Ffmpeg MPG в JPG - PullRequest
       29

Ffmpeg MPG в JPG

0 голосов
/ 26 сентября 2018

Я хочу преобразовать кадры видеофайла в формате MPG в изображения JPEG.

Ниже приведен код, который я пробовал

int save_frame_as_jpeg(AVCodecContext *pCodecCtx, AVFrame *pFrame, int FrameNo) {

    //AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
    AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!jpegCodec) {
        return -1;
    }
    AVCodecContext *jpegContext = avcodec_alloc_context3(jpegCodec);
    if (!jpegContext) {
        return -1;
    }

    jpegContext->pix_fmt = pCodecCtx->pix_fmt;
    jpegContext->height = pFrame->height;
    jpegContext->width = pFrame->width;
    jpegContext->time_base = pCodecCtx->time_base;

    if (avcodec_open2(jpegContext, jpegCodec, NULL) < 0) {
        return -1;
    }
    FILE *JPEGFile;
    char JPEGFName[256];

    //AVPacket packet = { .data = NULL,.size = 0 };
    AVPacket packet;
    av_init_packet(&packet);
    int gotFrame;

    if (( avcodec_send_packet(jpegContext, &packet)) < 0) {
        return -1;
    }
    if (( avcodec_receive_frame(jpegContext, pFrame)) < 0) {
        return -1;      
    }
    sprintf(JPEGFName, "dvr-%06d.jpg", FrameNo);
    JPEGFile = fopen(JPEGFName, "wb");
    fwrite(packet.data, 1, packet.size, JPEGFile);
    fclose(JPEGFile);

    av_packet_unref(&packet);
    avcodec_close(jpegContext);
    return 0;
}

static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
{


    char buf[1024];
    int ret;

    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Error sending a packet for decoding\n");
        exit(1);
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(dec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during decoding\n");
            exit(1);
        }

        printf("saving frame %3d\n", dec_ctx->frame_number);
        fflush(stdout);

        FILE *iFile = fopen(buf, "rb");
        fseek(iFile, 0, SEEK_END);
        size_t fileLen = ftell(iFile);
        fseek(iFile, 0, SEEK_SET);

        unsigned char* fileData = new unsigned char[fileLen];
        fread(fileData, 1, fileLen, iFile);
        fclose(iFile);

        getchar();
    }
}

int main()
{

    av_register_all();
    avcodec_register_all();
    avdevice_register_all();
    avfilter_register_all();

    const char *filename = "video.mpg";

    AVFormatContext *format_context = NULL;

    int ret = -1;
    ret = avformat_open_input(&format_context, filename, NULL, NULL);
    if (ret < 0) {
        printf("cannot open file. filename=%s, ret=%08x\n", filename, AVERROR(ret));
        return -1;
    }

    ret = avformat_find_stream_info(format_context, NULL);
    if (ret < 0) {
        printf("avformat_find_stream_info error. ret=%08x\n", AVERROR(ret));
        return -1;
    }

    AVStream *video_stream = NULL;
    for (unsigned int i = 0; i < format_context->nb_streams; i++) {
        if (format_context->streams[i]->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO) {
            // found Video stream
            video_stream = format_context->streams[i];
            break;
        }
    }
    if (video_stream == NULL) {
        printf("video_stream not found\n");
        return -1;
    }

    AVCodec *video_codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
    if (video_codec == NULL) {
        printf("avcodec_find_decoder codec not found. codec_id=%d\n", video_stream->codecpar->codec_id);
        return -1;
    }

    AVCodecContext *video_codec_context = avcodec_alloc_context3(video_codec);
    if (video_codec_context == NULL) {
        printf("avcodec_alloc_context3 error.\n");
        return -1;
    }

    ret = avcodec_open2(video_codec_context, video_codec, NULL);
    if (ret < 0) {
        printf("avcodec_open2 error. ret=%08x\n", AVERROR(ret));
        return -1;
    }

    AVFrame *frame = av_frame_alloc();
    AVPacket packet;
    int frame_number = 0;
    while (1) {
        // read ES
        if ((ret = av_read_frame(format_context, &packet)) < 0) {
            printf("av_read_frame eof or error. ret=%08x\n", AVERROR(ret));
            break; // eof or error
        }
        if (packet.stream_index == video_stream->index) {
            // decode Video ES
            if ((ret = avcodec_send_packet(video_codec_context, &packet)) < 0) {
                printf("avcodec_send_packet error. ret=%08x\n", AVERROR(ret));
            }
            if ((ret = avcodec_receive_frame(video_codec_context, frame)) < 0) {
                if (ret != AVERROR(EAGAIN)) {
                    printf("avcodec_receive_frame error. ret=%08x\n", AVERROR(ret));
                    break;
                }
            }
            else {

                if (packet.size)
                    decode(video_codec_context, frame, &packet);

                printf("decode finished. frame_number=%d\n", ++frame_number);

                save_frame_as_jpeg(video_codec_context, frame, frame_number);
                getchar();
            }
        }
        else {
            // does not Video ES.
        }
        av_packet_unref(&packet);
    }

    getchar(); // wait user input

    return 0;
}

Эта ошибка появилась

[mjpeg @ 000002889038fb80] Указанный формат пикселя yuv420p недопустим или не поддерживается

ошибка этой строки:

avcodec_open2(jpegContext, jpegCodec, NULL)

Я могу 'Не могу понять ошибку. Может ли кто-нибудь мне помочь?

...