wav.c 20.1 KB
Newer Older
1
/*
2
 * WAV muxer and demuxer
3
 * Copyright (c) 2001, 2002 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
Daniel Verkamp's avatar
Daniel Verkamp committed
5
 * Sony Wave64 demuxer
6
 * RF64 demuxer
Daniel Verkamp's avatar
Daniel Verkamp committed
7 8
 * Copyright (c) 2009 Daniel Verkamp
 *
9
 * This file is part of Libav.
10
 *
11
 * Libav is free software; you can redistribute it and/or
12 13
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
15
 *
16
 * Libav is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with Libav; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
24
 */
25

26 27
#include "libavutil/avassert.h"
#include "libavutil/dict.h"
28
#include "libavutil/log.h"
29
#include "libavutil/mathematics.h"
30
#include "libavutil/opt.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
31
#include "avformat.h"
32
#include "internal.h"
33
#include "avio_internal.h"
34
#include "pcm.h"
35
#include "riff.h"
36
#include "avio.h"
37
#include "metadata.h"
38

Fabrice Bellard's avatar
Fabrice Bellard committed
39
typedef struct {
40
    const AVClass *class;
41 42
    int64_t data;
    int64_t data_end;
43 44 45
    int64_t minpts;
    int64_t maxpts;
    int last_duration;
Daniel Verkamp's avatar
Daniel Verkamp committed
46
    int w64;
47
    int write_bext;
Fabrice Bellard's avatar
Fabrice Bellard committed
48 49
} WAVContext;

50
#if CONFIG_WAV_MUXER
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
static inline void bwf_write_bext_string(AVFormatContext *s, const char *key, int maxlen)
{
    AVDictionaryEntry *tag;
    int len = 0;

    if (tag = av_dict_get(s->metadata, key, NULL, 0)) {
        len = strlen(tag->value);
        len = FFMIN(len, maxlen);
        avio_write(s->pb, tag->value, len);
    }

    ffio_fill(s->pb, 0, maxlen - len);
}

static void bwf_write_bext_chunk(AVFormatContext *s)
{
    AVDictionaryEntry *tmp_tag;
    uint64_t time_reference = 0;
    int64_t bext = ff_start_tag(s->pb, "bext");

    bwf_write_bext_string(s, "description", 256);
    bwf_write_bext_string(s, "originator", 32);
    bwf_write_bext_string(s, "originator_reference", 32);
    bwf_write_bext_string(s, "origination_date", 10);
    bwf_write_bext_string(s, "origination_time", 8);

    if (tmp_tag = av_dict_get(s->metadata, "time_reference", NULL, 0))
        time_reference = strtoll(tmp_tag->value, NULL, 10);
    avio_wl64(s->pb, time_reference);
    avio_wl16(s->pb, 1);  // set version to 1

    if (tmp_tag = av_dict_get(s->metadata, "umid", NULL, 0)) {
        unsigned char umidpart_str[17] = {0};
        int i;
        uint64_t umidpart;
        int len = strlen(tmp_tag->value+2);

        for (i = 0; i < len/16; i++) {
            memcpy(umidpart_str, tmp_tag->value + 2 + (i*16), 16);
            umidpart = strtoll(umidpart_str, NULL, 16);
            avio_wb64(s->pb, umidpart);
        }
        ffio_fill(s->pb, 0, 64 - i*8);
    } else
        ffio_fill(s->pb, 0, 64); // zero UMID

    ffio_fill(s->pb, 0, 190); // Reserved

    if (tmp_tag = av_dict_get(s->metadata, "coding_history", NULL, 0))
        avio_put_str(s->pb, tmp_tag->value);

    ff_end_tag(s->pb, bext);
}

Fabrice Bellard's avatar
Fabrice Bellard committed
105 106
static int wav_write_header(AVFormatContext *s)
{
Fabrice Bellard's avatar
Fabrice Bellard committed
107
    WAVContext *wav = s->priv_data;
108
    AVIOContext *pb = s->pb;
109
    int64_t fmt, fact;
Fabrice Bellard's avatar
Fabrice Bellard committed
110

111
    ffio_wfourcc(pb, "RIFF");
112
    avio_wl32(pb, 0); /* file length */
113
    ffio_wfourcc(pb, "WAVE");
Fabrice Bellard's avatar
Fabrice Bellard committed
114 115

    /* format header */
116 117
    fmt = ff_start_tag(pb, "fmt ");
    if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
118
        av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
119
               s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
120 121
        return -1;
    }
122
    ff_end_tag(pb, fmt);
Fabrice Bellard's avatar
Fabrice Bellard committed
123

124
    if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
125
        && s->pb->seekable) {
126
        fact = ff_start_tag(pb, "fact");
127
        avio_wl32(pb, 0);
128
        ff_end_tag(pb, fact);
129 130
    }

131 132 133
    if (wav->write_bext)
        bwf_write_bext_chunk(s);

134
    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
135 136
    wav->maxpts = wav->last_duration = 0;
    wav->minpts = INT64_MAX;
137

Fabrice Bellard's avatar
Fabrice Bellard committed
138
    /* data header */
139
    wav->data = ff_start_tag(pb, "data");
140

141
    avio_flush(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
142 143 144 145

    return 0;
}

146
static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
Fabrice Bellard's avatar
Fabrice Bellard committed
147
{
148
    AVIOContext *pb  = s->pb;
149
    WAVContext    *wav = s->priv_data;
150
    avio_write(pb, pkt->data, pkt->size);
151
    if(pkt->pts != AV_NOPTS_VALUE) {
152 153
        wav->minpts        = FFMIN(wav->minpts, pkt->pts);
        wav->maxpts        = FFMAX(wav->maxpts, pkt->pts);
154 155 156
        wav->last_duration = pkt->duration;
    } else
        av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
157 158 159 160 161
    return 0;
}

static int wav_write_trailer(AVFormatContext *s)
{
162
    AVIOContext *pb  = s->pb;
163
    WAVContext    *wav = s->priv_data;
164
    int64_t file_size;
Fabrice Bellard's avatar
Fabrice Bellard committed
165

166
    avio_flush(pb);
167

168
    if (s->pb->seekable) {
169
        ff_end_tag(pb, wav->data);
Fabrice Bellard's avatar
Fabrice Bellard committed
170 171

        /* update file size */
172
        file_size = avio_tell(pb);
173
        avio_seek(pb, 4, SEEK_SET);
174
        avio_wl32(pb, (uint32_t)(file_size - 8));
175
        avio_seek(pb, file_size, SEEK_SET);
Fabrice Bellard's avatar
Fabrice Bellard committed
176

177
        avio_flush(pb);
178 179 180 181 182 183 184

        if(s->streams[0]->codec->codec_tag != 0x01) {
            /* Update num_samps in fact chunk */
            int number_of_samples;
            number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
                                           s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
                                           s->streams[0]->time_base.den);
185
            avio_seek(pb, wav->data-12, SEEK_SET);
186
            avio_wl32(pb, number_of_samples);
187
            avio_seek(pb, file_size, SEEK_SET);
188
            avio_flush(pb);
189
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
190 191 192
    }
    return 0;
}
193

194 195 196
#define OFFSET(x) offsetof(WAVContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
197
    { "write_bext", "Write BEXT chunk.", OFFSET(write_bext), AV_OPT_TYPE_INT, { 0 }, 0, 1, ENC },
198 199 200 201 202 203 204 205 206 207
    { NULL },
};

static const AVClass wav_muxer_class = {
    .class_name = "WAV muxer",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};

208
AVOutputFormat ff_wav_muxer = {
209
    .name              = "wav",
210
    .long_name         = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"),
211 212 213
    .mime_type         = "audio/x-wav",
    .extensions        = "wav",
    .priv_data_size    = sizeof(WAVContext),
214 215
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_NONE,
216 217 218
    .write_header      = wav_write_header,
    .write_packet      = wav_write_packet,
    .write_trailer     = wav_write_trailer,
219
    .flags             = AVFMT_TS_NONSTRICT,
220 221
    .codec_tag         = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
    .priv_class        = &wav_muxer_class,
222
};
223
#endif /* CONFIG_WAV_MUXER */
Fabrice Bellard's avatar
Fabrice Bellard committed
224

225 226

#if CONFIG_WAV_DEMUXER
227

228
static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
229
{
230 231
    *tag = avio_rl32(pb);
    return avio_rl32(pb);
232 233
}

Fabrice Bellard's avatar
Fabrice Bellard committed
234
/* return the size of the found tag */
235
static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
Fabrice Bellard's avatar
Fabrice Bellard committed
236 237
{
    unsigned int tag;
238
    int64_t size;
Fabrice Bellard's avatar
Fabrice Bellard committed
239

240
    for (;;) {
Anton Khirnov's avatar
Anton Khirnov committed
241
        if (pb->eof_reached)
Fabrice Bellard's avatar
Fabrice Bellard committed
242
            return -1;
243
        size = next_tag(pb, &tag);
Fabrice Bellard's avatar
Fabrice Bellard committed
244 245
        if (tag == tag1)
            break;
246
        avio_skip(pb, size);
Fabrice Bellard's avatar
Fabrice Bellard committed
247 248 249 250
    }
    return size;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
251 252 253 254 255
static int wav_probe(AVProbeData *p)
{
    /* check file header */
    if (p->buf_size <= 32)
        return 0;
256 257
    if (!memcmp(p->buf + 8, "WAVE", 4)) {
        if (!memcmp(p->buf, "RIFF", 4))
Daniel Verkamp's avatar
Daniel Verkamp committed
258 259 260 261 262 263
            /*
              Since ACT demuxer has standard WAV header at top of it's own,
              returning score is decreased to avoid probe conflict
              between ACT and WAV.
            */
            return AVPROBE_SCORE_MAX - 1;
264 265 266 267
        else if (!memcmp(p->buf,      "RF64", 4) &&
                 !memcmp(p->buf + 12, "ds64", 4))
            return AVPROBE_SCORE_MAX;
    }
Daniel Verkamp's avatar
Daniel Verkamp committed
268
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
269 270
}

271 272 273 274 275 276
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
{
    AVIOContext *pb = s->pb;
    int ret;

    /* parse fmt header */
277
    *st = avformat_new_stream(s, NULL);
278 279 280 281 282 283 284 285
    if (!*st)
        return AVERROR(ENOMEM);

    ret = ff_get_wav_header(pb, (*st)->codec, size);
    if (ret < 0)
        return ret;
    (*st)->need_parsing = AVSTREAM_PARSE_FULL;

286
    avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);
287 288 289 290

    return 0;
}

291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
static inline int wav_parse_bext_string(AVFormatContext *s, const char *key,
                                        int length)
{
    char temp[257];
    int ret;

    av_assert0(length <= sizeof(temp));
    if ((ret = avio_read(s->pb, temp, length)) < 0)
        return ret;

    temp[length] = 0;

    if (strlen(temp))
        return av_dict_set(&s->metadata, key, temp, 0);

    return 0;
}

static int wav_parse_bext_tag(AVFormatContext *s, int64_t size)
{
    char temp[131], *coding_history;
    int ret, x;
    uint64_t time_reference;
    int64_t umid_parts[8], umid_mask = 0;

    if ((ret = wav_parse_bext_string(s, "description", 256)) < 0 ||
        (ret = wav_parse_bext_string(s, "originator", 32)) < 0 ||
        (ret = wav_parse_bext_string(s, "originator_reference", 32)) < 0 ||
        (ret = wav_parse_bext_string(s, "origination_date", 10)) < 0 ||
        (ret = wav_parse_bext_string(s, "origination_time", 8)) < 0)
        return ret;

    time_reference = avio_rl64(s->pb);
    snprintf(temp, sizeof(temp), "%"PRIu64, time_reference);
    if ((ret = av_dict_set(&s->metadata, "time_reference", temp, 0)) < 0)
        return ret;

    /* check if version is >= 1, in which case an UMID may be present */
    if (avio_rl16(s->pb) >= 1) {
        for (x = 0; x < 8; x++)
            umid_mask |= umid_parts[x] = avio_rb64(s->pb);

        if (umid_mask) {
            /* the string formatting below is per SMPTE 330M-2004 Annex C */
            if (umid_parts[4] == 0 && umid_parts[5] == 0 && umid_parts[6] == 0 && umid_parts[7] == 0) {
                /* basic UMID */
                snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64,
                         umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3]);
            } else {
                /* extended UMID */
                snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64
                                             "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64,
                         umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3],
                         umid_parts[4], umid_parts[5], umid_parts[6], umid_parts[7]);
            }

            if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0)
                return ret;
        }

        avio_skip(s->pb, 190);
    } else
        avio_skip(s->pb, 254);

    if (size > 602) {
        /* CodingHistory present */
        size -= 602;

        if (!(coding_history = av_malloc(size+1)))
            return AVERROR(ENOMEM);

        if ((ret = avio_read(s->pb, coding_history, size)) < 0)
            return ret;

        coding_history[size] = 0;
        if ((ret = av_dict_set(&s->metadata, "coding_history", coding_history,
367
                               AV_DICT_DONT_STRDUP_VAL)) < 0)
368 369 370 371 372 373 374 375 376 377 378 379 380 381
            return ret;
    }

    return 0;
}

static const AVMetadataConv wav_metadata_conv[] = {
    {"description",      "comment"      },
    {"originator",       "encoded_by"   },
    {"origination_date", "date"         },
    {"origination_time", "creation_time"},
    {0},
};

Fabrice Bellard's avatar
Fabrice Bellard committed
382
/* wav input */
383
static int wav_read_header(AVFormatContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
384
{
385
    int64_t size, av_uninit(data_size);
386
    int64_t sample_count=0;
387
    int rf64;
388
    uint32_t tag, list_type;
389
    AVIOContext *pb = s->pb;
390
    AVStream *st = NULL;
391
    WAVContext *wav = s->priv_data;
392
    int ret, got_fmt = 0;
393
    int64_t next_tag_ofs, data_ofs = -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
394 395

    /* check RIFF header */
396
    tag = avio_rl32(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
397

398 399
    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
Fabrice Bellard's avatar
Fabrice Bellard committed
400
        return -1;
401 402
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
403 404
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return -1;
405

406
    if (rf64) {
407
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
408
            return -1;
409
        size = avio_rl32(pb);
410 411
        if (size < 16)
            return -1;
412 413 414
        avio_rl64(pb); /* RIFF size */
        data_size = avio_rl64(pb);
        sample_count = avio_rl64(pb);
415 416 417 418 419 420
        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
421
        avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
422 423
    }

424 425
    for (;;) {
        size = next_tag(pb, &tag);
426 427
        next_tag_ofs = avio_tell(pb) + size;

428 429 430
        if (pb->eof_reached)
            break;

431 432
        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
433 434 435 436 437 438 439
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
440 441
            break;
        case MKTAG('d', 'a', 't', 'a'):
442 443 444 445 446
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!pb->seekable || (!rf64 && !size))
                goto break_loop;
            break;
462 463 464
        case MKTAG('f','a','c','t'):
            if (!sample_count)
                sample_count = avio_rl32(pb);
465
            break;
466 467 468 469
        case MKTAG('b','e','x','t'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
470 471 472 473 474 475 476 477 478 479 480 481
        case MKTAG('L', 'I', 'S', 'T'):
            list_type = avio_rl32(pb);
            if (size <= 4) {
                av_log(s, AV_LOG_ERROR, "too short LIST");
                return AVERROR_INVALIDDATA;
            }
            switch (list_type) {
            case MKTAG('I', 'N', 'F', 'O'):
                if ((ret = ff_read_riff_info(s, size - 4)) < 0)
                    return ret;
            }
            break;
482
        }
483 484 485 486 487 488

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
489
    }
490
break_loop:
491 492 493 494 495 496
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);
497 498

    if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
499
        sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
500 501
    if (sample_count)
        st->duration = sample_count;
502 503

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
504
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
505

Fabrice Bellard's avatar
Fabrice Bellard committed
506 507 508
    return 0;
}

509 510 511
/** Find chunk with w64 GUID by skipping over other chunks
 * @return the size of the found chunk
 */
512
static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16])
513 514 515 516
{
    uint8_t guid[16];
    int64_t size;

Anton Khirnov's avatar
Anton Khirnov committed
517
    while (!pb->eof_reached) {
518 519
        avio_read(pb, guid, 16);
        size = avio_rl64(pb);
520 521 522 523
        if (size <= 24)
            return -1;
        if (!memcmp(guid, guid1, 16))
            return size;
524
        avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24);
525 526 527 528 529 530 531
    }
    return -1;
}

static const uint8_t guid_data[16] = { 'd', 'a', 't', 'a',
    0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };

Fabrice Bellard's avatar
Fabrice Bellard committed
532 533 534 535 536
#define MAX_SIZE 4096

static int wav_read_packet(AVFormatContext *s,
                           AVPacket *pkt)
{
Daniel Verkamp's avatar
Daniel Verkamp committed
537 538
    int ret, size;
    int64_t left;
539
    AVStream *st;
540
    WAVContext *wav = s->priv_data;
Fabrice Bellard's avatar
Fabrice Bellard committed
541

542 543
    st = s->streams[0];

544
    left = wav->data_end - avio_tell(s->pb);
545 546
    if (left <= 0){
        if (CONFIG_W64_DEMUXER && wav->w64)
Daniel Verkamp's avatar
Daniel Verkamp committed
547
            left = find_guid(s->pb, guid_data) - 24;
548 549 550
        else
            left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
        if (left < 0)
551
            return AVERROR_EOF;
552
        wav->data_end= avio_tell(s->pb) + left;
553 554
    }

555
    size = MAX_SIZE;
556 557 558 559
    if (st->codec->block_align > 1) {
        if (size < st->codec->block_align)
            size = st->codec->block_align;
        size = (size / st->codec->block_align) * st->codec->block_align;
560
    }
561 562
    size = FFMIN(size, left);
    ret  = av_get_packet(s->pb, pkt, size);
563 564
    if (ret < 0)
        return ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
565 566 567 568 569
    pkt->stream_index = 0;

    return ret;
}

570
static int wav_read_seek(AVFormatContext *s,
571
                         int stream_index, int64_t timestamp, int flags)
572 573 574 575
{
    AVStream *st;

    st = s->streams[0];
576
    switch (st->codec->codec_id) {
577 578 579 580
    case AV_CODEC_ID_MP2:
    case AV_CODEC_ID_MP3:
    case AV_CODEC_ID_AC3:
    case AV_CODEC_ID_DTS:
581 582 583 584 585
        /* use generic seeking with dynamically generated indexes */
        return -1;
    default:
        break;
    }
586
    return ff_pcm_read_seek(s, stream_index, timestamp, flags);
587 588
}

589
AVInputFormat ff_wav_demuxer = {
590
    .name           = "wav",
591
    .long_name      = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"),
592 593 594 595 596
    .priv_data_size = sizeof(WAVContext),
    .read_probe     = wav_probe,
    .read_header    = wav_read_header,
    .read_packet    = wav_read_packet,
    .read_seek      = wav_read_seek,
597 598
    .flags          = AVFMT_GENERIC_INDEX,
    .codec_tag      = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
Fabrice Bellard's avatar
Fabrice Bellard committed
599
};
600
#endif /* CONFIG_WAV_DEMUXER */
601 602


Daniel Verkamp's avatar
Daniel Verkamp committed
603
#if CONFIG_W64_DEMUXER
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
static const uint8_t guid_riff[16] = { 'r', 'i', 'f', 'f',
    0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 };

static const uint8_t guid_wave[16] = { 'w', 'a', 'v', 'e',
    0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };

static const uint8_t guid_fmt [16] = { 'f', 'm', 't', ' ',
    0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };

static int w64_probe(AVProbeData *p)
{
    if (p->buf_size <= 40)
        return 0;
    if (!memcmp(p->buf,      guid_riff, 16) &&
        !memcmp(p->buf + 24, guid_wave, 16))
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

624
static int w64_read_header(AVFormatContext *s)
625 626
{
    int64_t size;
627
    AVIOContext *pb  = s->pb;
628 629 630
    WAVContext    *wav = s->priv_data;
    AVStream *st;
    uint8_t guid[16];
631
    int ret;
632

633
    avio_read(pb, guid, 16);
634 635 636
    if (memcmp(guid, guid_riff, 16))
        return -1;

637
    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */
638 639
        return -1;

640
    avio_read(pb, guid, 16);
641 642 643 644 645 646 647 648 649 650 651
    if (memcmp(guid, guid_wave, 16)) {
        av_log(s, AV_LOG_ERROR, "could not find wave guid\n");
        return -1;
    }

    size = find_guid(pb, guid_fmt);
    if (size < 0) {
        av_log(s, AV_LOG_ERROR, "could not find fmt guid\n");
        return -1;
    }

652
    st = avformat_new_stream(s, NULL);
653 654 655 656
    if (!st)
        return AVERROR(ENOMEM);

    /* subtract chunk header size - normal wav file doesn't count it */
657 658 659
    ret = ff_get_wav_header(pb, st->codec, size - 24);
    if (ret < 0)
        return ret;
660
    avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);
661 662 663

    st->need_parsing = AVSTREAM_PARSE_FULL;

664
    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
665 666 667 668 669 670

    size = find_guid(pb, guid_data);
    if (size < 0) {
        av_log(s, AV_LOG_ERROR, "could not find data guid\n");
        return -1;
    }
671
    wav->data_end = avio_tell(pb) + size - 24;
672 673 674 675 676
    wav->w64      = 1;

    return 0;
}

677
AVInputFormat ff_w64_demuxer = {
678
    .name           = "w64",
679
    .long_name      = NULL_IF_CONFIG_SMALL("Sony Wave64"),
680 681 682 683 684
    .priv_data_size = sizeof(WAVContext),
    .read_probe     = w64_probe,
    .read_header    = w64_read_header,
    .read_packet    = wav_read_packet,
    .read_seek      = wav_read_seek,
685 686
    .flags          = AVFMT_GENERIC_INDEX,
    .codec_tag      = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
Daniel Verkamp's avatar
Daniel Verkamp committed
687
};
688
#endif /* CONFIG_W64_DEMUXER */