From 3772b2160ce79e56c33ff336d4a41823f5cdc45a Mon Sep 17 00:00:00 2001 From: Johns Date: Wed, 9 May 2012 20:16:46 +0200 Subject: [PATCH] Initial ADTS (AAC+) support. --- softhddev.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/softhddev.c b/softhddev.c index f97ba35..b8752b4 100644 --- a/softhddev.c +++ b/softhddev.c @@ -348,8 +348,8 @@ static int Ac3Check(const uint8_t * data, int size) frmsizcod = data[4] & 0x3F; // invalid is checked by fast frame_size = Ac3FrameSizeTable[frmsizcod][fscod] * 2; - if (frame_size + 2 > size) { - return -frame_size - 2; + if (frame_size + 5 > size) { + return -frame_size - 5; } // check if after this frame a new AC-3 frame starts if (FastAc3Check(data + frame_size)) { @@ -359,6 +359,71 @@ static int Ac3Check(const uint8_t * data, int size) return 0; } +/// +/// Fast check for ADTS Audio Data Transport Stream. +/// +/// 7/9 bytes 0xFFFxxxxxxxxxxx(xxxx) ADTS audio +/// +static inline int FastAdtsCheck(const uint8_t * p) +{ + if (p[0] != 0xFF) { // 12bit sync + return 0; + } + if ((p[1] & 0xF6) != 0xF0) { // sync + layer must be 0 + return 0; + } + if ((p[2] & 0x3C) == 0x3C) { // sampling frequency index != 15 + return 0; + } + return 1; +} + +/// +/// Check for ADTS Audio Data Transport Stream. +/// +/// 0xFFF already checked. +/// +/// @param data incomplete PES packet +/// @param size number of bytes +/// +/// @retval <0 possible ADTS audio, but need more data +/// @retval 0 no valid ADTS audio +/// @retval >0 valid AC-3 audio +/// +/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP +/// (QQQQQQQQ QQQQQQQ) +/// +/// o A*12 syncword 0xFFF +/// o B*1 MPEG Version: 0 for MPEG-4, 1 for MPEG-2 +/// o C*2 layer: always 0 +/// o .. +/// o F*4 sampling frequency index (15 is invalid) +/// o .. +/// o M*13 frame length +/// +static int AdtsCheck(const uint8_t * data, int size) +{ + int frame_size; + + if (size < 6) { + return -6; + } + + frame_size = (data[3] & 0x03) << 11; + frame_size |= (data[4] & 0xFF) << 3; + frame_size |= (data[5] & 0xE0) >> 5; + + if (frame_size + 3 > size) { + return -frame_size - 3; + } + // check if after this frame a new ADTS frame starts + if (FastAdtsCheck(data + frame_size)) { + return frame_size; + } + + return 0; +} + #ifndef NO_TS_AUDIO ////////////////////////////////////////////////////////////////////////////// @@ -541,11 +606,13 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size, unsigned codec_id; // 4 bytes 0xFFExxxxx Mpeg audio - // 3 bytes 0x56Exxx AAC LATM audio // 5 bytes 0x0B77xxxxxx AC3 audio + // 3 bytes 0x56Exxx AAC LATM audio + // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio // PCM audio can't be found + // FIXME: simple+faster detection, if codec already known r = 0; - if (FastMpegCheck(q)) { + if (!r && FastMpegCheck(q)) { r = MpegCheck(q, n); codec_id = CODEC_ID_MP2; } @@ -557,6 +624,10 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size, r = LatmCheck(q, n); codec_id = CODEC_ID_AAC_LATM; } + if (!r && FastAdtsCheck(q)) { + r = AdtsCheck(q, n); + codec_id = CODEC_ID_AAC; + } if (r < 0) { // need more bytes break; } @@ -1042,6 +1113,10 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id) } */ } + if (id != 0xbd && !r && FastAdtsCheck(p)) { + r = AdtsCheck(p, n); + codec_id = CODEC_ID_AAC; + } if (r < 0) { // need more bytes break; } @@ -1857,6 +1932,7 @@ int SetPlayMode(int play_mode) NewVideoStream = 1; // tell hw decoder we are closing stream VideoSetClosing(MyHwDecoder); + VideoResetStart(MyHwDecoder); #ifdef DEBUG VideoSwitch = GetMsTicks(); #endif @@ -1926,16 +2002,20 @@ void Clear(void) int i; VideoResetPacket(); // terminate work + VideoSetClosing(MyHwDecoder); + VideoResetStart(MyHwDecoder); VideoClearBuffers = 1; AudioFlushBuffers(); //NewAudioStream = 1; // FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers // wait for empty buffers + // FIXME: without softstart sync VideoDecode isn't called. for (i = 0; VideoClearBuffers && i < 20; ++i) { usleep(1 * 1000); } - Debug(3, "[softhddev]%s: buffers %d\n", __FUNCTION__, VideoGetBuffers()); + Debug(3, "[softhddev]%s: %dms buffers %d\n", __FUNCTION__, i, + VideoGetBuffers()); } /**