简体   繁体   English

Java mp4parser 输出为空

[英]Java mp4parser output is empty

This use case is a service that manually encodes a series of uncompressed .wav media segments into .m4s fragments for broadcast via MPEG-DASH, using ffmpeg to compress the .wav to .aac and sannies/mp4parser to assemble the aac audio into a .m4s media fragment.此用例是一项服务,它手动将一系列未压缩的 .wav 媒体片段编码为 .m4s 片段以通过 MPEG-DASH 进行广播,使用 ffmpeg 将 .wav 压缩为 .aac 并使用 sannies/mp4parser 将 aac 音频组合成 .m4s 片段。 m4s 媒体片段。

I created this public GitHub project to reproduce the issue in its entirety.我创建了这个公共 GitHub 项目来完整重现这个问题。

For example, here's the custom ChunkFragmentM4sBuilder.java class.例如,这里是自定义ChunkFragmentM4sBuilder.java类。


The first example using MP4 box works, insofar as I am able to generate an initializing MP4 + series of fragment M4s files which can then be concatenated to form a playable MPEG4 stream.第一个使用 MP4 盒的示例有效,因为我能够生成初始化 MP4 + 系列片段 M4s 文件,然后可以将这些文件连接起来形成可播放的 MPEG4 流。

Note: it's a requirement for this use case that each media segment is encoded from an individually generated source segment, versus using a tool such as MP4Box to stream from a continuous audio source.注意:此用例要求每个媒体片段都从单独生成的源片段编码,而不是使用 MP4Box 等工具从连续音频源进行流式传输。

Attempts to manually build media segments via mp4parser are still failing overall, because the fragments written by my ChunkFragmentM4sBuilder.java used below are malformed.尝试通过 mp4parser 手动构建媒体片段总体上仍然失败,因为我在下面使用的ChunkFragmentM4sBuilder.java编写的片段格式不正确。 But I'm having a difficult time understanding how exactly they are malformed.但是我很难理解它们究竟是如何畸形的。

It's been helpful for me to compare the two test logs side by side, ChunkFragmentM4sBuilderTest.log.txt and MP4BoxTest.log.txt .并排比较两个测试日志ChunkFragmentM4sBuilderTest.log.txtMP4BoxTest.log.txt对我很有帮助

via Java mp4parser (malformed)通过 Java mp4parser(格式错误)

The former log is from ChunkFragmentM4sBuilderTest.java which results in the concatenated test output test-java-mp4parser.mp4 which is in fact empty:前一个日志来自ChunkFragmentM4sBuilderTest.java ,它导致连接的测试输出test-java-mp4parser.mp4实际上是空的: Java mp4parser 方法的连接输出为空

Files.deleteIfExists(Path.of(m4sFilePath));
AACTrackImpl aacTrack=new AACTrackImpl(new FileDataSourceImpl(aacFilePath));
Movie movie=new Movie();
movie.addTrack(aacTrack);
Container mp4file=new ChunkFragmentM4sBuilder(hz,seconds,seqNum,bufferSize).build(movie);
FileChannel fc=new FileOutputStream(m4sFilePath).getChannel();
mp4file.writeContainer(fc);
fc.close();

Concatenated boxes:串联框:

FileTypeBox[majorBrand=iso5;minorVersion=512;compatibleBrand=iso6;compatibleBrand=mp41]
MovieBox[MovieHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;timescale=1000;duration=0;rate=1.0;volume=1.0;matrix=Rotate 0°;nextTrackId=2];TrackBox[TrackHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;trackId=1;duration=0;layer=0;alternateGroup=1;volume=1.0;matrix=Rotate 0°;width=0.0;height=0.0];EditBox[EditListBox{entries=[Entry{segmentDuration=0, mediaTime=1024, mediaRate=1.0}]}];MediaBox[MediaHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;timescale=48000;duration=0;language=und];HandlerBox[handlerType=soun;name=SoundHandler];MediaInformationBox[SoundMediaHeaderBox[balance=0.0];DataInformationBox[DataReferenceBox[DataEntryUrlBox[]]];SampleTableBox[SampleDescriptionBox[AudioSampleEntry{bytesPerSample=0, bytesPerFrame=0, bytesPerPacket=0, samplesPerPacket=0, packetSize=0, compressionId=0, soundVersion=0, sampleRate=48000, sampleSize=16, channelCount=2, boxes=[org.mp4parser.boxes.iso14496.part14.ESDescriptorBox@bed094d2]}];TimeToSampleBox[entryCount=0];SampleToChunkBox[entryCount=0];SampleSizeBox[sampleSize=0;sampleCount=0];StaticChunkOffsetBox[entryCount=0]]]]];MovieExtendsBox[org.mp4parser.boxes.iso14496.part12.TrackExtendsBox@11e7301d];UserDataBox[MetaBox[HandlerBox[handlerType=mdir;name=];AppleItemListBox[org.mp4parser.boxes.apple.AppleEncoderBox@691fba4]]]]
SegmentTypeBox[majorBrand=msdh;minorVersion=0;compatibleBrand=msdh;compatibleBrand=msix]
SegmentIndexBox{entries=[Entry{referenceType=0, referencedSize=160944, subsegmentDuration=480000, startsWithSap=1, sapType=0, sapDeltaTime=0}], referenceId=1, timeScale=48000, earliestPresentationTime=0, firstOffset=0, reserved=0}
MovieFragmentBox[MovieFragmentHeaderBox{sequenceNumber=151304042};TrackFragmentBox[TrackFragmentHeaderBox{trackId=1, baseDataOffset=-1, sampleDescriptionIndex=0, defaultSampleDuration=-1, defaultSampleSize=-1, defaultSampleFlags=null, durationIsEmpty=true, defaultBaseIsMoof=true};TrackFragmentBaseMediaDecodeTimeBox{baseMediaDecodeTime=0};TrackRunBox{sampleCount=470, dataOffset=-1, dataOffsetPresent=false, sampleSizePresent=true, sampleDurationPresent=true, sampleFlagsPresentPresent=false, sampleCompositionTimeOffsetPresent=false, firstSampleFlags=null}]]
org.mp4parser.boxes.iso14496.part12.MediaDataBox@3969adb0

via MP4Box (ok)通过 MP4Box(好的)

The latter log is from MP4BoxTest.java which results in the concatenated test output test-mp4box.mp4 which is OK.后一个日志来自MP4BoxTest.java ,它导致连接的测试输出test-mp4box.mp4是可以的。

Note however, this method is not acceptable for the final use case, because of the imperfections in the blocks that are output by this hack method.但是请注意,此方法对于最终用例是不可接受的,因为此 hack 方法输出的块中存在缺陷。

MP4Box 方法的连接输出没问题

MP4Box \
  -profile live \
  -add aacFilePath \
  -dash 10000 \
  -frag 10000 \
  -idx ${NUM} \
  -moof-sn ${NUM} \
  -out test5.mpd \
  -segment-name test5-128k- \
  -segment-ext m4s \
  -single-traf \
  -subsegs-per-sidx 0 \
  -daisy-chain \
  -single-segment \
  /tmp

Concatenated boxes:串联框:

FileTypeBox[majorBrand=iso5;minorVersion=512;compatibleBrand=iso6;compatibleBrand=mp41]
MovieBox[MovieHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;timescale=1000;duration=0;rate=1.0;volume=1.0;matrix=Rotate 0°;nextTrackId=2];TrackBox[TrackHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;trackId=1;duration=0;layer=0;alternateGroup=1;volume=1.0;matrix=Rotate 0°;width=0.0;height=0.0];EditBox[EditListBox{entries=[Entry{segmentDuration=0, mediaTime=1024, mediaRate=1.0}]}];MediaBox[MediaHeaderBox[creationTime=Thu Dec 31 16:00:00 PST 1903;modificationTime=Thu Dec 31 16:00:00 PST 1903;timescale=48000;duration=0;language=und];HandlerBox[handlerType=soun;name=SoundHandler];MediaInformationBox[SoundMediaHeaderBox[balance=0.0];DataInformationBox[DataReferenceBox[DataEntryUrlBox[]]];SampleTableBox[SampleDescriptionBox[AudioSampleEntry{bytesPerSample=0, bytesPerFrame=0, bytesPerPacket=0, samplesPerPacket=0, packetSize=0, compressionId=0, soundVersion=0, sampleRate=48000, sampleSize=16, channelCount=2, boxes=[org.mp4parser.boxes.iso14496.part14.ESDescriptorBox@bed094d2]}];TimeToSampleBox[entryCount=0];SampleToChunkBox[entryCount=0];SampleSizeBox[sampleSize=0;sampleCount=0];StaticChunkOffsetBox[entryCount=0]]]]];MovieExtendsBox[org.mp4parser.boxes.iso14496.part12.TrackExtendsBox@7ce1e496];UserDataBox[MetaBox[HandlerBox[handlerType=mdir;name=];AppleItemListBox[org.mp4parser.boxes.apple.AppleEncoderBox@51da5351]]]]
SegmentTypeBox[majorBrand=msdh;minorVersion=0;compatibleBrand=msdh;compatibleBrand=msix]
SegmentIndexBox{entries=[Entry{referenceType=0, referencedSize=162267, subsegmentDuration=479232, startsWithSap=1, sapType=1, sapDeltaTime=0}], referenceId=1, timeScale=48000, earliestPresentationTime=0, firstOffset=0, reserved=0}
MovieFragmentBox[MovieFragmentHeaderBox{sequenceNumber=151304042};TrackFragmentBox[TrackFragmentHeaderBox{trackId=1, baseDataOffset=-1, sampleDescriptionIndex=0, defaultSampleDuration=-1, defaultSampleSize=-1, defaultSampleFlags=null, durationIsEmpty=false, defaultBaseIsMoof=true};TrackFragmentBaseMediaDecodeTimeBox{baseMediaDecodeTime=0};TrackRunBox{sampleCount=468, dataOffset=1964, dataOffsetPresent=true, sampleSizePresent=true, sampleDurationPresent=false, sampleFlagsPresentPresent=false, sampleCompositionTimeOffsetPresent=false, firstSampleFlags=null}]]
org.mp4parser.boxes.iso14496.part12.MediaDataBox@640d3ba5

test-java-mp4parser.mp4 is not empty but is invalid because: test-java-mp4parser.mp4不为空但无效,因为:

  • the sidx entry referenced size is wrong sidx条目引用的大小错误
  • the tfhd is overriding the default sample description index ( 1 ) with 0 tfhd0覆盖默认样本描述索引 ( 1 )
  • the trun doesn't specify the data offset trun没有指定数据偏移量
  • the mdat AAC data starts with 8 zero bytes which cause the decoding to fail mdat AAC 数据以 8 个零字节开头,这会导致解码失败

The file plays with FFmpeg if these are fixed.如果这些是固定的,文件将使用 FFmpeg 播放。

The m4s segments listed are also malformed and don't seem to correspond to the concatenation result.列出的m4s段也格式不正确,似乎与连接结果不对应。 For example the sequence number is used as the sample description index.例如,序列号用作样本描述索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM