Browse code

wavdec: RIFX file format support

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Thomas Volkert authored on 2014/12/17 20:04:37
Showing 14 changed files
... ...
@@ -5,6 +5,7 @@ version <next>:
5 5
 - nvenc encoder
6 6
 - 10bit spp filter
7 7
 - colorlevels filter
8
+- RIFX format for *.wav files
8 9
 
9 10
 
10 11
 version 2.5:
... ...
@@ -75,7 +75,7 @@ static int read_header(AVFormatContext *s)
75 75
 
76 76
     avio_skip(pb, 16);
77 77
     size=avio_rl32(pb);
78
-    ff_get_wav_header(pb, st->codec, size);
78
+    ff_get_wav_header(pb, st->codec, size, 0);
79 79
 
80 80
     /*
81 81
       8000Hz (Fine-rec) file format has 10 bytes long
... ...
@@ -423,7 +423,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
423 423
 
424 424
     st->codec->codec_type = type;
425 425
     if (type == AVMEDIA_TYPE_AUDIO) {
426
-        int ret = ff_get_wav_header(pb, st->codec, type_specific_size);
426
+        int ret = ff_get_wav_header(pb, st->codec, type_specific_size, 0);
427 427
         if (ret < 0)
428 428
             return ret;
429 429
         if (is_dvr_ms_audio) {
... ...
@@ -794,7 +794,7 @@ static int avi_read_header(AVFormatContext *s)
794 794
 //                    avio_skip(pb, size - 5 * 4);
795 795
                     break;
796 796
                 case AVMEDIA_TYPE_AUDIO:
797
-                    ret = ff_get_wav_header(pb, st->codec, size);
797
+                    ret = ff_get_wav_header(pb, st->codec, size, 0);
798 798
                     if (ret < 0)
799 799
                         return ret;
800 800
                     ast->dshow_block_align = st->codec->block_align;
... ...
@@ -106,7 +106,7 @@ static int dxa_read_header(AVFormatContext *s)
106 106
         ast = avformat_new_stream(s, NULL);
107 107
         if (!ast)
108 108
             return AVERROR(ENOMEM);
109
-        ret = ff_get_wav_header(pb, ast->codec, fsize);
109
+        ret = ff_get_wav_header(pb, ast->codec, fsize, 0);
110 110
         if (ret < 0)
111 111
             return ret;
112 112
         if (ast->codec->sample_rate > 0)
... ...
@@ -1715,7 +1715,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
1715 1715
             ffio_init_context(&b, track->codec_priv.data,
1716 1716
                               track->codec_priv.size,
1717 1717
                               0, NULL, NULL, NULL, NULL);
1718
-            ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size);
1718
+            ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size, 0);
1719 1719
             if (ret < 0)
1720 1720
                 return ret;
1721 1721
             codec_id         = st->codec->codec_id;
... ...
@@ -142,7 +142,7 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f
142 142
             vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16);
143 143
             size -= 164;
144 144
         } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) {
145
-            ret = ff_get_wav_header(pb, ast->codec, 16);
145
+            ret = ff_get_wav_header(pb, ast->codec, 16, 0);
146 146
             if (ret < 0)
147 147
                 return ret;
148 148
             size -= 16;
... ...
@@ -714,7 +714,7 @@ static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
714 714
         return 0;
715 715
     st = c->fc->streams[c->fc->nb_streams-1];
716 716
 
717
-    if ((ret = ff_get_wav_header(pb, st->codec, atom.size)) < 0)
717
+    if ((ret = ff_get_wav_header(pb, st->codec, atom.size, 0)) < 0)
718 718
         av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
719 719
 
720 720
     return ret;
... ...
@@ -62,7 +62,7 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *t
62 62
 int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags);
63 63
 
64 64
 enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps);
65
-int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size);
65
+int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size, int big_endian);
66 66
 
67 67
 extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags()
68 68
 extern const AVCodecTag ff_codec_wav_tags[];
... ...
@@ -80,23 +80,37 @@ static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c)
80 80
     }
81 81
 }
82 82
 
83
-int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size)
83
+/* "big_endian" values are needed for RIFX file format */
84
+int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size, int big_endian)
84 85
 {
85 86
     int id;
86 87
 
87 88
     if (size < 14)
88 89
         avpriv_request_sample(codec, "wav header size < 14");
89 90
 
90
-    id                 = avio_rl16(pb);
91 91
     codec->codec_type  = AVMEDIA_TYPE_AUDIO;
92
-    codec->channels    = avio_rl16(pb);
93
-    codec->sample_rate = avio_rl32(pb);
94
-    codec->bit_rate    = avio_rl32(pb) * 8;
95
-    codec->block_align = avio_rl16(pb);
92
+    if (!big_endian) {
93
+        id                 = avio_rl16(pb);
94
+        codec->channels    = avio_rl16(pb);
95
+        codec->sample_rate = avio_rl32(pb);
96
+        codec->bit_rate    = avio_rl32(pb) * 8;
97
+        codec->block_align = avio_rl16(pb);
98
+    } else {
99
+        id                 = avio_rb16(pb);
100
+        codec->channels    = avio_rb16(pb);
101
+        codec->sample_rate = avio_rb32(pb);
102
+        codec->bit_rate    = avio_rb32(pb) * 8;
103
+        codec->block_align = avio_rb16(pb);
104
+    }
96 105
     if (size == 14) {  /* We're dealing with plain vanilla WAVEFORMAT */
97 106
         codec->bits_per_coded_sample = 8;
98
-    } else
99
-        codec->bits_per_coded_sample = avio_rl16(pb);
107
+    } else {
108
+        if (!big_endian) {
109
+            codec->bits_per_coded_sample = avio_rl16(pb);
110
+        } else {
111
+            codec->bits_per_coded_sample = avio_rb16(pb);
112
+        }
113
+    }
100 114
     if (id == 0xFFFE) {
101 115
         codec->codec_tag = 0;
102 116
     } else {
... ...
@@ -106,6 +120,10 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size)
106 106
     }
107 107
     if (size >= 18) {  /* We're obviously dealing with WAVEFORMATEX */
108 108
         int cbSize = avio_rl16(pb); /* cbSize */
109
+        if (big_endian) {
110
+            avpriv_report_missing_feature(codec, "WAVEFORMATEX support for RIFX files\n");
111
+            return AVERROR_PATCHWELCOME;
112
+        }
109 113
         size  -= 18;
110 114
         cbSize = FFMIN(size, cbSize);
111 115
         if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 56
33 33
 #define LIBAVFORMAT_VERSION_MINOR  15
34
-#define LIBAVFORMAT_VERSION_MICRO 105
34
+#define LIBAVFORMAT_VERSION_MICRO 106
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 37
                                                LIBAVFORMAT_VERSION_MINOR, \
... ...
@@ -57,14 +57,19 @@ typedef struct WAVDemuxContext {
57 57
     int smv_cur_pt;
58 58
     int smv_given_first;
59 59
     int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
60
+    int rifx; // RIFX: integer byte order for parameters is big endian
60 61
 } WAVDemuxContext;
61 62
 
62 63
 #if CONFIG_WAV_DEMUXER
63 64
 
64
-static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
65
+static int64_t next_tag(AVIOContext *pb, uint32_t *tag, int big_endian)
65 66
 {
66 67
     *tag = avio_rl32(pb);
67
-    return avio_rl32(pb);
68
+    if (!big_endian) {
69
+        return avio_rl32(pb);
70
+    } else {
71
+        return avio_rb32(pb);
72
+    }
68 73
 }
69 74
 
70 75
 /* RIFF chunks are always at even offsets relative to where they start. */
... ...
@@ -84,7 +89,7 @@ static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1)
84 84
     for (;;) {
85 85
         if (avio_feof(pb))
86 86
             return AVERROR_EOF;
87
-        size = next_tag(pb, &tag);
87
+        size = next_tag(pb, &tag, wav->rifx);
88 88
         if (tag == tag1)
89 89
             break;
90 90
         wav_seek_tag(wav, pb, size, SEEK_CUR);
... ...
@@ -98,7 +103,7 @@ static int wav_probe(AVProbeData *p)
98 98
     if (p->buf_size <= 32)
99 99
         return 0;
100 100
     if (!memcmp(p->buf + 8, "WAVE", 4)) {
101
-        if (!memcmp(p->buf, "RIFF", 4))
101
+        if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))
102 102
             /* Since the ACT demuxer has a standard WAV header at the top of
103 103
              * its own, the returned score is decreased to avoid a probe
104 104
              * conflict between ACT and WAV. */
... ...
@@ -121,6 +126,7 @@ static void handle_stream_probing(AVStream *st)
121 121
 static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
122 122
 {
123 123
     AVIOContext *pb = s->pb;
124
+    WAVDemuxContext *wav = s->priv_data;
124 125
     int ret;
125 126
 
126 127
     /* parse fmt header */
... ...
@@ -128,7 +134,7 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
128 128
     if (!*st)
129 129
         return AVERROR(ENOMEM);
130 130
 
131
-    ret = ff_get_wav_header(pb, (*st)->codec, size);
131
+    ret = ff_get_wav_header(pb, (*st)->codec, size, wav->rifx);
132 132
     if (ret < 0)
133 133
         return ret;
134 134
     handle_stream_probing(*st);
... ...
@@ -258,7 +264,8 @@ static int wav_read_header(AVFormatContext *s)
258 258
     tag = avio_rl32(pb);
259 259
 
260 260
     rf64 = tag == MKTAG('R', 'F', '6', '4');
261
-    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
261
+    wav->rifx = tag == MKTAG('R', 'I', 'F', 'X');
262
+    if (!rf64 && !wav->rifx && tag != MKTAG('R', 'I', 'F', 'F'))
262 263
         return AVERROR_INVALIDDATA;
263 264
     avio_rl32(pb); /* file size */
264 265
     tag = avio_rl32(pb);
... ...
@@ -288,7 +295,7 @@ static int wav_read_header(AVFormatContext *s)
288 288
 
289 289
     for (;;) {
290 290
         AVStream *vst;
291
-        size         = next_tag(pb, &tag);
291
+        size         = next_tag(pb, &tag, wav->rifx);
292 292
         next_tag_ofs = avio_tell(pb) + size;
293 293
 
294 294
         if (avio_feof(pb))
... ...
@@ -328,7 +335,7 @@ static int wav_read_header(AVFormatContext *s)
328 328
             break;
329 329
         case MKTAG('f', 'a', 'c', 't'):
330 330
             if (!sample_count)
331
-                sample_count = avio_rl32(pb);
331
+                sample_count = (!wav->rifx ? avio_rl32(pb) : avio_rb32(pb));
332 332
             break;
333 333
         case MKTAG('b', 'e', 'x', 't'):
334 334
             if ((ret = wav_parse_bext_tag(s, size)) < 0)
... ...
@@ -662,7 +669,7 @@ static int w64_read_header(AVFormatContext *s)
662 662
 
663 663
         if (!memcmp(guid, ff_w64_guid_fmt, 16)) {
664 664
             /* subtract chunk header size - normal wav file doesn't count it */
665
-            ret = ff_get_wav_header(pb, st->codec, size - 24);
665
+            ret = ff_get_wav_header(pb, st->codec, size - 24, 0);
666 666
             if (ret < 0)
667 667
                 return ret;
668 668
             avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);
... ...
@@ -670,7 +670,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
670 670
         if (!st)
671 671
             return NULL;
672 672
         if (!ff_guidcmp(formattype, ff_format_waveformatex)) {
673
-            int ret = ff_get_wav_header(pb, st->codec, size);
673
+            int ret = ff_get_wav_header(pb, st->codec, size, 0);
674 674
             if (ret < 0)
675 675
                 return NULL;
676 676
         } else {
... ...
@@ -75,7 +75,7 @@ static int xwma_read_header(AVFormatContext *s)
75 75
     if (!st)
76 76
         return AVERROR(ENOMEM);
77 77
 
78
-    ret = ff_get_wav_header(pb, st->codec, size);
78
+    ret = ff_get_wav_header(pb, st->codec, size, 0);
79 79
     if (ret < 0)
80 80
         return ret;
81 81
     st->need_parsing = AVSTREAM_PARSE_NONE;