summaryrefslogtreecommitdiff
path: root/libavformat/matroskadec.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2014-05-26 12:48:56 +0200
committerAnton Khirnov <anton@khirnov.net>2014-05-28 07:50:32 +0200
commit23f741f79327e31be7b2a75ebb2e02111e06e52f (patch)
tree7b8620d9fe6c673a180f547f461eb6d3fa4cf517 /libavformat/matroskadec.c
parent4efdadc8ec50332c812e8a95e8c67f5a260e7cb0 (diff)
matroskadec: parse the channel layout mask for FLAC
It is commonly stored in a vorbiscomment block in codec private data.
Diffstat (limited to 'libavformat/matroskadec.c')
-rw-r--r--libavformat/matroskadec.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 2056391525..e376baeac2 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -55,6 +55,7 @@
#include "internal.h"
#include "isom.h"
#include "matroska.h"
+#include "oggdec.h"
/* For ff_codec_get_id(). */
#include "riff.h"
#include "rmsipr.h"
@@ -1443,6 +1444,7 @@ static int matroska_parse_flac(AVFormatContext *s,
MatroskaTrack *track,
int *offset)
{
+ AVStream *st = track->stream;
uint8_t *p = track->codec_priv.data;
int size = track->codec_priv.size;
@@ -1454,6 +1456,42 @@ static int matroska_parse_flac(AVFormatContext *s,
*offset = 8;
track->codec_priv.size = 8 + FLAC_STREAMINFO_SIZE;
+ p += track->codec_priv.size;
+ size -= track->codec_priv.size;
+
+ /* parse the remaining metadata blocks if present */
+ while (size >= 4) {
+ int block_last, block_type, block_size;
+
+ flac_parse_block_header(p, &block_last, &block_type, &block_size);
+
+ p += 4;
+ size -= 4;
+ if (block_size > size)
+ return 0;
+
+ /* check for the channel mask */
+ if (block_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
+ AVDictionary *dict = NULL;
+ AVDictionaryEntry *chmask;
+
+ ff_vorbis_comment(s, &dict, p, block_size, 0);
+ chmask = av_dict_get(dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0);
+ if (chmask) {
+ uint64_t mask = strtol(chmask->value, NULL, 0);
+ if (!mask || mask & ~0x3ffffULL) {
+ av_log(s, AV_LOG_WARNING,
+ "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
+ } else
+ st->codec->channel_layout = mask;
+ }
+ av_dict_free(&dict);
+ }
+
+ p += block_size;
+ size -= block_size;
+ }
+
return 0;
}