基于ffmpeg提取视频中的i帧p帧

int mp4_to_yuv(char * input_path, char * output_path)
{
    //1、注册所有组件
    av_register_all();

    //2、打开视频文件
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    if ((avformat_open_input(&pFormatCtx, input_path, NULL, NULL)) < 0) 
    {       
        printf("Cannot open input file");
        return -1;
    }

    //3、获取视频信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
    {       
        printf("Cannot find stream\n");
        if(pFormatCtx)
            avformat_free_context(pFormatCtx);
        avformat_close_input(&pFormatCtx);
        return -1;
    }

    //4、找到视频流的位置
    int video_stream_index = -1;
    int i = 0;
    for (; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            video_stream_index = i;
            //av_log(pFormatCtx, AV_LOG_ERROR, "find the stream index %d.\n", video_stream_index);
            //LOGE("find the stream index %d", video_stream_index);
            break;
        }
    }

    //5、获取解码器
    AVCodecContext *pCodeCtx = pFormatCtx->streams[video_stream_index]->codec;
    int width = pCodeCtx->width;
    int height = pCodeCtx->height;

    AVCodec *pCodec = avcodec_find_decoder(pCodeCtx->codec_id);
    if (pCodec == NULL)
    {
        av_log(pFormatCtx, AV_LOG_ERROR, "Cannot find decoder.\n");
       if(pFormatCtx)
            avformat_free_context(pFormatCtx);
        avformat_close_input(&pFormatCtx);
        return -1;
    }

    //6、打开解码器
    if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0)
    {
        printf("Cannot open codec\n");
        if(pFormatCtx)
            avformat_free_context(pFormatCtx);
        avformat_close_input(&pFormatCtx);
        return -1;
    }
    //7、解析每一帧数据
    int got_picture_ptr, frame_count = 1;
    //压缩数据
    AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));
    //解压缩数据
    AVFrame *frame = av_frame_alloc();
    AVFrame *yuvFrame = av_frame_alloc();

    //将视频转换成指定的420P的YUV格式
    //缓冲区分配内存
    uint8_t *out_buffer = (uint8_t *) av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height));

    //初始化缓冲区
    avpicture_fill((AVPicture *) yuvFrame, out_buffer, AV_PIX_FMT_YUV420P, pCodeCtx->width,
                   pCodeCtx->height);
    //用于像素格式转换或者缩放
    struct SwsContext *sws_ctx = sws_getContext(pCodeCtx->width, pCodeCtx->height, pCodeCtx->pix_fmt,pCodeCtx->width, pCodeCtx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);

    //输出文件
    FILE *fp_yuv = fopen(output_path, "wb");
    //一帧一帧读取压缩的视频数据
    while (av_read_frame(pFormatCtx, packet) >= 0)
    {
        //找到视频流
        if (packet->stream_index == video_stream_index)
        {
            avcodec_decode_video2(pCodeCtx, frame, &got_picture_ptr, packet);
            
            //提取p帧,和i帧
            if((frame->pict_type == AV_PICTURE_TYPE_I) || (frame->pict_type == AV_PICTURE_TYPE_P))
            {
                printf("this is i PICTURE\n");
                //正在解码
                if (got_picture_ptr)
                {
                    //frame->yuvFrame,转为指定的YUV420P像素帧
                    sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
                              frame->height, yuvFrame->data, yuvFrame->linesize);
                    //计算视频数据总大小
                    int y_size = pCodeCtx->width * pCodeCtx->height;
                    //AVFrame->YUV,由于YUV的比例是4:1:1
                    fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
                    fwrite(yuvFrame->data[1], 1, y_size / 4, fp_yuv);
                    fwrite(yuvFrame->data[2], 1, y_size / 4, fp_yuv);                    
                }
            }
            
            //提取b帧
            /*
            if(frame->pict_type == AV_PICTURE_TYPE_B)
            {               
                //正在解码
                if (got_picture_ptr)
                {
                    //frame->yuvFrame,转为指定的YUV420P像素帧
                    sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
                              frame->height, yuvFrame->data, yuvFrame->linesize);
                    //计算视频数据总大小
                    int y_size = pCodeCtx->width * pCodeCtx->height;
                    //AVFrame->YUV,由于YUV的比例是4:1:1
                    fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
                    fwrite(yuvFrame->data[1], 1, y_size / 4, fp_yuv);
                    fwrite(yuvFrame->data[2], 1, y_size / 4, fp_yuv);                   
                }               
            }
            */
                        
            //释放packet
            av_packet_unref(packet);
        }
    }
    //8、释放资源
    fclose(fp_yuv);
    av_frame_free(&frame);
    av_frame_free(&yuvFrame);
    avcodec_close(pCodeCtx);
    av_free(out_buffer);
    avformat_free_context(pFormatCtx);
  
  return 0;
}




int main()
{
    
    mp4_to_yuv("/home/file/testvideo.mp4",
                "/home/file/testvideo.yuv");
    
    
    return 0;   
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容