C++ Ffmpeg mpg到jpg

C++ Ffmpeg mpg到jpg,c++,ffmpeg,frame,libavcodec,libav,C++,Ffmpeg,Frame,Libavcodec,Libav,我想将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_MJPE

我想将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;
}
int将帧另存为jpeg(AVCodecContext*pCodecCtx,AVFrame*pFrame,int FrameNo){
//AVCodec*jpegCodec=AVCodec\U find\U编码器(AV\U CODEC\U ID\U JPEG2000);
AVCodec*jpegCodec=AVCodec\U find\U编码器(AV\U CODEC\U ID\U MJPEG);
如果(!JPEG编解码器){
返回-1;
}
AVCodecContext*jpegContext=avcodec\u alloc\u context3(jpegCodec);
如果(!JPEG上下文){
返回-1;
}
jpegContext->pix_fmt=pCodecCtx->pix_fmt;
jpegContext->height=pFrame->height;
jpegContext->width=pFrame->width;
jpegContext->time\u base=pCodecCtx->time\u base;
如果(avcodec_open2(JPEG上下文,JPEG编解码器,NULL)<0){
返回-1;
}
文件*JPEG文件;
字符JPEGFName[256];
//AVPacket packet={.data=NULL,.size=0};
数据包;
av_初始_数据包(&数据包);
int-gotFrame;
如果((avcodec_发送_数据包(JPEG上下文和数据包))<0){
返回-1;
}
如果((avcodec_接收_帧(JPEG上下文,pFrame))<0){
返回-1;
}
sprintf(JPEGFName,“dvr-%06d.jpg”,帧号);
JPEGFile=fopen(JPEGFName,“wb”);
fwrite(packet.data,1,packet.size,JPEG文件);
fclose(jpeg文件);
av_数据包_unref(&packet);
avcodec_关闭(JPEG上下文);
返回0;
}
静态无效解码(AVCodecContext*dec_ctx、AVFrame*frame、AVPacket*pkt)
{
char-buf[1024];
int ret;
ret=avcodec\U send\U数据包(dec\U ctx,pkt);
如果(ret<0){
fprintf(stderr,“发送数据包进行解码时出错”);
出口(1);
}
而(ret>=0){
ret=avcodec_接收_帧(dec_ctx,帧);
如果(ret==AVERROR(EAGAIN)| | ret==AVERROR_EOF)
返回;
否则如果(ret<0){
fprintf(stderr,“解码过程中的错误”);
出口(1);
}
printf(“保存帧%3d\n”,dec\u ctx->帧号);
fflush(stdout);
文件*iFile=fopen(buf,“rb”);
fseek(iFile,0,SEEK_END);
大小\u t fileLen=ftell(iFile);
fseek(iFile,0,SEEK_SET);
unsigned char*fileData=新的unsigned char[fileLen];
fread(fileData,1,fileLen,iFile);
fclose(iFile);
getchar();
}
}
int main()
{
av_寄存器_all();
avcodec_寄存器_all();
avdevice_register_all();
avfilter_register_all();
const char*filename=“video.mpg”;
AVFormatContext*format_context=NULL;
int-ret=-1;
ret=avformat\u open\u输入(&format\u上下文,文件名,NULL,NULL);
如果(ret<0){
printf(“无法打开文件。文件名=%s,ret=%08x\n”,文件名,AVERROR(ret));
返回-1;
}
ret=avformat\u find\u stream\u info(format\u context,NULL);
如果(ret<0){
printf(“avformat\u find\u stream\u info error.ret=%08x\n”,AVERROR(ret));
返回-1;
}
AVStream*video_stream=NULL;
对于(无符号整数i=0;inb\u streams;i++){
如果(格式化上下文->流[i]->codepar->编解码器类型==AVMediaType::AVMediaType\U视频){
//找到视频流
视频流=格式上下文->流[i];
打破
}
}
如果(视频流==NULL){
printf(“未找到视频\n流”);
返回-1;
}
AVCodec*video\u codec=AVCodec\u find\u解码器(视频流->编解码器->编解码器id);
if(视频编解码器==NULL){
printf(“avcodec\u find\u解码器codec未找到。codec\u id=%d\n”,video\u stream->codepar->codec\u id);
返回-1;
}
AVCodecContext*video\u codec\u context=avcodec\u alloc\u context3(video\u codec);
if(视频编解码器上下文==NULL){
printf(“avcodec\u alloc\u context3错误。\n”);
返回-1;
}
ret=avcodec_open2(视频编解码器_上下文,视频编解码器,空);
如果(ret<0){
printf(“avcodec_open2错误。ret=%08x\n”,averor(ret));
返回-1;
}
AVFrame*frame=av_frame_alloc();
数据包;
int frame_number=0;
而(1){
//读ES
如果((ret=av_读取_帧(格式、上下文和数据包))<0){
printf(“av_read_frame eof or error.ret=%08x\n”,AVERROR(ret));
break;//eof或错误
}
if(packet.stream\u index==视频流->索引){
//解码视频
如果((ret=avcodec\U send\U数据包(视频\U codec\U上下文和数据包))<0){
printf(“avcodec\u send\u数据包错误。ret=%08x\n”,averor(ret));
}
如果((ret=avcodec_接收_帧(视频_codec_上下文,帧))<0){
if(ret!=averor(EAGAIN)){
printf(“avcodec\u receive\u frame error.ret=%08x\n”,averor(ret));
打破
}
}
否则{
if(数据包大小)
解码(视频、编解码器、上下文、帧和数据包);
printf(“解码完成。帧号=%d\n”,++帧号);
将帧另存为jpeg(视频编解码器上下文、帧、帧编号);
getchar();
}
}
否则{
//不录像。
}
av_数据包_unref(&packet);
}
getchar();//等待用户输入
返回0;
}
这一错误浮出水面

[mjpeg@00000 2889038FB80]指定的像素格式yuv420p无效 还是不支持

此行出错:

avcodec\u open2(jpegContext,jpegCodec,NULL)

我不明白这个错误。有人能帮我吗