實(shí)現(xiàn)最小YUV視頻解碼器

本文記錄了使用ffmpeg進(jìn)行視頻解碼的最小解碼器代碼莽红,通過這個(gè)小程序可以理解ffmpeg的解碼過程及用到的api。這里將解碼碼后得到的YUV格式的視頻保存到文件中船老,可以使用YUV Playe播放。代碼已上傳git圃酵,
https://github.com/beijixing/ffmpegStudy

流程圖.jpg

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}

void devoder()
{
    //注冊(cè)編解碼器
    av_register_all();

    AVFormatContext *pAVFormatCtx = NULL;
    int ret = avformat_open_input(&pAVFormatCtx,"Titanic.mkv",NULL, NULL);
    if(ret != 0)
    {
        printf("avformat_open_input failed!");
        return;
    }

    //查找流信息
    ret = avformat_find_stream_info(pAVFormatCtx, NULL);
    if(ret != 0)
    {
        printf("avformat_find_stream_info failed!");
        return;
    }

    //查找視頻流索引
   int videoIndex = -1;
   videoIndex = av_find_best_stream(pAVFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL);
   if(videoIndex < 0)
   {
       printf("av_find_best_stream failed!");
       return;
   }

   //查找解碼器上下文
   AVCodecContext *pAVCodecCtx = pAVFormatCtx->streams[videoIndex]->codec;
   //查找解碼器
   AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecCtx->codec_id);

   if(pAVCodec == NULL)
   {
       printf("Codec not found.\n");
       return;
   }
    //打開解碼器
   ret = avcodec_open2(pAVCodecCtx, pAVCodec, NULL);
   if(ret < 0)
   {
       printf("avcodec_open2 failed !\n");
       return;
   }

   //解碼視頻
   AVFrame *pAVFrame = av_frame_alloc();
   AVFrame *pAVFrameYUV = av_frame_alloc();

   //創(chuàng)建緩存
   int nBuffSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pAVCodecCtx->width, pAVCodecCtx->height, 1);
   unsigned char* buffer = (unsigned char *)av_malloc(nBuffSize);
   //設(shè)置緩存
   av_image_fill_arrays(pAVFrameYUV->data, pAVFrameYUV->linesize, buffer,
                        AV_PIX_FMT_YUV420P, pAVCodecCtx->width,
                        pAVCodecCtx->height, 1);
   //創(chuàng)建AVPacket
   AVPacket *pAVPacket = (AVPacket *)av_malloc(sizeof (AVPacket));
   //創(chuàng)建圖像轉(zhuǎn)換上下文
   SwsContext *pSwsCtx = sws_getContext(pAVCodecCtx->width, pAVCodecCtx->height,
                                       pAVCodecCtx->pix_fmt, pAVCodecCtx->width, pAVCodecCtx->height,
                                        AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);


   int gotPicture = 0;
   FILE* pYuvFile = fopen("test.yuv", "wb");
   if(!pYuvFile)
   {
       printf("fopen test.yuv failed !\n");
       return;
   }

   int frameCnt = 0;
   while (av_read_frame(pAVFormatCtx, pAVPacket) >= 0)
   {
       //只解碼視頻
       if(pAVPacket->stream_index == videoIndex)
       {
            ret = avcodec_decode_video2(pAVCodecCtx, pAVFrame, &gotPicture, pAVPacket);
            if(ret < 0)
            {
                printf("avcodec_decode_video2 failed !\n");
                break;
            }
            if(gotPicture)
            {
                //格式轉(zhuǎn)換
                sws_scale(pSwsCtx, pAVFrame->data,
                          pAVFrame->linesize,
                          0,
                          pAVCodecCtx->height,
                          pAVFrameYUV->data,
                          pAVFrameYUV->linesize);
                fwrite(pAVFrameYUV->data[0],1,pAVCodecCtx->width*pAVCodecCtx->height, pYuvFile);
                fwrite(pAVFrameYUV->data[1],1,pAVCodecCtx->width*pAVCodecCtx->height/4, pYuvFile);
                fwrite(pAVFrameYUV->data[2],1,pAVCodecCtx->width*pAVCodecCtx->height/4, pYuvFile);
                frameCnt++;
                printf("frameCnt = %d !\n", frameCnt);
            }

       }
   }

   //釋放指針
   fclose(pYuvFile);
   sws_freeContext(pSwsCtx);
   av_frame_free(&pAVFrame);
   av_frame_free(&pAVFrameYUV);
   av_packet_free(&pAVPacket);
   avformat_close_input(&pAVFormatCtx);
}


int main(int argc, char *argv[])
{
    devoder();
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市捌锭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌观谦,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豁状,死亡現(xiàn)場(chǎng)離奇詭異捉偏,居然都是意外死亡泻红,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門讹躯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人潮梯,你說我怎么就攤上這事〔夜В” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵喉恋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我轻黑,道長(zhǎng),這世上最難降的妖魔是什么氓鄙? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮抖拦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘态罪。我一直安慰自己噩茄,他們只是感情好复颈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耗啦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帜讲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天似将,我揣著相機(jī)與錄音蚀苛,去河邊找鬼。 笑死肢执,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的预茄。 我是一名探鬼主播兴溜,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拙徽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了膘怕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岛心,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后忘古,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诅诱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了干旁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡争群,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出大年,到底是詐尸還是另有隱情,我是刑警寧澤鲜戒,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布抹凳,位于F島的核電站,受9級(jí)特大地震影響赢底,放射性物質(zhì)發(fā)生泄漏失都。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一咳焚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧庞溜,春花似錦、人聲如沸流码。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至驾荣,卻和暖如春外构,著一層夾襖步出監(jiān)牢的瞬間播掷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工叮趴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人眯亦。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像妻率,于是被迫代替她去往敵國(guó)和親乱顾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宫静,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容