FFmpeg簡單使用:過濾器 ---- h264_mp4toannexb


=====================================================

FFmpeg簡單使用:解封裝 ---- 基本流程

FFmpeg簡單使用:解封裝 ---- 提取aac

FFmpeg簡單使用:音頻解碼 ---- 提取pcm

FFmpeg簡單使用:視頻解碼 ---- 提取yuv

FFmpeg簡單使用:音頻編碼 ---- pcm轉aac

FFmpeg簡單使用:視頻編碼 ---- YUV轉H264

FFmpeg簡單使用:過濾器 ---- 視頻過濾

FFmpeg簡單使用:過濾器 ---- 視頻過濾2

FFmpeg簡單使用:過濾器 ---- h264_mp4toannexb

FFmpeg簡單使用:解封裝h264 ---- 提取SPS PPS

=====================================================

H264有兩種封裝方式:字節流AnnexB格式 AVCC格式。

1. AnnexB格式 ---- 用於實時播放

開始前綴(00000001或000001)+NALU數據  絕大部分編碼器的默認輸出格式
  一共有兩種起始碼start_code
   ①3字節0x000001  單幀多slice(即單幀多個NALU)之間間隔
   ②4字節0x00000001 幀之間,或者SPS等之前
4字節類型的開始碼在在連續的數據傳輸中非常有用,因為用字節來對齊、分割流數據,比如:用連續的31個bit0后接一個bit1來分割流數據,是很容易的。

AnnexB格式每個NALU都包含起始碼,且通常會周期性的在關鍵幀之前重復SPS和PPS
  👉👉👉所以解碼器可以從視頻流隨機點開始進行解碼,實時的流格式

 2. AVCC格式 ---- 用於存儲

AVCC格式不使用起始碼作為NALU的分界,這種格式在每個NALU前都加上一個大端格式的前綴(1、2、4字節,代表NALU長度)

所以在解析AVCC格式的時候需要將指定的前綴字節數的值保存在一個頭部對象中,這個都通常稱為extradata或者sequence header。同時,SPS和PPS數據也需要保存在extradata或者叫’sequence header’中。

3.AVPacket數據格式

AVPacket中的data格式是:size(4個字節)+ nalu + size(4個字節)+ nalu,一個packet可能會存在多個nalu,前面size表示nalu的大小(不包含自身)

圖1.

 

如圖1所示,前4個字節表示:第一個nalu大小是0x52d = 1325, 總的pkt的大小是66736。表示存在多個nalu。下一個nalu位置:0x7dc0 + 0x025d + 4 = 0x8021,如圖2所示

圖2.

 

 

 4.AVPacket轉換為 AnnexB,使用h264_mp4toannexb

編碼:

 // 1 獲取相應的比特流過濾器
    // FLV/MP4/MKV等結構中,h264需要h264_mp4toannexb處理。添加SPS/PPS等信息。
    // FLV封裝時,可以把多個NALU放在一個VIDEO TAG中,結構為4B NALU長度+NALU1+4B NALU長度+NALU2+...,
    // 需要做的處理把4B長度換成00000001或者000001
    // annexb模式: startcode 00000001 AVCC模式: 無startcode (mp4 flv mkv)
    const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
    AVBSFContext *bsf_ctx = NULL;
    // 2 初始化過濾器上下文
    av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;
    // 3 添加解碼器屬性
    avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar);
    av_bsf_init(bsf_ctx);

   // 4 發送和接受
if (av_bsf_send_packet(bsf_ctx, pkt) != 0) // bitstreamfilter內部去維護內存空間 { av_packet_unref(pkt); // 你不用了就把資源釋放掉 continue; // 繼續送 } av_packet_unref(pkt); // 釋放資源 while(av_bsf_receive_packet(bsf_ctx, pkt) == 0) { out_pkt_count++; // printf("fwrite size:%d\n", pkt->size); av_packet_unref(pkt); }

我們看看filter之后的數據:

圖3.

 

 我們可以看到,和圖1相比size變為00 00 00 01.下面我們看下一幀

圖4.

 

 我們可以看到,下一個並不是簡單變為00 00 00 01,而是插入了一個nalu,再下一個nalu(f885位置),才是之前的nalu。我們分析一下中間插入的nalu,看第一下第一個字節表示nalu header.

NALU header格式:

0x67:

F:0 默認為0

R :11 表示這個幀很重要

T:7 表示SPS,到這里可以看出,插入了一個filter

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM