手动编码为MPEG-TS [英] Manual encoding into MPEG-TS

查看:253
本文介绍了手动编码为MPEG-TS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SO ...



我正在尝试采用H264附件B字节流视频,并将其编码为纯Java中的MPEG-TS。我的目标是创建一个最小的MPEG-TS,单个程序,有效的流,并且不包括任何时间信息信息(PCR,PTS,DTS)。



我目前在我生成的文件可以被传递到ffmpeg(ffmpeg -i myVideo.ts)和ffmpeg报告的时候...

  [NULL @ 0x7f8103022600]开始时间未设置在estimate_timings_from_pts 

输入#0,mpegts,从'video.ts':
持续时间:N / A,比特率:N / A
程序1
流#0:0 [0x100]:视频:h264(主)([27] [0] [0] [0] / 0x001B),yuv420p(tv,bt709),1280x720 [SAR 1:1 DAR 16:9],29.97 fps,29.97 tbr,90k tbn,59.94 tbc

。 ..似乎这样的启动时间的警告并不是很大的事情,而ffmpeg无法确定视频多长时间。如果我从我的视频文件(ffmpeg -i myVideo.ts -vcodec copy validVideo.ts)创建另一个mpeg-ts文件,并运行ffmpeg -i validVideo.ts我得到...


$ b $持续时间:00:00:11.61,开始时间:1.400000,比特率:3325 kb / s,$ b $ $ $ $ $ $ b程序1
元数据:
service_name:Service01
service_provider:FFmpeg
流#0:0 [0x100]:视频:h264(主)([27] [0] [0] [0] / 0x001B),yuv420p(tv,bt709),1280x720 [SAR 1:1 DAR 16:9],29.97 fps,29.97 tbr,90k tbn,59.94 tbc

...所以你可以看到时间信息和比特率,元数据也是这样。



我的H264视频只包含I和P帧(当然是在I帧之前的SPS和PPS),我创建我的MPEG-TS流的方式是...


  1. 在文件开头写一个PAT

  2. 在文件的开头写一个PMT

  3. 创建TS和来自SPS,PPS和I帧的PES数据包(如果需要,也可以使用AUD NAL?)

  4. 从P帧创建TS和PES数据包(如果需要,再次为AUD NAL)

  5. 对于I帧或P帧的最后一个有效载荷,将填充字节添加到适配字段,以确保它适合完整的TS数据包

  6. 对整个文件重复3-5 ...

...我的PAT看起来像这样...

  4740 0010 0000 b00d 0001 c100 0000 01f0 
002a b104 b2ff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff

...我的PMT看起来像这样...

  4750 0010 
0002 b012 0001 c100 00ff fff0 001b e100
f000 c15b 41e0 ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff

...通知c100 00后,ff ff,f0 ...说我们不使用PCR ...还要注意,我已经更新我的CRC反映了PMT的这种变化。我的第一个I帧数据包看起来像...

  4741 0010 0000 01e0 
0000 8000 0000 0000 0109 f000 0000 0127
4d40 288d 8d60 2802 dd80 b501 0101 4000
00fa 4000 3a98 3a18 00b7 2000 3380 2ef2
e343 0016 e400 0670 05de 5c16 345d c000
0000 0128 ee3c 8000 0000 0165 8880 0020
0000 4fe5 63b5 4e90 b11c 9f8f f891 10f3
13b1 666b 9fc6 03e9 e321 36bf 1788 347b
eb23 fc89 5772 6e2e 1714 96df ed16 9b30
252d ceb7 07e9 a0c7 c6e7 9515 be87 2df1
81f3 b9d2 ba5f 243e 2d5c cba2 8ca5 b798
6bec 8c43 0b5d bbda bc5b 6e7c e15c 84e8
2f13 be84

...您会注意到01e0 0000之后,8000 00是PES标头扩展名,其中我没有指定PTS / DTS,剩余长度为零。我的第一个P帧包看起来像...

  4741 001d 
0000 01e0 0000 8000 0000 0000 0109 f000
0000 0141 9a00 0200 0593 ff45 a7ae 1acd
f2d7 f9ec 557f cdb6 ba38 60d6 a626 5edb
4bb9 9783 89e2 d7e1 102e 4625 2fbf ce16
f952 d8c9 f027 e55a 6b2a 81c3 48d4 6a45
050a f355 fbec db01 6562 6405 04aa e011
50ec 0b45 45e5 0df7 2fed a3f8 ac13 2e69
6739 6d81 f13d 2455 e6ca 1c6b dc96 65d5
3bad f250 7dab 42e4 7ba9 f564 ee61 29fb
1b2c 974c 6924 1a1f 99ef 063c b99a c507
8c22 b0f8 b14c 3e4d 01d0 6120 4e19 8725
2fda 6550 f907 3f87

...每当I帧或P帧结束时,我有一个包含适应字段的TS数据包,如...

  4701 003c b000 ffff ffff ffff ffff ffff 
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ff ff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff

...其中第一个b0字节是适应字段填充字节,其余的是I或P帧的最终字节。所以你可以告诉我可以使用ffmpeg并传递我的文件,以任何格式创建一个有效的电影。然而,我需要我创建的文件是正确的格式,我不能弄清楚我最后一块丢失的是什么。有任何想法吗?

解决方案

您有冲突的要求。 有效流和不包括任何时间信息是不兼容的。 TS要求至少每100毫秒进行一次PCR。而当玩家具体时,大多数玩家不会呈现一帧,而没有演示时间戳。你可以从VUI数据中导出时间戳,但它必须存在于容器中。


SO...

I am trying to take a H264 Annex B byte stream video and encode it into MPEG-TS in pure Java. My goals is to create a minimal MPEG-TS, Single Program, valid stream and to not include any timing information information (PCR, PTS, DTS).

I am currently at the point where my generated file can be passed to ffmpeg (ffmpeg -i myVideo.ts) and ffmpeg reports...

[NULL @ 0x7f8103022600] start time is not set in estimate_timings_from_pts

Input #0, mpegts, from 'video.ts':
Duration: N/A, bitrate: N/A
Program 1 
  Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc

...it seems like this warning for start time is not a big deal... and ffmpeg is unable to determine how long the video is. If I create another mpeg-ts file from my video file (ffmpeg -i myVideo.ts -vcodec copy validVideo.ts) and run ffmpeg -i validVideo.ts I get...

Input #0, mpegts, from 'video2.ts':
Duration: 00:00:11.61, start: 1.400000, bitrate: 3325 kb/s
Program 1 
  Metadata:
    service_name    : Service01
    service_provider: FFmpeg
  Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc

...so you can see the timing information and bitrate is there and so is the metadata.

My H264 video is comprised of only I and P Frames (with the SPS and PPS preceding the I Frame of course) and the way that I am creating my MPEG-TS stream is...

  1. Write a single PAT at the beginning of the file
  2. Write a single PMT at the beginning of the file
  3. Create TS and PES packets from SPS, PPS and I Frame (AUD NALs too, if this is required?)
  4. Create TS and PES packets from P Frame (again, AUD NALs too, if required)
  5. For the last payload of either an I Frame or P Frame, add filler bytes to an adaptation field to make sure it fits into a full TS packet
  6. Repeat 3-5 for the entire file

...my PAT looks like this...

4740 0010 0000 b00d 0001 c100 0000 01f0
002a b104 b2ff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff

...and my PMT looks like this...

4750 0010
0002 b012 0001 c100 00ff fff0 001b e100
f000 c15b 41e0 ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff

...notice after the c100 00, the "ff ff", f0... says that we are not using a PCR... Also notice that I have updated my CRC to reflect this change to the PMT. My first I Frame packet looks like...

4741 0010 0000 01e0
0000 8000 0000 0000 0109 f000 0000 0127
4d40 288d 8d60 2802 dd80 b501 0101 4000
00fa 4000 3a98 3a18 00b7 2000 3380 2ef2
e343 0016 e400 0670 05de 5c16 345d c000
0000 0128 ee3c 8000 0000 0165 8880 0020
0000 4fe5 63b5 4e90 b11c 9f8f f891 10f3
13b1 666b 9fc6 03e9 e321 36bf 1788 347b
eb23 fc89 5772 6e2e 1714 96df ed16 9b30
252d ceb7 07e9 a0c7 c6e7 9515 be87 2df1
81f3 b9d2 ba5f 243e 2d5c cba2 8ca5 b798
6bec 8c43 0b5d bbda bc5b 6e7c e15c 84e8
2f13 be84 

...you'll notice after the 01e0 0000, 8000 00 is the PES header extension where I specify no PTS / DTS and the remaining length is zero. My first P Frame packet looks like...

4741 001d
0000 01e0 0000 8000 0000 0000 0109 f000
0000 0141 9a00 0200 0593 ff45 a7ae 1acd
f2d7 f9ec 557f cdb6 ba38 60d6 a626 5edb
4bb9 9783 89e2 d7e1 102e 4625 2fbf ce16
f952 d8c9 f027 e55a 6b2a 81c3 48d4 6a45
050a f355 fbec db01 6562 6405 04aa e011
50ec 0b45 45e5 0df7 2fed a3f8 ac13 2e69
6739 6d81 f13d 2455 e6ca 1c6b dc96 65d5
3bad f250 7dab 42e4 7ba9 f564 ee61 29fb
1b2c 974c 6924 1a1f 99ef 063c b99a c507
8c22 b0f8 b14c 3e4d 01d0 6120 4e19 8725
2fda 6550 f907 3f87

...and whenever an I Frame or P Frame is ending, I have a TS packet with an adaptation field like...

4701 003c b000 ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff

...where the first b0 bytes are the adaptation field stuffing bytes and the remaining ones are the final bytes of the I or P Frame. So as you can tell I can use ffmpeg and pass it my file to create a valid movie in any format. However, I need the file I create to be in the proper format and I cannot quite figure out what the last piece I am missing is. Any ideas?

解决方案

You have conflicting requirements. "valid stream" and "not include any timing information" are incompatible. It is a requirement of TS to have a PCR at least every 100 milliseconds. And while player specific, most players will not 'present' a frame without a 'presentation time stamp'. You my be able to derive the timestamp from the VUI data, but it must exist in the container.

这篇关于手动编码为MPEG-TS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆