[MPlayer-dev-eng] [PATCH] MPEG(2/4) AAC decoder

Naoya OYAMA naoya.oyama at gmail.com
Sun Feb 13 15:59:20 CET 2011


Hi.
I write audio decoder.
AAC passthrough

AAC is ISDB standard(Japan/South American DVB) audio format.
so, AV-Receiver of Japan corresponds to AAC.
I have "ONKYO TX-SA608" AV-Receiver and it works fine.

Index: libmpcodecs/ad.c
===================================================================
--- libmpcodecs/ad.c	(revision 32893)
+++ libmpcodecs/ad.c	(working copy)
@@ -39,6 +39,7 @@
 extern const ad_functions_t mpcodecs_ad_liba52;
 extern const ad_functions_t mpcodecs_ad_hwac3;
 extern const ad_functions_t mpcodecs_ad_hwmpa;
+extern const ad_functions_t mpcodecs_ad_hwaac;
 extern const ad_functions_t mpcodecs_ad_pcm;
 extern const ad_functions_t mpcodecs_ad_dvdpcm;
 extern const ad_functions_t mpcodecs_ad_alaw;
@@ -73,6 +74,7 @@
 #endif
   &mpcodecs_ad_hwac3,
   &mpcodecs_ad_hwmpa,
+  &mpcodecs_ad_hwaac,
 #ifdef CONFIG_FFMPEG
   &mpcodecs_ad_ffmpeg,
 #endif
Index: libmpcodecs/ad_hwaac.c
===================================================================
--- libmpcodecs/ad_hwaac.c	(revision 0)
+++ libmpcodecs/ad_hwaac.c	(revision 0)
@@ -0,0 +1,173 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "libaf/af_format.h"
+#include "ad_internal.h"
+
+#include "libmpdemux/aac_hdr.h"
+
+//based on ad_hwmpa.c
+
+static const ad_info_t info =
+{
+	"MPEG audio(AAC) pass-through (fake decoder)",
+	"hwaac",
+	"Naoya OYAMA",
+	"Naoya OYAMA",
+	"For hardware decoders"
+};
+
+LIBAD_EXTERN(hwaac)
+
+static int aac_sync(sh_audio_t *sh, int no_frames, int *n, int
*srate, int *num)
+{
+	int cnt = 0, x = 0, len, frames_count;
+
+	frames_count = 0;
+	do
+	{
+		while(cnt + 8 < sh->a_in_buffer_len)
+		{
+			x = aac_parse_frame(&(sh->a_in_buffer[cnt]), srate, num);
+			if(x != 0)
+			{
+				frames_count++;
+				if(frames_count == no_frames)
+				{
+					*n = x;
+					return cnt;
+				}
+			}
+			cnt++;
+		}
+		len = demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],sh->a_in_buffer_size-sh->a_in_buffer_len);
+		if(len > 0)
+			sh->a_in_buffer_len += len;
+	} while(len > 0);
+	mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Cannot sync AAC frame: %d\r\n", len);
+	return -1;
+}
+
+static int preinit(sh_audio_t *sh)
+{
+	sh->audio_out_minsize = 4096;//check
+	sh->audio_in_minsize =  4096;//check
+	sh->channels = 2;
+	sh->samplesize = 2;
+	sh->sample_format = AF_FORMAT_AAC_LE;
+	return 1;
+}
+
+static int init(sh_audio_t *sh)
+{
+	int cnt, srate, len, num;
+
+	if((cnt = aac_sync(sh, 1, &len, &srate, &num)) < 0)
+		return 0;
+
+	sh->samplerate = srate;
+	sh->i_bps = (len * srate) / (num * 1024);
+	mp_msg(MSGT_DECAUDIO,MSGL_V,"ad_hwaac initialized, bitrate: [%d]
kbit/s\r\n", sh->i_bps*8/1000);
+	return 1;
+}
+
+static int decode_audio(sh_audio_t *sh,unsigned char *buf,int
minlen,int maxlen)
+{
+	int len, start, tot, tot2;
+	int srate, num;
+	int frame_sample_nr;
+	uint16_t *buf16 = (uint16_t *)buf;
+
+	tot = tot2 = 0;
+	buf16[0] = 0xf872; // iec 61937 syncword 1
+	buf16[1] = 0x4e1f; // iec 61937 syncword 2
+	buf16[2] = 0x0007; // data-type MPEG(2/4) AAC
+
+	while(tot2 < sh->audio_out_minsize)
+	{
+		start = aac_sync(sh, 1, &len, &srate, &num);
+                if (start < 0)
+                    return -1;
+		frame_sample_nr = num * 1024 * sh->channels * 2;
+		if(tot2 + frame_sample_nr > maxlen)
+			break;
+
+		if(start + len > sh->a_in_buffer_len)
+		{
+			int l;
+			l = FFMIN(sh->a_in_buffer_size - sh->a_in_buffer_len, start + len);
+			l = demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len], l);
+			if(! l)
+				break;
+			sh->a_in_buffer_len += l;
+			continue;
+		}
+
+		memcpy(&buf[tot+8], &(sh->a_in_buffer[start]), len);
+		tot += len;
+		tot2 += frame_sample_nr;
+
+		sh->a_in_buffer_len -= start + len;
+		memmove(sh->a_in_buffer, &(sh->a_in_buffer[start + len]),
sh->a_in_buffer_len);
+                sh->i_bps = (len * 8 * srate) / (num*1024);
+	}
+	buf16[3] = tot <<3;
+
+	// stuffing
+	memset(&buf[tot+8], 0, tot2-tot-8);
+	return tot2;
+}
+
+
+static int control(sh_audio_t *sh,int cmd,void* arg, ...)
+{
+	int start, len;
+
+	switch(cmd)
+	{
+		case ADCTRL_RESYNC_STREAM:
+			if(aac_sync(sh, 1, &len, NULL, NULL) >= 0)
+				return CONTROL_TRUE;
+			else
+				return CONTROL_FALSE;
+		case ADCTRL_SKIP_FRAME:
+			start = aac_sync(sh, 2, &len, NULL, NULL);
+			if(start < 0)
+				return CONTROL_FALSE;
+
+			sh->a_in_buffer_len -= start;
+			memmove(sh->a_in_buffer, &(sh->a_in_buffer[start]), sh->a_in_buffer_len);
+			return CONTROL_TRUE;
+	}
+	return CONTROL_UNKNOWN;
+}
+
+
+static void uninit(sh_audio_t *sh)
+{
+}
Index: libao2/ao_alsa.c
===================================================================
--- libao2/ao_alsa.c	(revision 32893)
+++ libao2/ao_alsa.c	(working copy)
@@ -121,7 +121,7 @@
       long get_vol, set_vol;
       float f_multi;

-      if(AF_FORMAT_IS_AC3(ao_data.format))
+      if(AF_FORMAT_IS_AC3(ao_data.format) || AF_FORMAT_IS_AAC(ao_data.format))
 	return CONTROL_TRUE;

       if(mixer_channel) {
@@ -361,10 +361,12 @@
 	alsa_format = SND_PCM_FORMAT_U16_BE;
 	break;
       case AF_FORMAT_AC3_LE:
+      case AF_FORMAT_AAC_LE:
       case AF_FORMAT_S16_LE:
 	alsa_format = SND_PCM_FORMAT_S16_LE;
 	break;
       case AF_FORMAT_AC3_BE:
+      case AF_FORMAT_AAC_BE:
       case AF_FORMAT_S16_BE:
 	alsa_format = SND_PCM_FORMAT_S16_BE;
 	break;
@@ -419,9 +421,9 @@
      * while opening the abstract alias for the spdif subdevice
      * 'iec958'
      */
-    if (AF_FORMAT_IS_AC3(format)) {
+    if (AF_FORMAT_IS_AC3(format) || AF_FORMAT_IS_AAC(format)) {
 	device.str = "iec958";
-	mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3, %i channels\n",
channels);
+	mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3/AAC, %i
channels\n", channels);
     }
   else
         /* in any case for multichannel playback we should select
@@ -470,7 +472,7 @@

     if (!alsa_handler) {
       int open_mode = block ? 0 : SND_PCM_NONBLOCK;
-      int isac3 =  AF_FORMAT_IS_AC3(format);
+      int isac3 =  AF_FORMAT_IS_AC3(format) || AF_FORMAT_IS_AAC(format) ;
       //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC
       if ((err = try_open_device(alsa_device, open_mode, isac3)) < 0)
 	{
@@ -521,6 +523,9 @@
          alsa_format = SND_PCM_FORMAT_S16_LE;
          if (AF_FORMAT_IS_AC3(ao_data.format))
            ao_data.format = AF_FORMAT_AC3_LE;
+         else if (AF_FORMAT_IS_AAC(ao_data.format)) {
+           ao_data.format = AF_FORMAT_AAC_LE;
+         }
          else
          ao_data.format = AF_FORMAT_S16_LE;
       }
Index: Makefile
===================================================================
--- Makefile	(revision 32893)
+++ Makefile	(working copy)
@@ -340,6 +340,7 @@
               libmpcodecs/ad_dvdpcm.c \
               libmpcodecs/ad_hwac3.c \
               libmpcodecs/ad_hwmpa.c \
+              libmpcodecs/ad_hwaac.c \
               libmpcodecs/ad_imaadpcm.c \
               libmpcodecs/ad_msadpcm.c \
               libmpcodecs/ad_pcm.c \
Index: etc/codecs.conf
===================================================================
--- etc/codecs.conf	(revision 32893)
+++ etc/codecs.conf	(working copy)
@@ -3,7 +3,7 @@
 ;  Before editing this file, please read DOCS/tech/codecs.conf.txt !
 ;=============================================================================

-release 20101127
+release 20110213

 ;=============================================================================
 ;                   VIDEO CODECS
@@ -4866,6 +4866,22 @@
   fourcc "LAME"      ; used in mythtv .nuv files
   driver hwmpa

+audiocodec hwaac
+  info "MPEG audio(AAC) pass-through for hardware MPEG decoders"
+  status working
+  comment "for hardware MPEG audio(AAC) decoders"
+  fourcc "VLB " ; Used in NSV, not really working
+  fourcc "AAC " ; Used in NSV
+  fourcc "AACP" ; Used in NSV for AACPlus
+  fourcc raac,racp
+  format 0xff
+  format 0x706D
+  format 0x4143 ; aac in asf
+  format 0xA106 ; aac in avi
+  format 0xAAC0 ; Borgtech nonsense tag
+  format 0x4134504D ; ISDB
+  driver hwaac
+
 audiocodec msnsiren
   info "msn siren audio codec"
   status working
Index: libaf/af_format.h
===================================================================
--- libaf/af_format.h	(revision 32893)
+++ libaf/af_format.h	(working copy)
@@ -58,9 +58,10 @@
 // Special flags refering to non pcm data
 #define AF_FORMAT_MU_LAW	(1<<6)
 #define AF_FORMAT_A_LAW		(2<<6)
-#define AF_FORMAT_MPEG2		(3<<6) // MPEG(2) audio
+#define AF_FORMAT_MPEG2		(3<<6) // MPEG(2) BC audio
 #define AF_FORMAT_AC3		(4<<6) // Dolby Digital AC3
 #define AF_FORMAT_IMA_ADPCM	(5<<6)
+#define AF_FORMAT_AAC	        (6<<6) // MPEG(2/4) AAC
 #define AF_FORMAT_SPECIAL_MASK	(7<<6)

 // PREDEFINED formats
@@ -86,6 +87,9 @@
 #define AF_FORMAT_AC3_LE	(AF_FORMAT_AC3|AF_FORMAT_16BIT|AF_FORMAT_LE)
 #define AF_FORMAT_AC3_BE	(AF_FORMAT_AC3|AF_FORMAT_16BIT|AF_FORMAT_BE)

+#define AF_FORMAT_AAC_LE	(AF_FORMAT_AAC|AF_FORMAT_16BIT|AF_FORMAT_LE)
+#define AF_FORMAT_AAC_BE	(AF_FORMAT_AAC|AF_FORMAT_16BIT|AF_FORMAT_BE)
+
 #if HAVE_BIGENDIAN
 #define AF_FORMAT_U16_NE AF_FORMAT_U16_BE
 #define AF_FORMAT_S16_NE AF_FORMAT_S16_BE
@@ -95,6 +99,7 @@
 #define AF_FORMAT_S32_NE AF_FORMAT_S32_BE
 #define AF_FORMAT_FLOAT_NE AF_FORMAT_FLOAT_BE
 #define AF_FORMAT_AC3_NE AF_FORMAT_AC3_BE
+#define AF_FORMAT_AAC_NE AF_FORMAT_AAC_BE
 #else
 #define AF_FORMAT_U16_NE AF_FORMAT_U16_LE
 #define AF_FORMAT_S16_NE AF_FORMAT_S16_LE
@@ -104,11 +109,13 @@
 #define AF_FORMAT_S32_NE AF_FORMAT_S32_LE
 #define AF_FORMAT_FLOAT_NE AF_FORMAT_FLOAT_LE
 #define AF_FORMAT_AC3_NE AF_FORMAT_AC3_LE
+#define AF_FORMAT_AAC_NE AF_FORMAT_AAC_LE
 #endif

 #define AF_FORMAT_UNKNOWN (-1)

 #define AF_FORMAT_IS_AC3(fmt) (((fmt) & AF_FORMAT_SPECIAL_MASK) ==
AF_FORMAT_AC3)
+#define AF_FORMAT_IS_AAC(fmt) (((fmt) & AF_FORMAT_SPECIAL_MASK) ==
AF_FORMAT_AAC)

 int af_str2fmt(const char *str);
 int af_str2fmt_short(const char *str);
Index: libaf/format.c
===================================================================
--- libaf/format.c	(revision 32893)
+++ libaf/format.c	(working copy)
@@ -161,6 +161,8 @@
     { "ac3le", AF_FORMAT_AC3_LE },
     { "ac3be", AF_FORMAT_AC3_BE },
     { "ac3ne", AF_FORMAT_AC3_NE },
+    { "aacle", AF_FORMAT_AAC_LE },
+    { "aacbe", AF_FORMAT_AAC_BE },
     { "imaadpcm", AF_FORMAT_IMA_ADPCM },

     { "u8", AF_FORMAT_U8 },


More information about the MPlayer-dev-eng mailing list