slibs icon indicating copy to clipboard operation
slibs copied to clipboard

Unable to decode Fraunhofer FDK AAC -encoded files

Open davidgrisham opened this issue 1 year ago • 1 comments

Hi!

I'm working on integrating uaac.h as an AAC decoder for miniaudio, but I'm having issues getting uaac to decode my AAC files in the first place. I'm using ffmpeg and libfdk_aac (Fraunhofer FDK AAC) to encode my files. I've tested with your aplay+ program and am getting the same issue.

I have two files in the following test:

  • output.m4a was encoded with the default ffmpeg/libfdk_aac settings
  • output-moov.m4a was encoded the same way, but I passed the -movflags +faststart options so that the moov atom would be at the start of the file (since uaac wasn't able to find it)
$ ./aplay+ files/

/home/grish/scratch/aplay-/files/output.m4a
[moov] is not found!
[trak] is not found!
[mdia] is not found!
[hdlr] is not found!
type:4d344120/736f756e 0 fffffff8
Error: cannot read AAC data

/home/grish/scratch/aplay-/files/output-moov.m4a
[mdat] is not found!
Error: cannot read AAC data

I've been playing around with the uaac_extract_aac function, but am not well-versed in decoding audio files. Curious if you have any ideas here, or at least a sense of how much work it would be to get this working. I have a rather large audio library that's encoded in the same way, so I'm hoping to get this working without modifying the audio files.

davidgrisham avatar Dec 28 '23 16:12 davidgrisham

I've now gotten aplay+ to output very clicky/noisy audio, and I can sort of hear the actual song underneath. I updated the uaac_extract_aac function to:

uint8_t *uaac_extract_aac(int fd, int *len, int *samplerate, int *channels)
{
	_ATOM ftyp = uaac_findMp4Atom("ftyp", 0, 0, fd);
	if (!ftyp.size) return 0; // no mp4/m4a file
	_ATOM free = uaac_findMp4Atom("free", ftyp.pos + ftyp.size, 1, fd);
	if (!free.size) return 0; // no mp4/m4a file

	_ATOM mdat = uaac_findMp4Atom("mdat", free.pos + free.size, 1, fd);
	printf("mdat.size: %d\n", mdat.size);
	*len = mdat.size;
	uint8_t *data = (uint8_t*)malloc(mdat.size);
	if (!data) return 0; // memory error!

	ssize_t bytes_read = read(fd, data, mdat.size);
	printf("bytes_read: %zd\n", bytes_read);

	_ATOM moov = uaac_findMp4Atom("moov", mdat.pos + mdat.size, 0, fd);
	_ATOM trak = uaac_findMp4Atom("trak", moov.pos + 8, 1, fd);
	_ATOM mdia = uaac_findMp4Atom("mdia", trak.pos + 8, 1, fd);
	_ATOM mdhd = uaac_findMp4Atom("mdhd", mdia.pos + 8, 1, fd);
	_ATOM hdlr = uaac_findMp4Atom("hdlr", mdhd.pos + mdhd.size, 1, fd);
	_ATOM minf = uaac_findMp4Atom("minf", hdlr.pos + hdlr.size, 1, fd);
	_ATOM stbl = uaac_findMp4Atom("stbl", minf.pos + 8, 1, fd);
	_ATOM stsd = uaac_findMp4Atom("stsd", stbl.pos + 8, 1, fd);
	if (!stsd.size) return 0; // something is not ok

	*channels = uaac_read16(stsd.pos + 8 + 0x20, fd);
	*samplerate = uaac_read32(stsd.pos + 8 + 0x26, fd);

	printf("channels: %d\n", *channels);
	printf("samplerate: %d\n", *samplerate);

	return data;
}

And after recompiling + running aplay+ the terminal output is:

$ ./aplay+ -d 'hw:2,0' files/

/home/grish/scratch/aplay-/files/output.m4a
mdat.size: 7727795
bytes_read: 7727795
channels: 2
samplerate: 48000
48000Hz 2ch

In case it's helpful, here's the data ffmpeg extracts from the same audio file:

$ ffprobe -i output.m4a
ffprobe version n6.0 Copyright (c) 2007-2023 the FFmpeg developers
  built with gcc 13.2.1 (GCC) 20230801
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-openssl --enable-shared --enable-vaapi --enable-version3 --enable-vulkan --enable-libfdk_aac --enable-nonfree --disable-htmlpages
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.m4a':
  Metadata:
    major_brand     : M4A
    minor_version   : 512
    compatible_brands: M4A isomiso2
    title           : Irresistible
    artist          : Deafheaven
    composer        : George Clarke/Kerry McCoy
    album           : Sunbather (10th Anniversary Remix / Remaster)
    genre           : Black Metal
    track           : 2
    disc            : 0
    date            : 2023
    compilation     : 0
    encoder         : Lavf60.3.100
    ORIGINAL YEAR   : 0000
    lyrics          :
    sort_album_artist:
    sort_artist     :
    sort_composer   :
    grouping        :
    comment         : ~ N ~
    album_artist    : Deafheaven
  Duration: 00:03:13.15, start: 0.000000, bitrate: 321 kb/s
  Stream #0:0[0x1](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 320 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]

davidgrisham avatar Dec 28 '23 18:12 davidgrisham