[FFmpeg-devel] [RFC] LOAS (aka LATM) demuxer

Janne Grunau janne-ffmpeg
Mon Aug 2 18:20:46 CEST 2010


On Mon, Aug 02, 2010 at 11:38:18AM -0400, Alex Converse wrote:
> On Sun, Aug 1, 2010 at 4:50 PM, Janne Grunau <janne-ffmpeg at jannau.net> wrote:
> > Hi,
> >
> > attached is a first working version of a LOAS/LATM demuxer. Only tested
> > with single audio stream files. No seek support yet since it would
> > require to read all frames. LOAS has no index and no timestamps.
> >
> > It is on its own not very useful since I doubt loas files/streams exists
> > besides the ones I've extracted out of mpeg-ts samples. It needs to be
> > integrated into the mpeg-ts demuxer. I'm not convinced that demuxer
> > chaining is the best way to do it.
> >
> 
> Could MPEG-TS spin it manually the way we handle dv-in-mov?
> 
> > Janne
> >
> > From f5cb3aa15d7ce995a2aca776a4fd668897bbc88a Mon Sep 17 00:00:00 2001
> > From: Janne Grunau <janne at grunau.be>
> > Date: Sun, 1 Aug 2010 22:25:43 +0200
> > Subject: [PATCH] Add MPEG4 Low Overhead Audio Stream demuxer
> >
> > LOAS is just a thin synchronization layer around LATM and is the actual
> > format used in MPEG-TS with stream_type=0x11.
> >
> > The demuxer code contains already all code necessary for a real LATM
> > demuxer but it is pointless since it would require another format to
> > signal if the AudioMuxElement includes an audio configuration.
> >
> > The demuxer should support multiple programs (streams) but is only
> > tested with single stream samples. It misses support for MPEG4 Audio
> > features without decoding support in libavcodec.
> > ---
> > ?Changelog ? ? ? ? ? ? ? ?| ? ?1 +
> > ?libavformat/Makefile ? ? | ? ?1 +
> > ?libavformat/allformats.c | ? ?1 +
> > ?libavformat/avformat.h ? | ? ?2 +-
> > ?libavformat/latmdec.c ? ?| ?574 ++++++++++++++++++++++++++++++++++++++++++++++
> > ?5 files changed, 578 insertions(+), 1 deletions(-)
> > ?create mode 100644 libavformat/latmdec.c
> >
> > diff --git a/Changelog b/Changelog
> > index eded417..c44a25a 100644
> > --- a/Changelog
> > +++ b/Changelog
> > @@ -27,6 +27,7 @@ version <next>:
> > ?- SubRip subtitle file muxer and demuxer
> > ?- Chinese AVS encoding via libxavs
> > ?- ffprobe -show_packets option added
> > +- LOAS/LATM demuxer added
> >
> >
> >
> > diff --git a/libavformat/latmdec.c b/libavformat/latmdec.c
> > new file mode 100644
> > index 0000000..57d762d
> > --- /dev/null
> > +++ b/libavformat/latmdec.c
> > @@ -0,0 +1,574 @@
> > +/*
> > + * copyright (c) 2009 Paul Kendall <paul at kcbbs.gen.nz>
> > + * copyright (c) 2010 Janne Grunau <janne-ffmpeg at jannau.net>
> > + *
> > + * 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
> > + */
> > +
> > +/**
> > + * @file
> > + * LATM/LOAS demuxer
> > + */
> > +
> > +#include "avformat.h"
> > +#include "libavcodec/avcodec.h"
> > +#include "libavcodec/get_bits.h"
> > +#include "libavcodec/put_bits.h"
> > +#include "libavcodec/mpeg4audio.h"
> > +
> > +
> > +#define LOAS_SYNC_WORD 0x2B7 ? ? ? /// LOAS sync word, 11 bits
> > +
> > +#define LATM_MAX_FRAME_SIZE ?(8*1024)
> > +
> > +struct latm_stream_config {
> > + ? ?uint32_t ? ? ? ? ?frame_length;
> > + ? ?uint32_t ? ? ? ? ?mux_slot_length;
> > + ? ?uint8_t ? ? ? ? ? frame_length_type;
> > + ? ?uint8_t ? ? ? ? ? extra[64];
> > + ? ?int ? ? ? ? ? ? ? extrasize;
> > + ? ?MPEG4AudioConfig ?config;
> > +};
> > +
> > +struct latm_demux_context {
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? ?audio_mux_version_A;
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? ?same_time_framing;
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? ?num_sub_frames;
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? ?num_programs;
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? ?num_layers[16];
> > + ? ?struct latm_stream_config ?streams[16];
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?stream_cnt;
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?cur_stream;
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?has_config;
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?read_data;
> > + ? ?AVFormatContext ? ? ? ? ? *s;
> > + ? ?GetBitContext ? ? ? ? ? ? *gb;
> > + ? ?uint8_t ? ? ? ? ? ? ? ? ? *buf;
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?pos;
> > + ? ?int ? ? ? ? ? ? ? ? ? ? ? ?len;
> > + ? ?uint64_t ? ? ? ? ? ? ? ? ? pkt_cnt;
> > +};
> > +
> > +
> > +static inline uint32_t latm_get_value(GetBitContext *gb)
> > +{
> > + ? ?uint8_t num_bytes = get_bits(gb, 2);
> > + ? ?return get_bits_long(gb, num_bytes * 8);
> > +}
> > +
> > +static inline void copy_bits(PutBitContext *pb, GetBitContext *gb, int bits)
> > +{
> > + ? ?put_bits(pb, bits, get_bits(gb, bits));
> 
> unsigned el = get_bits(gb, bits);
> put_bits(pb, eb);
> return el;
> 
> should avoid a bunch of temporaries alter on.

This is still Paul's code. It's probably easier if it just parses the
config and count the bits and copies the whole config later. 

This config parsing code should be shared the existing code in the
decoder.

> > +static void read_ga_specific_config(int audio_object_type, GetBitContext *gb,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?PutBitContext *pb)
> > +{
> > + ? ?int depends_on_coder;
> > + ? ?int ext_flag;
> > +
> > + ? ?copy_bits(pb, gb, 1); ? ? ? ? ? ? ? ? ? ? ? ?// framelen_flag
> > + ? ?depends_on_coder = get_bits(gb, 1);
> > + ? ?put_bits(pb, 1, depends_on_coder);
> > + ? ?if (depends_on_coder)
> > + ? ? ? ?copy_bits(pb, gb, 14); ? ? ? ? ? ? ? ? ? // delay
> > + ? ?ext_flag = get_bits(gb, 1);
> > + ? ?put_bits(pb, 1, ext_flag);
> > +
> > + ? ?if (audio_object_type == AOT_AAC_SCALABLE ||
> > + ? ? ? ?audio_object_type == AOT_ER_AAC_SCALABLE)
> > + ? ? ? ?copy_bits(pb, gb, 3); ? ? ? ? ? ? ? ? ? ?// layer number
> > +
> > + ? ?if (!ext_flag)
> > + ? ? ? ?return;
> > +
> > + ? ?if (audio_object_type == AOT_ER_BSAC) {
> > + ? ? ? ?copy_bits(pb, gb, 5); ? ? ? ? ? ? ? ? ? ?// numOfSubFrame
> > + ? ? ? ?copy_bits(pb, gb, 11); ? ? ? ? ? ? ? ? ? // layer_length
> > + ? ?} else if (audio_object_type == AOT_ER_AAC_LC ||
> > + ? ? ? ? ? ? ? audio_object_type == AOT_ER_AAC_LTP ||
> > + ? ? ? ? ? ? ? audio_object_type == AOT_ER_AAC_SCALABLE ||
> > + ? ? ? ? ? ? ? audio_object_type == AOT_ER_AAC_LD)
> > + ? ? ? ?copy_bits(pb, gb, 3); ? ? ? ? ? ? ? ? ? ?// stuff
> > + ? ?copy_bits(pb, gb, 1); ? ? ? ? ? ? ? ? ? ? ? ?// extflag3
> > +}
> > +
> > +static int read_audio_specific_config(struct latm_stream_config *stream,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?GetBitContext *gb)
> > +{
> > + ? ?PutBitContext pb;
> > + ? ?int ret = 0;
> > + ? ?int audio_object_type;
> > + ? ?int sampling_frequency_index;
> > +
> > + ? ?MPEG4AudioConfig *c = &stream->config;
> > +
> > + ? ?init_put_bits(&pb, stream->extra, sizeof(stream->extra));
> > +
> > + ? ?c->sbr = -1;
> > +
> > + ? ?audio_object_type = get_bits(gb, 5);
> > + ? ?put_bits(&pb, 5, audio_object_type);
> > + ? ?if (audio_object_type == AOT_ESCAPE) {
> > + ? ? ? ?uint8_t extended = get_bits(gb, 6);
> > + ? ? ? ?put_bits(&pb, 6, extended);
> > + ? ? ? ?audio_object_type = AOT_ESCAPE + extended + 1;
> > + ? ?}
> > + ? ?c->object_type = audio_object_type;
> > +
> > + ? ?sampling_frequency_index = get_bits(gb, 4);
> > + ? ?put_bits(&pb, 4, sampling_frequency_index);
> > + ? ?c->sampling_index = sampling_frequency_index;
> > + ? ?c->sample_rate =
> > + ? ? ? ? ? ?ff_mpeg4audio_sample_rates[sampling_frequency_index];
> > + ? ?if (sampling_frequency_index == 0x0f) {
> > + ? ? ? ?c->sample_rate = get_bits_long(gb, 24);
> > + ? ? ? ?put_bits(&pb, 24, c->sample_rate);
> > + ? ?}
> > + ? ?c->chan_config = get_bits(gb, 4);
> 
> Is this allowed to be zero? if so does that trigger a PCE?

yes if PCE == program config element. currently broken, I'll fix it.

...

> > + ? ? ? ?pkt->data = av_malloc(cfg->mux_slot_length);
> 
> if malloc fails?

fixed all locally

thanks

Janne




More information about the ffmpeg-devel mailing list