mux復用 demux解復用
阿新 • • 發佈:2017-08-09
字節 參數 只需要 表示 get 播放 手工 context 想要 保存音頻包:
直接輸出解復用之後的的音頻數據碼流。只需要在每次調用av_read_frame()之後將得到的音頻的AVPacket存為本地文件即可。
但在分離AAC碼流的時候,直接存儲AVPacket後的文件可能是不能播放的。 分離H.264碼流的時候,直接存儲AVPacket後的文件可能是不能播放的。
復用格式是FLV,MP4等,直接存儲後的文件是不能播放的。
因為FLV,MP4這些屬於“特殊容器”。經過仔細對比後發現,調用av_read_frame()後得到的AVPacket裏面的內容是AAC純數據,就是那種不包含ADTS文件頭的AAC數據。(存儲AAC數據的AVPacket的data字段中的數據是不包含7字節ADTS文件頭的數據)因此如果想要得到可以播放的AAC文件,需要在每個AVPacket前面加上7字節ADTS文件頭。
demux分離時,h264需要h264_mp4toannexb,音頻aac好像沒有用到
mux時,h264也需要h264_mp4toannexb,aac用到aac_adtstoasc
mux時對於某些封裝格式(例如MP4/FLV/MKV等)中的AAC,需要用到名稱為“aac_adtstoasc”的bitstream filter。
============================================================
保存視頻包:
分離某些封裝格式(例如MP4/FLV/MKV等)中的H.264的時候,需要首先寫入SPS和PPS
例如flv格式時,從av_read_frame中讀出的包也是不包含video tag header的裸視頻數據。
FLV,MP4這些“特殊容器”,需要經過以下2步處理才能得到可播放的H.264碼流: 1.第一次存儲AVPacket之前需要在前面加上H.264的SPS和PPS。這些信息存儲在AVCodecContext的extradata裏面。 並且需要使用FFMPEG中的名為"h264_mp4toannexb"的bitstream filter 進行處理。 然後將處理後的extradata存入文件 具體代碼如下: 代碼片段A
或
經過以上兩步處理之後,我們就得到了可以正常播放的H.264碼流 ====================================================
其它處理方式: (1)使用bitstream filter處理每個AVPacket(簡單) 把每個AVPacket中的數據(data字段)經過bitstream filter“過濾”一遍。關鍵函數是av_bitstream_filter_filter()。示例代碼如下。
經過上述代碼處理之後,AVPacket中的數據有如下變化: *每個AVPacket的data添加了H.264的NALU的起始碼{0,0,0,1} *每個IDR幀數據前面添加了SPS和PPS (2)手工添加SPS,PPS(稍微復雜) 將AVCodecContext的extradata數據經過bitstream filter處理之後得到SPS、PPS,拷貝至每個IDR幀之前。“代碼片段A”示例了寫入SPS、PPS的過程。
然後修改AVPacket的data。把前4個字節改為起始碼。參見:代碼片段B
參考: 視音頻分離器(demuxer):ts->h264+aac 利用av_interleaved_write_frame
視音頻復用器(muxer):h264+aac->mkv,用到av_interleaved_write_frame 分離多媒體文件中的音頻碼流
分離多媒體文件中的H.264碼流
視音頻分離器簡化版(demuxer-simple):flv->h264+aac
但在分離AAC碼流的時候,直接存儲AVPacket後的文件可能是不能播放的。 分離H.264碼流的時候,直接存儲AVPacket後的文件可能是不能播放的。
復用格式是FLV,MP4等,直接存儲後的文件是不能播放的。
因為FLV,MP4這些屬於“特殊容器”。經過仔細對比後發現,調用av_read_frame()後得到的AVPacket裏面的內容是AAC純數據,就是那種不包含ADTS文件頭的AAC數據。(存儲AAC數據的AVPacket的data字段中的數據是不包含7字節ADTS文件頭的數據)因此如果想要得到可以播放的AAC文件,需要在每個AVPacket前面加上7字節ADTS文件頭。
分離某些封裝格式(例如MP4/FLV/MKV等)中的H.264的時候,需要首先寫入SPS和PPS
例如flv格式時,從av_read_frame中讀出的包也是不包含video tag header的裸視頻數據。
FLV,MP4這些“特殊容器”,需要經過以下2步處理才能得到可播放的H.264碼流: 1.第一次存儲AVPacket之前需要在前面加上H.264的SPS和PPS。這些信息存儲在AVCodecContext的extradata裏面。 並且需要使用FFMPEG中的名為"h264_mp4toannexb"的bitstream filter 進行處理。 然後將處理後的extradata存入文件 具體代碼如下: 代碼片段A
-
unsigned char
- int dummy_len;
- AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb");
- av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &dummy, &dummy_len, NULL, 0, 0);
- fwrite(pCodecCtx->extradata,pCodecCtx-->extradata_size,1,fp);
- av_bitstream_filter_close(bsfc);
- free(dummy);
- char nal_start[]={0,0,0,1};
- fwrite(nal_start,4,1,fp);
- fwrite(pkt->data+4,pkt->size-4,1,fp);
- fclose(fp);
或
- char nal_start[]={0,0,0,1};
- memcpy(packet->data,nal_start,4);
經過以上兩步處理之後,我們就得到了可以正常播放的H.264碼流 ====================================================
其它處理方式: (1)使用bitstream filter處理每個AVPacket(簡單) 把每個AVPacket中的數據(data字段)經過bitstream filter“過濾”一遍。關鍵函數是av_bitstream_filter_filter()。示例代碼如下。
- AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
- while(av_read_frame(ifmt_ctx, &pkt)>=0){
- if(pkt.stream_index==videoindex){
- av_bitstream_filter_filter(h264bsfc, ifmt_ctx->streams[videoindex]->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
- fwrite(pkt.data,1,pkt.size,fp_video);
- //...
- }
- av_free_packet(&pkt);
- }
- av_bitstream_filter_close(h264bsfc);
經過上述代碼處理之後,AVPacket中的數據有如下變化: *每個AVPacket的data添加了H.264的NALU的起始碼{0,0,0,1} *每個IDR幀數據前面添加了SPS和PPS (2)手工添加SPS,PPS(稍微復雜) 將AVCodecContext的extradata數據經過bitstream filter處理之後得到SPS、PPS,拷貝至每個IDR幀之前。“代碼片段A”示例了寫入SPS、PPS的過程。
然後修改AVPacket的data。把前4個字節改為起始碼。參見:代碼片段B
參考: 視音頻分離器(demuxer):ts->h264+aac 利用av_interleaved_write_frame
視音頻復用器(muxer):h264+aac->mkv,用到av_interleaved_write_frame 分離多媒體文件中的音頻碼流
分離多媒體文件中的H.264碼流
視音頻分離器簡化版(demuxer-simple):flv->h264+aac
mux復用 demux解復用