aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-03-26 02:42:40 +0100
committerMichael Niedermayer <michaelni@gmx.at>2011-03-26 03:06:30 +0100
commit27ef7b1bcd0577e3f5bdfc524b42b0548567be20 (patch)
treedbb243f25cf614d4951ce9352c89befb3526ed23
parent0bfe349d4a3e2a98c6f4f02fb03d8585e531d850 (diff)
parenteb81cf860cbb23ece082e6a463a2c6ced8c55ead (diff)
downloadffmpeg-27ef7b1bcd0577e3f5bdfc524b42b0548567be20.tar.gz
Merge remote-tracking branch 'newdev/master'
* newdev/master: mov: set audio service type for AC-3 from bitstream mode in the 'dac3' atom. Get audio_service_type for AC-3 based on bitstream mode in the AC-3 parser and decoder, and vice-versa for the AC-3 encoder. Use audio_service_type to set stream disposition. Add APIchanges entry for audio_service_type. Add audio_service_type field to AVCodecContext for encoding and reporting of the service type in the audio bitstream. configure: in check_ld, place new -l flags before existing ones support @heading, @subheading, @subsubheading, and @subsubsection in texi2pod.pl doc: update build system documentation aacenc: indentation aacenc: fix the side calculation in search_for_ms vp8.c: rename EDGE_* to VP8_EDGE_*. Conflicts: doc/APIchanges libavcodec/avcodec.h libavcodec/version.h libavcodec/vp8.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rwxr-xr-xconfigure2
-rw-r--r--doc/APIchanges3
-rw-r--r--doc/build_system.txt51
-rw-r--r--doc/fate.txt45
-rw-r--r--doc/ffmpeg.texi22
-rwxr-xr-xdoc/texi2pod.pl6
-rw-r--r--ffmpeg.c1
-rw-r--r--libavcodec/aac_ac3_parser.c1
-rw-r--r--libavcodec/aac_ac3_parser.h1
-rw-r--r--libavcodec/aaccoder.c4
-rw-r--r--libavcodec/ac3.h1
-rw-r--r--libavcodec/ac3_parser.c5
-rw-r--r--libavcodec/ac3dec.c5
-rw-r--r--libavcodec/ac3dec.h1
-rw-r--r--libavcodec/ac3enc.c16
-rw-r--r--libavcodec/avcodec.h20
-rw-r--r--libavcodec/eac3dec.c2
-rw-r--r--libavcodec/options.c10
-rw-r--r--libavcodec/version.h4
-rw-r--r--libavcodec/vp8.c2
-rw-r--r--libavformat/mov.c6
-rw-r--r--libavformat/utils.c13
22 files changed, 190 insertions, 31 deletions
diff --git a/configure b/configure
index ec1f3a7095..54973e959b 100755
--- a/configure
+++ b/configure
@@ -642,7 +642,7 @@ check_ld(){
test "${f}" = "${f#-l}" && flags="$flags $f" || libs="$libs $f"
done
check_cc $($filter_cflags $flags) || return
- check_cmd $ld $LDFLAGS $flags -o $TMPE $TMPO $extralibs $libs
+ check_cmd $ld $LDFLAGS $flags -o $TMPE $TMPO $libs $extralibs
}
check_cppflags(){
diff --git a/doc/APIchanges b/doc/APIchanges
index 883258da41..c246cef2e1 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -12,6 +12,9 @@ libavutil: 2009-03-08
API changes, most recent first:
+2011-03-25 - 34b47d7 - lavc 52.115.0 - AVCodecContext.audio_service_type
+ Add audio_service_type field to AVCodecContext.
+
2011-XX-XX - XXXXXXX - lavu XX.XXX.X - pixfmt.h
Add PIX_FMT_BGR48LE and PIX_FMT_BGR48BE pixel formats
diff --git a/doc/build_system.txt b/doc/build_system.txt
index 8a200695a5..8e6c63ab68 100644
--- a/doc/build_system.txt
+++ b/doc/build_system.txt
@@ -1,11 +1,38 @@
FFmpeg currently uses a custom build system, this text attempts to document
some of its obscure features and options.
-Options to make:
-make V=1 <target>
- Build target with verbosity 1, instead of 1, 2 can be used too
-make SAMPLES=<path to the fate samples> <target>
- specify the path to the fate samples at make time
+Makefile variables:
+
+V
+ Disable the default terse mode, the full command issued by make and its
+ output will be shown on the screen.
+
+DESTDIR
+ Destination directory for the install targets, useful to prepare packages
+ or install Libav in cross-environments.
+
+Makefile targets:
+
+all
+ Default target, builds all the libraries and the executables.
+
+fate
+ Run the fate test suite, note you must have installed it
+
+fate-list
+ Will list all fate/regression test targets
+
+install
+ Install headers, libraries and programs.
+
+libavformat/output-example
+ Build the libavformat basic example.
+
+libavcodec/api-example
+ Build the libavcodec basic example.
+
+libswscale/swscale-test
+ Build the swscale self-test (useful also as example).
Useful standard make commands:
@@ -21,17 +48,3 @@ make -k
continue build in case of errors, this is useful for the regression tests
sometimes but note it will still not run all reg tests.
-
-Targets to make:
-fate-list
- Will list all fate/regression test targets
-
-fate
- Run the fate test suite, note you must have installed it
-
-
-Setting up local fate:
-use the following command to get the fate test samples
-rsync -aL rsync://rsync.mplayerhq.hu:/samples/fate-suite/ fate/fate-suite
-pass --samples=<path to the samples> to configure or pass the path with the
-SAMPLES variable to make
diff --git a/doc/fate.txt b/doc/fate.txt
new file mode 100644
index 0000000000..a074ed1e5d
--- /dev/null
+++ b/doc/fate.txt
@@ -0,0 +1,45 @@
+FATE Automated Testing Environment
+
+FATE provides a regression testsuite that can be run locally or configured
+to send reports to fate.ffmpeg.org.
+In order to run, it needs a large amount of data (samples and references)
+that is provided separately from the actual source distribution.
+
+Use the following command to get the fate test samples
+
+# rsync -aL rsync://rsync.mplayerhq.hu:/samples/fate-suite/ fate/fate-suite
+
+To inform the build system about the testsuite location, pass
+`--samples=<path to the samples>` to configure or set the SAMPLES Make
+variable or the FATE_SAMPLES environment variable to a suitable value.
+
+For information on how to set up FATE to send results to the official FFmpeg
+testing framework, please refer to the following wiki page:
+http://wiki.multimedia.cx/index.php?title=FATE
+
+FATE Makefile targets:
+
+fate-list
+ Will list all fate/regression test targets.
+
+fate
+ Run the FATE test suite (requires the fate-suite dataset).
+
+Fate Makefile variables:
+
+V
+ Verbosity level, can be set to 0, 1 or 2.
+ * 0: show just the test arguments
+ * 1: show just the command used in the test
+ * 2: show everything
+
+SAMPLES
+ Specify or override the path to the FATE samples at make time, it has a
+ meaning only while running the regression tests.
+
+THREADS
+ Specify how many threads to use while running regression tests, it is
+ quite useful to detect thread-related regressions.
+
+Example:
+ make V=1 SAMPLES=/var/fate/samples THREADS=2 fate
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index b9b738210e..47ed58bb37 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -586,6 +586,28 @@ Set the ISO 639 language code (3 letters) of the current audio stream.
@table @option
@item -atag @var{fourcc/tag}
Force audio tag/fourcc.
+@item -audio_service_type @var{type}
+Set the type of service that the audio stream contains.
+@table @option
+@item ma
+Main Audio Service (default)
+@item ef
+Effects
+@item vi
+Visually Impaired
+@item hi
+Hearing Impaired
+@item di
+Dialogue
+@item co
+Commentary
+@item em
+Emergency
+@item vo
+Voice Over
+@item ka
+Karaoke
+@end table
@item -absf @var{bitstream_filter}
Bitstream filters available are "dump_extra", "remove_extra", "noise", "mp3comp", "mp3decomp".
@end table
diff --git a/doc/texi2pod.pl b/doc/texi2pod.pl
index aa3273ec1a..84c36ff1e1 100755
--- a/doc/texi2pod.pl
+++ b/doc/texi2pod.pl
@@ -231,10 +231,12 @@ while(<$inf>) {
# Single line command handlers.
- /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
+ /^\@(?:section|unnumbered|unnumberedsec|center|heading)\s+(.+)$/
and $_ = "\n=head2 $1\n";
- /^\@subsection\s+(.+)$/
+ /^\@(?:subsection|subheading)\s+(.+)$/
and $_ = "\n=head3 $1\n";
+ /^\@(?:subsubsection|subsubheading)\s+(.+)$/
+ and $_ = "\n=head4 $1\n";
# Block command handlers:
/^\@itemize\s*(\@[a-z]+|\*|-)?/ and do {
diff --git a/ffmpeg.c b/ffmpeg.c
index f471614bd4..6f74e61e18 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2123,6 +2123,7 @@ static int transcode(AVFormatContext **output_files,
codec->sample_rate = icodec->sample_rate;
codec->channels = icodec->channels;
codec->frame_size = icodec->frame_size;
+ codec->audio_service_type = icodec->audio_service_type;
codec->block_align= icodec->block_align;
if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
codec->block_align= 0;
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index 87911619eb..6f6ed895f0 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -94,6 +94,7 @@ get_next:
avctx->channel_layout = s->channel_layout;
}
avctx->frame_size = s->samples;
+ avctx->audio_service_type = s->service_type;
}
avctx->bit_rate = s->bit_rate;
diff --git a/libavcodec/aac_ac3_parser.h b/libavcodec/aac_ac3_parser.h
index 75f6d4be4a..ccc387d3aa 100644
--- a/libavcodec/aac_ac3_parser.h
+++ b/libavcodec/aac_ac3_parser.h
@@ -49,6 +49,7 @@ typedef struct AACAC3ParseContext {
int bit_rate;
int samples;
int64_t channel_layout;
+ int service_type;
int remaining_size;
uint64_t state;
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 79723c61ef..f08b34b823 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -817,7 +817,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
int prevsc = sce->sf_idx[w*16+g];
if (dists[w*16+g] > uplims[w*16+g] && sce->sf_idx[w*16+g] > 60) {
if (find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1))
- sce->sf_idx[w*16+g]--;
+ sce->sf_idx[w*16+g]--;
else //Try to make sure there is some energy in every band
sce->sf_idx[w*16+g]-=2;
}
@@ -1057,7 +1057,7 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe,
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
M[i] = (sce0->coeffs[start+w2*128+i]
+ sce1->coeffs[start+w2*128+i]) * 0.5;
- S[i] = sce0->coeffs[start+w2*128+i]
+ S[i] = M[i]
- sce1->coeffs[start+w2*128+i];
}
abs_pow34_v(L34, sce0->coeffs+start+w2*128, sce0->ics.swb_sizes[g]);
diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h
index 5e0b2621aa..1a8cce9a6d 100644
--- a/libavcodec/ac3.h
+++ b/libavcodec/ac3.h
@@ -87,6 +87,7 @@ typedef struct {
uint16_t crc1;
uint8_t sr_code;
uint8_t bitstream_id;
+ uint8_t bitstream_mode;
uint8_t channel_mode;
uint8_t lfe_on;
uint8_t frame_type;
diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c
index 301aadcd84..43feb5bc38 100644
--- a/libavcodec/ac3_parser.c
+++ b/libavcodec/ac3_parser.c
@@ -69,7 +69,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
skip_bits(gbc, 5); // skip bsid, already got it
- skip_bits(gbc, 3); // skip bitstream mode
+ hdr->bitstream_mode = get_bits(gbc, 3);
hdr->channel_mode = get_bits(gbc, 3);
if(hdr->channel_mode == AC3_CHMODE_STEREO) {
@@ -151,6 +151,9 @@ static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info,
hdr_info->channels = hdr.channels;
hdr_info->channel_layout = hdr.channel_layout;
hdr_info->samples = hdr.num_blocks * 256;
+ hdr_info->service_type = hdr.bitstream_mode;
+ if (hdr.bitstream_mode == 0x7 && hdr.channels > 1)
+ hdr_info->service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
if(hdr.bitstream_id>10)
hdr_info->codec_id = CODEC_ID_EAC3;
else if (hdr_info->codec_id == CODEC_ID_NONE)
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 7f12d9cba0..c4365170f9 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -273,6 +273,7 @@ static int parse_frame_header(AC3DecodeContext *s)
/* get decoding parameters from header info */
s->bit_alloc_params.sr_code = hdr.sr_code;
+ s->bitstream_mode = hdr.bitstream_mode;
s->channel_mode = hdr.channel_mode;
s->channel_layout = hdr.channel_layout;
s->lfe_on = hdr.lfe_on;
@@ -1399,6 +1400,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
if(s->out_channels < s->channels)
s->output_mode = s->out_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO;
}
+ /* set audio service type based on bitstream mode for AC-3 */
+ avctx->audio_service_type = s->bitstream_mode;
+ if (s->bitstream_mode == 0x7 && s->channels > 1)
+ avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
/* decode the audio blocks */
channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index a5b1111123..73044d3f7c 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -79,6 +79,7 @@ typedef struct {
int bit_rate; ///< stream bit rate, in bits-per-second
int sample_rate; ///< sample frequency, in Hz
int num_blocks; ///< number of audio blocks
+ int bitstream_mode; ///< bitstream mode (bsmod)
int channel_mode; ///< channel mode (acmod)
int channel_layout; ///< channel layout
int lfe_on; ///< lfe channel in use
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 72b0291727..f41fd2da61 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -1657,6 +1657,18 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s)
if (s->cutoff > (s->sample_rate >> 1))
s->cutoff = s->sample_rate >> 1;
+ /* validate audio service type / channels combination */
+ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE &&
+ avctx->channels == 1) ||
+ ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_COMMENTARY ||
+ avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_EMERGENCY ||
+ avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_VOICE_OVER)
+ && avctx->channels > 1)) {
+ av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the "
+ "specified number of channels\n");
+ return AVERROR(EINVAL);
+ }
+
return 0;
}
@@ -1799,7 +1811,9 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx)
return ret;
s->bitstream_id = 8 + s->bit_alloc.sr_shift;
- s->bitstream_mode = 0; /* complete main audio service */
+ s->bitstream_mode = avctx->audio_service_type;
+ if (s->bitstream_mode == AV_AUDIO_SERVICE_TYPE_KARAOKE)
+ s->bitstream_mode = 0x7;
s->frame_size_min = 2 * ff_ac3_frame_size_tab[s->frame_size_code][s->bit_alloc.sr_code];
s->bits_written = 0;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5a9411f633..7ab02e635f 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -546,6 +546,19 @@ enum AVLPCType {
AV_LPC_TYPE_NB , ///< Not part of ABI
};
+enum AVAudioServiceType {
+ AV_AUDIO_SERVICE_TYPE_MAIN = 0,
+ AV_AUDIO_SERVICE_TYPE_EFFECTS = 1,
+ AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2,
+ AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3,
+ AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4,
+ AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5,
+ AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6,
+ AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7,
+ AV_AUDIO_SERVICE_TYPE_KARAOKE = 8,
+ AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI
+};
+
typedef struct RcOverride{
int start_frame;
int end_frame;
@@ -2876,6 +2889,13 @@ typedef struct AVCodecContext {
uint64_t vbv_delay;
/**
+ * Type of service that the audio stream conveys.
+ * - encoding: Set by user.
+ * - decoding: Set by libavcodec.
+ */
+ enum AVAudioServiceType audio_service_type;
+
+ /**
* Current statistics for PTS correction.
* - decoding: maintained and used by libavcodec, not intended to be used by user apps
* - encoding: unused
diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c
index 52d15c83f8..40f571ffc7 100644
--- a/libavcodec/eac3dec.c
+++ b/libavcodec/eac3dec.c
@@ -410,7 +410,7 @@ int ff_eac3_parse_header(AC3DecodeContext *s)
/* informational metadata */
if (get_bits1(gbc)) {
- skip_bits(gbc, 3); // skip bit stream mode
+ s->bitstream_mode = get_bits(gbc, 3);
skip_bits(gbc, 2); // skip copyright bit and original bitstream bit
if (s->channel_mode == AC3_CHMODE_STEREO) {
skip_bits(gbc, 4); // skip Dolby surround and headphone mode
diff --git a/libavcodec/options.c b/libavcodec/options.c
index e4bc8a6226..47854d9d08 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -436,6 +436,16 @@ static const AVOption options[]={
{"slice", NULL, 0, FF_OPT_TYPE_CONST, FF_THREAD_SLICE, INT_MIN, INT_MAX, V|E|D, "thread_type"},
{"frame", NULL, 0, FF_OPT_TYPE_CONST, FF_THREAD_FRAME, INT_MIN, INT_MAX, V|E|D, "thread_type"},
{"vbv_delay", "initial buffer fill time in periods of 27Mhz clock", 0, FF_OPT_TYPE_INT64, 0, 0, INT64_MAX},
+{"audio_service_type", "audio service type", OFFSET(audio_service_type), FF_OPT_TYPE_INT, AV_AUDIO_SERVICE_TYPE_MAIN, 0, AV_AUDIO_SERVICE_TYPE_NB-1, A|E, "audio_service_type"},
+{"ma", "Main Audio Service", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_MAIN, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"ef", "Effects", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_EFFECTS, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"vi", "Visually Impaired", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"hi", "Hearing Impaired", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"di", "Dialogue", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_DIALOGUE, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"co", "Commentary", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_COMMENTARY, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"em", "Emergency", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_EMERGENCY, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"vo", "Voice Over", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_VOICE_OVER, INT_MIN, INT_MAX, A|E, "audio_service_type"},
+{"ka", "Karaoke", 0, FF_OPT_TYPE_CONST, AV_AUDIO_SERVICE_TYPE_KARAOKE, INT_MIN, INT_MAX, A|E, "audio_service_type"},
{NULL},
};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 477d85164d..73a6f3382d 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,8 +21,8 @@
#define AVCODEC_VERSION_H
#define LIBAVCODEC_VERSION_MAJOR 52
-#define LIBAVCODEC_VERSION_MINOR 114
-#define LIBAVCODEC_VERSION_MICRO 1
+#define LIBAVCODEC_VERSION_MINOR 115
+#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 073de8e25a..773500caab 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -512,7 +512,7 @@ void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y)
mb->mode = VP8_MVMODE_MV;
/* If we have three distinct MVs, merge first and last if they're the same */
- if (cnt[CNT_SPLITMV] && AV_RN32A(&near_mv[1+VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1+VP8_EDGE_TOPLEFT]))
+ if (cnt[CNT_SPLITMV] && AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT]))
cnt[CNT_NEAREST] += 1;
/* Swap near and nearest if necessary */
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 23ba1d47f0..d819c87802 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -492,16 +492,20 @@ static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVStream *st;
- int ac3info, acmod, lfeon;
+ int ac3info, acmod, lfeon, bsmod;
if (c->fc->nb_streams < 1)
return 0;
st = c->fc->streams[c->fc->nb_streams-1];
ac3info = avio_rb24(pb);
+ bsmod = (ac3info >> 14) & 0x7;
acmod = (ac3info >> 11) & 0x7;
lfeon = (ac3info >> 10) & 0x1;
st->codec->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
+ st->codec->audio_service_type = bsmod;
+ if (st->codec->channels > 1 && bsmod == 0x7)
+ st->codec->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
return 0;
}
diff --git a/libavformat/utils.c b/libavformat/utils.c
index b4b48643dd..ff810a5541 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2445,6 +2445,19 @@ int av_find_stream_info(AVFormatContext *ic)
}else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if(!st->codec->bits_per_coded_sample)
st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id);
+ // set stream disposition based on audio service type
+ switch (st->codec->audio_service_type) {
+ case AV_AUDIO_SERVICE_TYPE_EFFECTS:
+ st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; break;
+ case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:
+ st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED; break;
+ case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:
+ st->disposition = AV_DISPOSITION_HEARING_IMPAIRED; break;
+ case AV_AUDIO_SERVICE_TYPE_COMMENTARY:
+ st->disposition = AV_DISPOSITION_COMMENT; break;
+ case AV_AUDIO_SERVICE_TYPE_KARAOKE:
+ st->disposition = AV_DISPOSITION_KARAOKE; break;
+ }
}
}