From 976915600441b20685ade4d534d0907114817f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Mon, 10 Aug 2009 17:18:17 +0000 Subject: [PATCH] Initial support for AAC LATM (still not finished) --- Makefile | 1 + src/parser_latm.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++ src/parser_latm.h | 26 +++++++ src/parsers.c | 98 ++++++++++++++++++++++++ src/tvhead.h | 1 + 5 files changed, 317 insertions(+) create mode 100644 src/parser_latm.c create mode 100644 src/parser_latm.h diff --git a/Makefile b/Makefile index c5c73c9c..ea114915 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ SRCS = src/main.c \ src/psi.c \ src/parsers.c \ src/parser_h264.c \ + src/parser_latm.c \ src/tsdemux.c \ src/bitstream.c \ src/htsp.c \ diff --git a/src/parser_latm.c b/src/parser_latm.c new file mode 100644 index 00000000..5d6fd6dd --- /dev/null +++ b/src/parser_latm.c @@ -0,0 +1,191 @@ +/* + * LATM / AAC Parser + * + * Copyright (C) 2009 Andreas Öman + * + * Based on LATM Parser patch sent to ffmpeg-devel@ + * copyright (c) 2009 Paul Kendall + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "tvhead.h" +#include "parsers.h" +#include "parser_latm.h" +#include "bitstream.h" + +static const int mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + + +typedef struct latm_private { + + int configured; + int audio_mux_version_A; + int frame_length_type; + + int sample_rate_index; + int channel_config; + +} latm_private_t; + + + +static uint32_t +latm_get_value(bitstream_t *bs) +{ + return read_bits(bs, read_bits(bs, 2) * 8); +} + + +static void +read_audio_specific_config(latm_private_t *latm, bitstream_t *bs) +{ + int aot; + + aot = read_bits(bs, 5); + if(aot != 2) + return; + + latm->sample_rate_index = read_bits(bs, 4); + + if(latm->sample_rate_index == 0xf) + return; + + latm->channel_config = read_bits(bs, 4); + + skip_bits(bs, 1); //framelen_flag + if(read_bits1(bs)) { // depends_on_coder + skip_bits(bs, 14); // delay + } + skip_bits(bs, 1); // ext_flag +} + + +static void +read_stream_mux_config(latm_private_t *latm, bitstream_t *bs) +{ + int audio_mux_version = read_bits(bs, 1); + latm->audio_mux_version_A = 0; + if(audio_mux_version) // audioMuxVersion + latm->audio_mux_version_A = read_bits(bs, 1); + + if(!latm->audio_mux_version_A) { + + if(audio_mux_version) + latm_get_value(bs); // taraFullness + + read_bits(bs, 1); // allStreamSameTimeFraming = 1 + read_bits(bs, 6); // numSubFrames = 0 + read_bits(bs, 4); // numPrograms = 0 + + // for each program (which there is only on in DVB) + read_bits(bs, 3); // numLayer = 0 + + // for each layer (which there is only on in DVB) + if (!audio_mux_version) + read_audio_specific_config(latm, bs); + else { + uint32_t ascLen = latm_get_value(bs); + abort(); // ascLen -= read_audio_specific_config(filter, gb); + skip_bits(bs, ascLen); + } + + // these are not needed... perhaps + latm->frame_length_type = read_bits(bs, 3); + switch(latm->frame_length_type) { + case 0: + read_bits(bs, 8); + break; + case 1: + read_bits(bs, 9); + break; + case 3: + case 4: + case 5: + read_bits(bs, 6); // celp_table_index + break; + case 6: + case 7: + read_bits(bs, 1); // hvxc_table_index + } + + if (read_bits(bs, 1)) { // other data? + if (audio_mux_version) + latm_get_value(bs); // other_data_bits + else { + int esc; + do { + esc = read_bits(bs, 1); + read_bits(bs, 8); + } while (esc); + } + } + + if (read_bits(bs, 1)) // crc present? + read_bits(bs, 8); // config_crc + } +} + + + +/** + * Parse AAC LATM + */ +void +parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, uint8_t *data, + int len) +{ + latm_private_t *latm; + + bitstream_t bs; + int slot_len, tmp; + + init_bits(&bs, data, len); + + if((latm = st->st_priv) == NULL) + latm = st->st_priv = calloc(1, sizeof(latm_private_t)); + + if(!read_bits1(&bs)) { + latm->configured = 1; + read_stream_mux_config(latm, &bs); + } + + if(!latm->configured) + return; + + if(latm->frame_length_type != 0) + return; + + slot_len = 0; + do { + tmp = read_bits(&bs, 8); + slot_len += tmp; + } while (tmp == 255); + + printf("TYPE = %d, muxslotlen = %d\n", + read_bits(&bs, 3), slot_len); + +} diff --git a/src/parser_latm.h b/src/parser_latm.h new file mode 100644 index 00000000..45b9651a --- /dev/null +++ b/src/parser_latm.h @@ -0,0 +1,26 @@ +/* + * Packet parsing functions + * Copyright (C) 2007 Andreas Öman + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#ifndef PARSER_LATM_H_ +#define PARSER_LATM_H_ + +void +parse_latm_audio_mux_element(th_transport_t *t, th_stream_t *st, uint8_t *data, + int len); + +#endif /* PARSER_LATM_H_ */ diff --git a/src/parsers.c b/src/parsers.c index 9cfbe11b..19a36a76 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -28,6 +28,7 @@ #include "tvhead.h" #include "parsers.h" #include "parser_h264.h" +#include "parser_latm.h" #include "bitstream.h" #include "packet.h" #include "transports.h" @@ -85,6 +86,9 @@ static void parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, static void parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data, int len, int start, aparser_t *vp); +static void parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data, + int len, int start); + static void parse_mpegaudio(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt); static void parse_ac3(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt); @@ -137,6 +141,11 @@ parse_raw_mpeg(th_transport_t *t, th_stream_t *st, uint8_t *data, case SCT_AC3: parse_audio(t, st, data, len, start, parse_ac3); break; + + case SCT_AAC: + if(0) // not yet + parse_aac(t, st, data, len, start); + break; default: break; @@ -144,6 +153,95 @@ parse_raw_mpeg(th_transport_t *t, th_stream_t *st, uint8_t *data, } + + + +/** + * Parse AAC LATM + */ +static void +parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data, + int len, int start) +{ + int l, muxlen, p; + + + + if(start) { + int i; + + if(0)for(i = 0; i < st->st_buffer_ptr - 2; i++) { + if(st->st_buffer[i] == 0x56 && (st->st_buffer[i + 1] & 0xe0) == 0xe0) { + muxlen = (st->st_buffer[i + 1] & 0x1f) << 8 | + st->st_buffer[i + 2]; + + printf("AAC Sync at %8d: %8d bytes, next at %d\n", i, muxlen + 3, + i + muxlen + 3); + } + } + + /* Payload unit start */ + st->st_parser_state = 1; + st->st_buffer_ptr = 0; + st->st_parser_ptr = 0; + } + + if(st->st_parser_state == 0) + return; + + if(st->st_buffer == NULL) { + st->st_buffer_size = 4000; + st->st_buffer = malloc(st->st_buffer_size); + } + + if(st->st_buffer_ptr + len >= st->st_buffer_size) { + st->st_buffer_size += len * 4; + st->st_buffer = realloc(st->st_buffer, st->st_buffer_size); + } + + memcpy(st->st_buffer + st->st_buffer_ptr, data, len); + st->st_buffer_ptr += len; + + + if(st->st_parser_ptr == 0) { + int hlen; + + if(st->st_buffer_ptr < 9) + return; + + hlen = parse_pes_header(t, st, st->st_buffer + 6, st->st_buffer_ptr - 6); + if(hlen < 0) + return; + + st->st_parser_ptr += 6 + hlen; + } + + + p = st->st_parser_ptr; + + while((l = st->st_buffer_ptr - p) > 3) { + if(st->st_buffer[p] == 0x56 && (st->st_buffer[p + 1] & 0xe0) == 0xe0) { + muxlen = (st->st_buffer[p + 1] & 0x1f) << 8 | + st->st_buffer[p + 2]; + + if(l < muxlen + 3) + break; + + parse_latm_audio_mux_element(t, st, st->st_buffer + p + 3, muxlen); + + p += muxlen + 3; + } else { + printf("skip\n"); + p++; + } + } + st->st_parser_ptr = p; +} + + + + + /** * Generic video parser * diff --git a/src/tvhead.h b/src/tvhead.h index 13bef2f6..34924456 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -274,6 +274,7 @@ typedef struct th_stream { uint32_t st_startcode; uint32_t st_startcode_offset; int st_parser_state; + int st_parser_ptr; void *st_priv; /* Parser private data */ struct th_pkt *st_curpkt;