作者:星隕
來源:
音視訊開發進階有了上一篇文章基礎,這裡就隻關注 FFmpeg 如何解析的具體實踐了。
在開始工程之前,第一步要做的就是編譯 FFmpeg 源碼,生成 Android 平台上使用的 so 庫。
在生成完了之後,導入 Android 工程項目中,并且配置 CMake 檔案,添加對應的庫,就可以開始開發了。
如果覺得麻煩,也可以直接從網上找一個工程使用現成的東西,也可以參考的我的學習項目:
https://github.com/glumes/FFMPEGLearnFFmpeg 3.0 與 2.0 的不同之處
如果是剛開始學習,完全可以參照雷神的部落格來寫例子,而且還能運作成功。不過,既然 FFmpeg 都出了 3.0 版本了,還是要跟進學習一下。
可以看到,在具體解析操作時發生了變化,不再是之前的
avcodec_decode_video2
函數,而是拆分成了兩個函數,
avcodec_send_packet
和
avcodec_receive_frame
。
avcodec_send_packet
負責發送編碼壓縮後的資料,也就是 Packet 資料,而
avcodec_receive_frame
負責接收解碼後的原始資料,也就是 Frame 資料,這麼一來一回的配合,每次從檔案中讀取一部分内容,直到将整個檔案解碼完成。
解碼流程代碼
FFmpge 的解碼流程大都是相同的,隻是在細節地方會有差異,主體流程還是沒變,看了好多解碼的代碼,大多也是這樣的,隻是在解碼成具體的某些格式時,對原始資料 Frame 的操作會有不同。
// 聲明一堆待會要用到的變量
AVCodecContext *avCodecContext = nullptr;
AVCodec *avCodec = nullptr;
AVCodecParserContext *parserContext = nullptr;
AVPacket *packet;
AVFrame *frame;
// 為上面聲明的變量在指派,并且檢查指派是否成功
avcodec_register_all()
// 為解碼器指派,并制定解碼器類型
avCodec = avcodec_find_decoder(AV_CODEC_ID_HEVC);
// 為 AVCodecParserContext 和 AVCodecContext 指派
parserContext = av_parser_init(avCodec->id);
avCodecContext = avcodec_alloc_context3(avCodec);
// 打開解碼器
avcodec_open2(avCodecContext, avCodec, nullptr);
// 為 Packet 和 Frame 指派
frame = av_frame_alloc();
packet = av_packet_alloc();
while // 開始一點點的解碼檔案内容,直到檔案末尾
// 解碼從 while 中一次讀取到的内容
av_parser_parse2
// 發送讀取到的 packet
avcodec_send_packet
// 接收解析完的 frame
avcodec_receive_frame
// 對原生資料進行相關操作,解碼成不同資料格式,操作不同。
// todo
//最後,釋放上面聲明的變量
av_frame_free
av_packet_free
avcodec_free_context
av_parser_close
MPEG->PCM 的解碼
在了解視訊檔案的相關基礎以及 FFmpeg 解碼的大緻流程後,就可以開始進行 MPEG->PCM 的解碼工作了。
不過,在這裡還是少了兩個重要的概念:
- FFmpeg 各種類以及變量的含義。
- 各種音視訊檔案的格式協定。
前半部分還好,對着雷神的部落格一點點的看,還是能看懂的。至于各種音視訊檔案的協定,那就要靠慢慢積累了。
這裡就不貼上全部的代碼了,可以參考如下兩個地方:
- http://ffmpeg.org/doxygen/trunk/decode_video_8c-example.html
- https://github.com/glumes/FFMPEGLearn/blob/master/FFmpegLib/src/main/cpp/ffmpeg_examples/decode_video.cpp
參考
「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SOlFjYkBTY1kjYiNDZ5YGOilDN0cTYmJjMhhjMzMDNx8CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)