<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi,<br class=""><br class="">I’m writing a C++ program to validate the integrity of a Fragmented MP4 file containing AAC audio.<br class="">This program would parse the FMP4 file, read each audio packet, attachment ADTS headers, and then try to decode the AAC using libfdk_aac.<br class=""><br class="">I am using libavformat, and I am able to parse the MP4 atoms correctly, however I’m having issues figuring out the best way to attach the ADTS headers.<br class=""><br class="">My current idea is to use a libavformat mp4 demuxed and send that to an adts muxer. I’ve written all the code to do it now; but I’m now getting errors like so:<div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(251, 0, 7); background-color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #fc69ff" class="">[adts @ 0x7fae51001600] </span><span style="font-variant-ligatures: no-common-ligatures" class="">MPEG-4 AOT 0 is not allowed in ADTS</span></div><br class=""><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class="">I’m not sure what to do now.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class="">My code is as below:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><b class="">AudioAssetReader::AudioAssetReader</b>(<span style="color: #7f0055" class=""><b class="">const</b></span> <span style="color: #005032" class="">AudioAssetReaderInput</span> &input) <span style="color: #7f0055" class=""><b class="">throw</b></span> (<span style="color: #005032" class="">invalid_argument</span>):</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                              </span><span style="color: #0000c0" class="">input</span>(input), <span style="color: #0000c0" class="">segmentsIter</span>(input.getBeginSegmentsIter()), <span style="color: #0000c0" class="">audioBufferSize</span>(409600), <span style="color: #0000c0" class="">adtsPacketBufferSize</span>(409600) {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">       </span><span style="color: #7f0055" class=""><b class="">if</b></span> (input.getSegments()->empty()) {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(42, 0, 255);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">           </span></span><span style="color: #7f0055" class=""><b class="">throw</b></span><span style="color: #000000" class=""> </span><span style="color: #005032" class="">invalid_argument</span><span style="color: #000000" class="">(</span>"A reader must read at least 1 segment of audio!"<span style="color: #000000" class="">);</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">    </span>}</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">     </span></span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>audioBuffer<span style="color: #000000" class=""> = </span><span style="color: #7f0055" class=""><b class="">new</b></span><span style="color: #000000" class=""> </span><span style="color: #005032" class="">uint8_t</span><span style="color: #000000" class="">[</span>audioBufferSize<span style="color: #000000" class="">];</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">       </span></span>// create the main context used to parse the audio asset, segment by segment</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span><span style="color: #7f0055" class=""><b class="">bool</b></span> isBufferWritable = <span style="color: #7f0055" class=""><b class="">false</b></span>;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">assetSegmentReaderContext</span> = avio_alloc_context(<span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">audioBuffer</span>, <span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">audioBufferSize</span>, isBufferWritable, <span style="color: #7f0055" class=""><b class="">this</b></span>, <span style="color: #005032" class="">AudioAssetReader</span>::<i class="">readSegment</i>, NULL, NULL);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span><span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">assetParsingContext</span> = avformat_alloc_context();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">     </span></span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>assetParsingContext<span style="color: #000000" class="">-></span>pb<span style="color: #000000" class=""> = </span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>assetSegmentReaderContext<span style="color: #000000" class="">;</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">       </span><span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">assetParsingContext</span>-><span style="color: #0000c0" class="">flags</span> = AVFMT_FLAG_CUSTOM_IO;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre"> </span></span>// create another context used to append ADTS headers to the parsed segments, if we need them</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">  </span><span style="color: #7f0055" class=""><b class="">this</b></span>->initializeADTSMuxerContext(input);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span style="color: #7f0055" class=""><b class="">void</b></span> <b class="">AudioAssetReader::initializeADTSMuxerContext</b>(<span style="color: #7f0055" class=""><b class="">const</b></span> <span style="color: #005032" class="">AudioAssetReaderInput</span> &input) {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">    </span></span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>adtsPacketBuffer<span style="color: #000000" class=""> = </span><span style="color: #7f0055" class=""><b class="">new</b></span><span style="color: #000000" class=""> </span><span style="color: #005032" class="">uint8_t</span><span style="color: #000000" class="">[</span>adtsPacketBufferSize<span style="color: #000000" class="">];</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">     </span><span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsPacket</span> = av_packet_alloc();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">    </span></span>// create another context used to append ADTS headers to the parsed segments, if we need them</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">  </span><span style="color: #7f0055" class=""><b class="">bool</b></span> isBufferWritable = <span style="color: #7f0055" class=""><b class="">true</b></span>;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>avformat_alloc_output_context2(&<span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsMuxerContext</span>, NULL, <span style="color: #2a00ff" class="">"</span><span style="text-decoration: underline ; color: #2a00ff" class="">adts</span><span style="color: #2a00ff" class="">"</span>, NULL);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span><span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsMuxerWriterContext</span> = avio_alloc_context(<span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsPacketBuffer</span>, <span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsPacketBufferSize</span>, isBufferWritable, <span style="color: #7f0055" class=""><b class="">this</b></span>, NULL, <span style="color: #005032" class="">AudioAssetReader</span>::<i class="">writeADTSPacket</i>, NULL);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre"> </span></span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>adtsMuxerContext<span style="color: #000000" class="">-></span>pb<span style="color: #000000" class=""> = </span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>adtsMuxerWriterContext<span style="color: #000000" class="">;</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">     </span></span>// initialize an ADTS stream</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span>AVCodecID aacCodec = AVCodecID::<span style="color: #0000c0" class=""><i class="">AV_CODEC_ID_AAC</i></span>;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre"> </span><span style="color: #005032" class="">AVCodec</span> *codec = avcodec_find_encoder(aacCodec);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">       </span><span style="color: #005032" class="">AVStream</span> *stream = avformat_new_stream(<span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsMuxerContext</span>, codec);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">       </span>stream-></span>id<span style="color: #000000" class=""> = </span><span style="color: #7f0055" class=""><b class="">this</b></span><span style="color: #000000" class="">-></span>adtsMuxerContext<span style="color: #000000" class="">-></span>nb_streams<span style="color: #000000" class=""> - 1;</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span>stream-><span style="color: #0000c0" class="">time_base</span>.<span style="color: #0000c0" class="">den</span> = input.getSampleRateHz();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">       </span>stream-><span style="color: #0000c0" class="">time_base</span>.<span style="color: #0000c0" class="">num</span> = 1;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">     </span></span>// configure the stream with the details of the AAC packets</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">    </span><span style="color: #005032" class="">AVCodecParameters</span> *codecParameters = stream-><span style="color: #0000c0" class="">codecpar</span>;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>codecParameters-><span style="color: #0000c0" class="">codec_id</span> = aacCodec;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">       </span>codecParameters-><span style="color: #0000c0" class="">bit_rate</span> = input.getBitrateBps();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">  </span>codecParameters-><span style="color: #0000c0" class="">profile</span> = <span style="color: #7f0055" class=""><b class="">this</b></span>->getAACProfileForCodec(input.getCodec());</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">     </span>codecParameters-><span style="color: #0000c0" class="">sample_rate</span> = input.getSampleRateHz();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">     </span>codecParameters-><span style="color: #0000c0" class="">channels</span> = input.getChannelCount();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(0, 0, 192);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>codecParameters-></span>codec_type<span style="color: #000000" class=""> = </span><i class="">AVMEDIA_TYPE_AUDIO</i><span style="color: #000000" class="">;</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">   </span>codecParameters-><span style="color: #0000c0" class="">channel_layout</span> = av_get_default_channel_layout(input.getChannelCount());</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">    </span><span style="color: #005032" class="">uint8_t</span>* header = <span style="color: #7f0055" class=""><b class="">new</b></span> <span style="color: #005032" class="">uint8_t</span>[7];</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">      </span><span style="color: #642880" class=""><b class="">memset</b></span>(header, 1, 7);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">   </span></span>//header[3] = 2 << 6;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">     </span>codecParameters-><span style="color: #0000c0" class="">extradata</span> = header;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>codecParameters-><span style="color: #0000c0" class="">extradata_size</span> = 7;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(63, 127, 95);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span>// write out a header to the <span style="text-decoration: underline" class="">muxer</span>; this is a no-<span style="text-decoration: underline" class="">op</span> for our purposes</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre"> </span><span style="color: #7f0055" class=""><b class="">const</b></span> <span style="color: #7f0055" class=""><b class="">int</b></span> result = avformat_write_header(<span style="color: #7f0055" class=""><b class="">this</b></span>-><span style="color: #0000c0" class="">adtsMuxerContext</span>, NULL);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">    </span><span style="color: #7f0055" class=""><b class="">if</b></span> (result < 0) {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">             </span><span style="color: #7f0055" class=""><b class="">char</b></span> *message = <span style="color: #7f0055" class=""><b class="">new</b></span> <span style="color: #7f0055" class=""><b class="">char</b></span>[AV_ERROR_MAX_STRING_SIZE];</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>av_make_error_string(message, AV_ERROR_MAX_STRING_SIZE, result);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(42, 0, 255);" class=""><span style="color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">            </span>cerr<<endl<<</span>"Failed to write the ADTS <span style="text-decoration: underline" class="">muxer</span> header due to: "<span style="color: #000000" class=""><<result<<</span>": "<span style="color: #000000" class=""><<message<<endl;</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">          </span><span style="color: #7f0055" class=""><b class="">delete</b></span>[] message;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">}</div><br class="">Ronak</div></div></body></html>