基于ffmpeg提取視頻中的i幀p幀

int mp4_to_yuv(char * input_path, char * output_path)
{
    //1、注冊(cè)所有組件
    av_register_all();

    //2、打開(kāi)視頻文件
    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、打開(kāi)解碼器
    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、解析每一幀數(shù)據(jù)
    int got_picture_ptr, frame_count = 1;
    //壓縮數(shù)據(jù)
    AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));
    //解壓縮數(shù)據(jù)
    AVFrame *frame = av_frame_alloc();
    AVFrame *yuvFrame = av_frame_alloc();

    //將視頻轉(zhuǎn)換成指定的420P的YUV格式
    //緩沖區(qū)分配內(nèi)存
    uint8_t *out_buffer = (uint8_t *) av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height));

    //初始化緩沖區(qū)
    avpicture_fill((AVPicture *) yuvFrame, out_buffer, AV_PIX_FMT_YUV420P, pCodeCtx->width,
                   pCodeCtx->height);
    //用于像素格式轉(zhuǎn)換或者縮放
    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");
    //一幀一幀讀取壓縮的視頻數(shù)據(jù)
    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,轉(zhuǎn)為指定的YUV420P像素幀
                    sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
                              frame->height, yuvFrame->data, yuvFrame->linesize);
                    //計(jì)算視頻數(shù)據(jù)總大小
                    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,轉(zhuǎn)為指定的YUV420P像素幀
                    sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
                              frame->height, yuvFrame->data, yuvFrame->linesize);
                    //計(jì)算視頻數(shù)據(jù)總大小
                    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;   
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • https://my.oschina.net/ShengTcai/blog/850020 關(guān)于FFMPEG 中I幀...
    JosephDHF閱讀 5,171評(píng)論 3 1
  • 說(shuō)起家里青春期孩子的臭美舉動(dòng),幾個(gè)家長(zhǎng)滔滔不絕 : 校服褲子改窄改短;書(shū)包里帶身漂亮衣服,放學(xué)再換上(包括...
    不在遠(yuǎn)方而在日常閱讀 438評(píng)論 0 0
  • 【日精進(jìn)打卡第23天】【知~學(xué)習(xí)】《六項(xiàng)精進(jìn)》1遍 共28遍《大學(xué)》1遍 共28遍【經(jīng)典名句分享】不讓未來(lái) 后悔,...
    like001閱讀 84評(píng)論 0 0
  • 盡興的陪孩子玩了一天,然后就是腰酸背痛困的睡了幾乎一天。小孩子的恢復(fù)力真是驚人,而我現(xiàn)在的體質(zhì)和恢復(fù)力,讓我真的開(kāi)...
    芮靈翾閱讀 579評(píng)論 0 0
  • 一個(gè)詞足以表達(dá)我此刻內(nèi)心的感受。順暢!從開(kāi)始到結(jié)尾,每一個(gè)細(xì)胞都在這種順暢的享受當(dāng)中歡呼雀躍。這就是讓我欣喜的好巧...
    腳下日月閱讀 807評(píng)論 2 5

友情鏈接更多精彩內(nèi)容