存储h264码流使用什么文件格式
答案:2 悬赏:0 手机版
解决时间 2021-02-27 23:41
- 提问者网友:听门外雪花风
- 2021-02-27 11:39
存储h264码流使用什么文件格式
最佳答案
- 五星知识达人网友:污到你湿
- 2021-02-27 12:04
H264可以用很多容器封装,也就是你所说的文件格式封装
一般主流的H264封装文件格式有,TS,MP4,MKV,FLV,M3U8(就是TS分片)等等
一般主流的H264封装文件格式有,TS,MP4,MKV,FLV,M3U8(就是TS分片)等等
全部回答
- 1楼网友:爱难随人意
- 2021-02-27 12:59
mp4的视频h264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略。笔者也是在改编live555流媒体时,增加mp4文件类型支持时遇到了该问题。
(一)首先,从原理上了解一下这2种格式的区别:
avc1 描述:h.264 bitstream without start codes.一般通过ffmpeg转码生成的视频,是不带起始码0×00000001的。
h264 描述:h.264 bitstream with start codes.一般对于一下hdvd等电影的压制格式,是带有起始码0×00000001的。
(二)其次,通过vlc播放器,可以查看到具体的格式。打开视频后,通过菜单【工具】/【编解码信息】可以查看到【编解码器】具体格式,举例如下,编解码器信息:
编码: h264 – mpeg-4 avc (part 10) (avc1)
编码: h264 – mpeg-4 avc (part 10) (h264)
(三)最后,分享一下ffmpeg demux mp4文件后,转换视频流为live555可直接使用的h264 es流的经验和方法:
针对(avc1),av_read_frame后,取前四个字节为长度,把前四字节直接替换为0×00,0×00,0×00,0×01即可,但注意每个frame可以有多个naul:
avpacket pkt;
avpacket* packet = &pkt;
av_init_packet(packet);
av_read_frame(ctx, packet);
if(packet->stream_index == 0)
{//is video stream
const char start_code[4] = { 0, 0, 0, 1 };
if(is_avc_ || memcmp(start_code, packet->data, 4) != 0)
{//is avc1 code, have no start code of h264
int len = 0;
uint8_t *p = packet->data;
is_avc_ = true;
do
{//add start_code for each nal, one frame may have multi nals.
len = ntohl(*((long*)p));
memcpy(p, start_code, 4);
p += 4;
p += len;
if(p >= packet->data + packet->size)
{
break;
}
} while (1);
}
}
对于另外一种格式,(h264), 则直接对每个packet调用av_bitstream_filter_filter处理每个packet即可:
bsfc_ = av_bitstream_filter_init("h264_mp4toannexb");
if(pkt->stream_index == 0)
{//is video stream
avbitstreamfiltercontext* bsfc = bsfc_;
int a;
while (bsfc) {
avpacket new_pkt = *pkt;
a = av_bitstream_filter_filter(bsfc, encode_ctx_, null,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & av_pkt_flag_key);
if(a == 0 && new_pkt.data != pkt->data && new_pkt.destruct) {
uint8_t *t = (uint8_t*)(new_pkt.size + ff_input_buffer_padding_size); //the new should be a subset of the old so cannot overflow
if(t) {
memcpy(t, new_pkt.data, new_pkt.size);
memset(t + new_pkt.size, 0, ff_input_buffer_padding_size);
new_pkt.data = t;
a = 1;
} else
a = averror(enomem);
}
if (a > 0 && pkt->data != new_pkt.data) {
av_free_packet(pkt);
new_pkt.destruct = av_destruct_packet;
} else if (a < 0) {
envir() << "!!!!!!!!!!av_bitstream_filter_filter failed" << ",res=" << a << "\n";
}
*pkt = new_pkt;
bsfc = bsfc->next;
}
}
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯