[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