shithub: aacdec

Download patch

ref: 27191ef56ec52ba2688d941198aca82588904274
parent: 281db6ceec174d040229ca88d20499d006541c78
author: menno <menno>
date: Mon Sep 22 16:05:32 EDT 2003

Added option to extract the decoded AAC file to and MPEG-4 AAC ADTS file

--- a/frontend/main.c
+++ b/frontend/main.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: main.c,v 1.46 2003/09/22 18:22:19 menno Exp $
+** $Id: main.c,v 1.47 2003/09/22 20:05:31 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -111,9 +111,10 @@
     b->bytes_into_buffer -= bytes;
 }
 
+static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0};
+
 int adts_parse(aac_buffer *b, int *bitrate, float *length)
 {
-    static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
     int frames, frame_length;
     int t_framelength = 0;
     int samplerate;
@@ -131,7 +132,7 @@
                 break;
 
             if (frames == 0)
-                samplerate = sample_rates[(b->buffer[2]&0x3c)>>2];
+                samplerate = adts_sample_rates[(b->buffer[2]&0x3c)>>2];
 
             frame_length = ((((unsigned int)b->buffer[3] & 0x3)) << 11)
                 | (((unsigned int)b->buffer[4]) << 3) | (b->buffer[5] >> 5);
@@ -246,7 +247,86 @@
     printf("\n");
 }
 
+int FindAdtsSRIndex(int sr)
+{
+    int i;
 
+	for (i = 0; i < 16; i++)
+    {
+		if (sr == adts_sample_rates[i])
+			return i;
+	}
+	return 16 - 1;
+}
+
+unsigned char *MakeAdtsHeader(int *dataSize, faacDecFrameInfo *hInfo)
+{
+    unsigned char *data;
+    int profile = (hInfo->object_type - 1) & 0x3;
+    int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ?
+        FindAdtsSRIndex(hInfo->samplerate / 2) : FindAdtsSRIndex(hInfo->samplerate);
+    int framesize = 7 + hInfo->bytesconsumed;
+
+    if (hInfo->header_type == ADTS)
+        framesize -= 7;
+
+    *dataSize = 7;
+
+    data = malloc(*dataSize * sizeof(unsigned char));
+    memset(data, 0, *dataSize * sizeof(unsigned char));
+
+    data[0] += 0xFF; /* 8b: syncword */
+
+    data[1] += 0xF0; /* 4b: syncword */
+    /* 1b: mpeg id = 0 */
+    /* 2b: layer = 0 */
+    data[1] += 1; /* 1b: protection absent */
+
+    data[2] += ((profile << 6) & 0xC0); /* 2b: profile */
+    data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */
+    /* 1b: private = 0 */
+    data[2] += ((hInfo->channels >> 2) & 0x1); /* 1b: channel_configuration */
+
+    data[3] += ((hInfo->channels << 6) & 0xC0); /* 2b: channel_configuration */
+    /* 1b: original */
+    /* 1b: home */
+    /* 1b: copyright_id */
+    /* 1b: copyright_id_start */
+    data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */
+
+    data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */
+
+    data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */
+    data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */
+
+    data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */
+    /* 2b: num_raw_data_blocks */
+
+    return data;
+
+#if 0
+    // build adts header
+    adts.PutBits(0xFFF, 12);		// syncword
+    adts.PutBits(isMpeg2, 1);		// id
+    adts.PutBits(0, 2);				// layer
+    adts.PutBits(1, 1);				// protection_absent
+    adts.PutBits(profile, 2);		// profile
+    adts.PutBits(
+        MP4AV_AdtsFindSamplingRateIndex(samplingFrequency),
+        4);							// sampling_frequency_index
+    adts.PutBits(0, 1);				// private
+    adts.PutBits(channels, 3);		// channel_configuration
+    adts.PutBits(0, 1);				// original
+    adts.PutBits(0, 1);				// home
+
+    adts.PutBits(0, 1);				// copyright_id
+    adts.PutBits(0, 1);				// copyright_id_start
+    adts.PutBits(*pAdtsDataLength, 13);	// aac_frame_length
+    adts.PutBits(0x7FF, 11);		// adts_buffer_fullness
+    adts.PutBits(0, 2);				// num_raw_data_blocks
+#endif
+}
+
 /* globals */
 char *progName;
 
@@ -268,6 +348,7 @@
     fprintf(stdout, "Options:\n");
     fprintf(stdout, " -h    Shows this help screen.\n");
     fprintf(stdout, " -i    Shows info about the input file.\n");
+    fprintf(stdout, " -a X  Write MPEG-4 AAC ADTS output file.\n");
     fprintf(stdout, " -o X  Set output filename.\n");
     fprintf(stdout, " -f X  Set output format. Valid values for X are:\n");
     fprintf(stdout, "        1:  Microsoft WAV format (default).\n");
@@ -299,9 +380,9 @@
     return;
 }
 
-int decodeAACfile(char *aacfile, char *sndfile, int to_stdout,
+int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout,
                   int def_srate, int object_type, int outputFormat, int fileType,
-                  int downMatrix, int infoOnly)
+                  int downMatrix, int infoOnly, int adts_out)
 {
     int tagsize;
     unsigned long samplerate;
@@ -310,6 +391,10 @@
 
     audio_file *aufile;
 
+    FILE *adtsFile;
+    unsigned char *adtsData;
+    int adtsDataSize;
+
     faacDecHandle hDecoder;
     faacDecFrameInfo frameInfo;
     faacDecConfigurationPtr config;
@@ -327,6 +412,16 @@
 
     memset(&b, 0, sizeof(aac_buffer));
 
+    if (adts_out)
+    {
+        adtsFile = fopen(adts_fn, "wb");
+        if (adtsFile == NULL)
+        {
+            fprintf(stderr, "Error opening file: %s\n", adts_fn);
+            return 1;
+        }
+    }
+
     b.infile = fopen(aacfile, "rb");
     if (b.infile == NULL)
     {
@@ -459,6 +554,20 @@
         sample_buffer = faacDecDecode(hDecoder, &frameInfo,
             b.buffer, b.bytes_into_buffer);
 
+        if (adts_out == 1)
+        {
+            adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo);
+
+            /* write the adts header */
+            fwrite(adtsData, 1, adtsDataSize, adtsFile);
+
+            /* write the frame data */
+            if (frameInfo.header_type == ADTS)
+                fwrite(b.buffer + 7, 1, frameInfo.bytesconsumed - 7, adtsFile);
+            else
+                fwrite(b.buffer, 1, frameInfo.bytesconsumed, adtsFile);
+        }
+
         /* update buffer indices */
         advance_buffer(&b, frameInfo.bytesconsumed);
 
@@ -474,23 +583,28 @@
             /* print some channel info */
             print_channel_info(&frameInfo);
 
-            /* open output file */
-            if (!to_stdout)
+            if (!adts_out)
             {
-                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                /* open output file */
+                if (!to_stdout)
+                {
+                    aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
+                        outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                } else {
+                    aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
+                        outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                }
+                if (aufile == NULL)
+                {
+                    if (b.buffer)
+                        free(b.buffer);
+                    faacDecClose(hDecoder);
+                    fclose(b.infile);
+                    return 0;
+                }
             } else {
-                aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                fprintf(stderr, "Writing output MPEG-4 AAC ADTS file.\n\n");
             }
-            if (aufile == NULL)
-            {
-                if (b.buffer)
-                    free(b.buffer);
-                faacDecClose(hDecoder);
-                fclose(b.infile);
-                return 0;
-            }
             first_time = 0;
         }
 
@@ -505,7 +619,7 @@
 #endif
         }
 
-        if ((frameInfo.error == 0) && (frameInfo.samples > 0))
+        if ((frameInfo.error == 0) && (frameInfo.samples > 0) && (!adts_out))
         {
             write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
         }
@@ -521,9 +635,14 @@
 
     faacDecClose(hDecoder);
 
+    if (adts_out == 1)
+    {
+        fclose(adtsFile);
+    }
+
     fclose(b.infile);
 
-    if (!first_time)
+    if (!first_time && !adts_out)
         close_audio_file(aufile);
 
     if (b.buffer)
@@ -573,8 +692,9 @@
     12000, 11025, 8000
 };
 
-int decodeMP4file(char *mp4file, char *sndfile, int to_stdout,
-                  int outputFormat, int fileType, int downMatrix, int noGapless, int infoOnly)
+int decodeMP4file(char *mp4file, char *sndfile, char *adts_fn, int to_stdout,
+                  int outputFormat, int fileType, int downMatrix, int noGapless,
+                  int infoOnly, int adts_out)
 {
     int track;
     unsigned long samplerate;
@@ -586,6 +706,10 @@
 
     audio_file *aufile;
 
+    FILE *adtsFile;
+    unsigned char *adtsData;
+    int adtsDataSize;
+
     faacDecHandle hDecoder;
     faacDecConfigurationPtr config;
     faacDecFrameInfo frameInfo;
@@ -612,6 +736,16 @@
     config->downMatrix = downMatrix;
     faacDecSetConfiguration(hDecoder, config);
 
+    if (adts_out)
+    {
+        adtsFile = fopen(adts_fn, "wb");
+        if (adtsFile == NULL)
+        {
+            fprintf(stderr, "Error opening file: %s\n", adts_fn);
+            return 1;
+        }
+    }
+
     infile = MP4Read(mp4file, 0);
     if (!infile)
     {
@@ -702,6 +836,16 @@
 
         sample_buffer = faacDecDecode(hDecoder, &frameInfo, buffer, buffer_size);
 
+        if (adts_out == 1)
+        {
+            adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo);
+
+            /* write the adts header */
+            fwrite(adtsData, 1, adtsDataSize, adtsFile);
+
+            fwrite(buffer, 1, frameInfo.bytesconsumed, adtsFile);
+        }
+
         if (buffer) free(buffer);
 
         if (!noGapless)
@@ -732,24 +876,27 @@
             /* print some channel info */
             print_channel_info(&frameInfo);
 
-            /* open output file */
-            if(!to_stdout)
+            if (!adts_out)
             {
-                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
-            } else {
+                /* open output file */
+                if(!to_stdout)
+                {
+                    aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
+                        outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                } else {
 #ifdef _WIN32
-                setmode(fileno(stdout), O_BINARY);
+                    setmode(fileno(stdout), O_BINARY);
 #endif
-                aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                    aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
+                        outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
+                }
+                if (aufile == NULL)
+                {
+                    faacDecClose(hDecoder);
+                    MP4Close(infile);
+                    return 0;
+                }
             }
-            if (aufile == NULL)
-            {
-                faacDecClose(hDecoder);
-                MP4Close(infile);
-                return 0;
-            }
             first_time = 0;
         }
 
@@ -766,7 +913,7 @@
 #endif
         }
 
-        if ((frameInfo.error == 0) && (sample_count > 0))
+        if ((frameInfo.error == 0) && (sample_count > 0) && (!adts_out))
         {
             write_audio_file(aufile, sample_buffer, sample_count, delay);
         }
@@ -781,9 +928,14 @@
 
     faacDecClose(hDecoder);
 
+    if (adts_out == 1)
+    {
+        fclose(adtsFile);
+    }
+
     MP4Close(infile);
 
-    if (!first_time)
+    if (!first_time && !adts_out)
         close_audio_file(aufile);
 
     return frameInfo.error;
@@ -800,6 +952,7 @@
     int format = 1;
     int outputFormat = FAAD_FMT_16BIT;
     int outfile_set = 0;
+    int adts_out = 0;
     int showHelp = 0;
     int mp4file = 0;
     int noGapless = 0;
@@ -806,6 +959,7 @@
     char *fnp;
     char aacFileName[255];
     char audioFileName[255];
+    char adtsFileName[255];
     MP4FileHandle infile;
 
 /* System dependant types */
@@ -836,6 +990,7 @@
         int option_index = 0;
         static struct option long_options[] = {
             { "outfile",    0, 0, 'o' },
+            { "adtsout",    0, 0, 'a' },
             { "format",     0, 0, 'f' },
             { "bits",       0, 0, 'b' },
             { "samplerate", 0, 0, 's' },
@@ -847,7 +1002,7 @@
             { "help",       0, 0, 'h' }
         };
 
-        c = getopt_long(argc, argv, "o:s:f:b:l:wgdhi",
+        c = getopt_long(argc, argv, "o:a:s:f:b:l:wgdhi",
             long_options, &option_index);
 
         if (c == -1)
@@ -855,13 +1010,22 @@
 
         switch (c) {
         case 'o':
-            if (optarg) {
+            if (optarg)
+            {
                 outfile_set = 1;
                 strcpy(audioFileName, optarg);
             }
             break;
+        case 'a':
+            if (optarg)
+            {
+                adts_out = 1;
+                strcpy(adtsFileName, optarg);
+            }
+            break;
         case 's':
-            if (optarg) {
+            if (optarg)
+            {
                 char dr[10];
                 if (sscanf(optarg, "%s", dr) < 1) {
                     def_srate = 0;
@@ -871,9 +1035,11 @@
             }
             break;
         case 'f':
-            if (optarg) {
+            if (optarg)
+            {
                 char dr[10];
-                if (sscanf(optarg, "%s", dr) < 1) {
+                if (sscanf(optarg, "%s", dr) < 1)
+                {
                     format = 1;
                 } else {
                     format = atoi(dr);
@@ -883,9 +1049,11 @@
             }
             break;
         case 'b':
-            if (optarg) {
+            if (optarg)
+            {
                 char dr[10];
-                if (sscanf(optarg, "%s", dr) < 1) {
+                if (sscanf(optarg, "%s", dr) < 1)
+                {
                     outputFormat = FAAD_FMT_16BIT; /* just use default */
                 } else {
                     outputFormat = atoi(dr);
@@ -895,9 +1063,11 @@
             }
             break;
         case 'l':
-            if (optarg) {
+            if (optarg)
+            {
                 char dr[10];
-                if (sscanf(optarg, "%s", dr) < 1) {
+                if (sscanf(optarg, "%s", dr) < 1)
+                {
                     object_type = LC; /* default */
                 } else {
                     object_type = atoi(dr);
@@ -971,11 +1141,11 @@
 
     if (mp4file)
     {
-        result = decodeMP4file(aacFileName, audioFileName, writeToStdio,
-            outputFormat, format, downMatrix, noGapless, infoOnly);
+        result = decodeMP4file(aacFileName, audioFileName, adtsFileName, writeToStdio,
+            outputFormat, format, downMatrix, noGapless, infoOnly, adts_out);
     } else {
-        result = decodeAACfile(aacFileName, audioFileName, writeToStdio,
-            def_srate, object_type, outputFormat, format, downMatrix, infoOnly);
+        result = decodeAACfile(aacFileName, audioFileName, adtsFileName, writeToStdio,
+            def_srate, object_type, outputFormat, format, downMatrix, infoOnly, adts_out);
     }
 
 
--- a/include/faad.h
+++ b/include/faad.h
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: faad.h,v 1.30 2003/09/22 18:22:19 menno Exp $
+** $Id: faad.h,v 1.31 2003/09/22 20:05:31 menno Exp $
 **/
 
 #ifndef __AACDEC_H__
@@ -155,6 +155,9 @@
 
     /* MPEG-4 ObjectType */
     unsigned char object_type;
+
+    /* AAC header type; MP4 will be signalled as RAW also */
+    unsigned char header_type;
 
     /* multichannel configuration */
     unsigned char num_front_channels;
--- a/libfaad/decoder.c
+++ b/libfaad/decoder.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: decoder.c,v 1.68 2003/09/22 18:22:19 menno Exp $
+** $Id: decoder.c,v 1.69 2003/09/22 20:05:32 menno Exp $
 **/
 
 #include "common.h"
@@ -914,6 +914,12 @@
     hInfo->object_type = hDecoder->object_type;
     /* sbr */
     hInfo->sbr = NO_SBR;
+    /* header type */
+    hInfo->header_type = RAW;
+    if (hDecoder->adif_header_present)
+        hInfo->header_type = ADIF;
+    if (hDecoder->adts_header_present)
+        hInfo->header_type = ADTS;
 
     /* check if frame has channel elements */
     if (channels == 0)
--- a/libfaad/structs.h
+++ b/libfaad/structs.h
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: structs.h,v 1.14 2003/09/22 18:22:19 menno Exp $
+** $Id: structs.h,v 1.15 2003/09/22 20:05:32 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -342,6 +342,9 @@
 
     /* MPEG-4 ObjectType */
     uint8_t object_type;
+
+    /* AAC header type; MP4 will be signalled as RAW also */
+    uint8_t header_type;
 
     /* multichannel configuration */
     uint8_t num_front_channels;
--- a/libfaad/syntax.h
+++ b/libfaad/syntax.h
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: syntax.h,v 1.34 2003/09/22 18:22:19 menno Exp $
+** $Id: syntax.h,v 1.35 2003/09/22 20:05:32 menno Exp $
 **/
 
 #ifndef __SYNTAX_H__
@@ -44,6 +44,11 @@
 #define ER_LC     17
 #define ER_LTP    19
 #define DRM_ER_LC 27 /* special object type for DRM */
+
+/* header types */
+#define RAW        0
+#define ADIF       1
+#define ADTS       2
 
 /* SBR signalling */
 #define NO_SBR           0