wav.c 23.9 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 10 11
 * This file is part of FFmpeg.
 *
 * FFmpeg 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
 * FFmpeg 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 FFmpeg; 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;
48 49 50 51 52 53 54
    int64_t smv_data_ofs;
    int smv_block_size;
    int smv_frames_per_jpeg;
    int smv_block;
    int smv_last_stream;
    int smv_eof;
    int audio_eof;
55
    int ignore_length;
Fabrice Bellard's avatar
Fabrice Bellard committed
56 57
} WAVContext;

58
#if CONFIG_WAV_MUXER
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 105 106 107 108 109 110 111 112
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
113 114
static int wav_write_header(AVFormatContext *s)
{
Fabrice Bellard's avatar
Fabrice Bellard committed
115
    WAVContext *wav = s->priv_data;
116
    AVIOContext *pb = s->pb;
117
    int64_t fmt, fact;
Fabrice Bellard's avatar
Fabrice Bellard committed
118

119
    ffio_wfourcc(pb, "RIFF");
120
    avio_wl32(pb, 0); /* file length */
121
    ffio_wfourcc(pb, "WAVE");
Fabrice Bellard's avatar
Fabrice Bellard committed
122 123

    /* format header */
124 125
    fmt = ff_start_tag(pb, "fmt ");
    if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
126
        av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
127
               s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
128 129
        return -1;
    }
130
    ff_end_tag(pb, fmt);
Fabrice Bellard's avatar
Fabrice Bellard committed
131

132
    if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
133
        && s->pb->seekable) {
134
        fact = ff_start_tag(pb, "fact");
135
        avio_wl32(pb, 0);
136
        ff_end_tag(pb, fact);
137 138
    }

139 140 141
    if (wav->write_bext)
        bwf_write_bext_chunk(s);

142
    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
143 144
    wav->maxpts = wav->last_duration = 0;
    wav->minpts = INT64_MAX;
145

Fabrice Bellard's avatar
Fabrice Bellard committed
146
    /* data header */
147
    wav->data = ff_start_tag(pb, "data");
148

149
    avio_flush(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
150 151 152 153

    return 0;
}

154
static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
Fabrice Bellard's avatar
Fabrice Bellard committed
155
{
156
    AVIOContext *pb  = s->pb;
157
    WAVContext    *wav = s->priv_data;
158
    avio_write(pb, pkt->data, pkt->size);
159
    if(pkt->pts != AV_NOPTS_VALUE) {
160 161
        wav->minpts        = FFMIN(wav->minpts, pkt->pts);
        wav->maxpts        = FFMAX(wav->maxpts, pkt->pts);
162 163 164
        wav->last_duration = pkt->duration;
    } else
        av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
165 166 167 168 169
    return 0;
}

static int wav_write_trailer(AVFormatContext *s)
{
170
    AVIOContext *pb  = s->pb;
171
    WAVContext    *wav = s->priv_data;
172
    int64_t file_size;
Fabrice Bellard's avatar
Fabrice Bellard committed
173

174
    avio_flush(pb);
175

176
    if (s->pb->seekable) {
177
        ff_end_tag(pb, wav->data);
Fabrice Bellard's avatar
Fabrice Bellard committed
178 179

        /* update file size */
180
        file_size = avio_tell(pb);
181
        avio_seek(pb, 4, SEEK_SET);
182
        avio_wl32(pb, (uint32_t)(file_size - 8));
183
        avio_seek(pb, file_size, SEEK_SET);
Fabrice Bellard's avatar
Fabrice Bellard committed
184

185
        avio_flush(pb);
186 187 188 189 190 191 192

        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);
193
            avio_seek(pb, wav->data-12, SEEK_SET);
194
            avio_wl32(pb, number_of_samples);
195
            avio_seek(pb, file_size, SEEK_SET);
196
            avio_flush(pb);
197
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
198 199 200
    }
    return 0;
}
201

202 203 204
#define OFFSET(x) offsetof(WAVContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
205
    { "write_bext", "Write BEXT chunk.", OFFSET(write_bext), AV_OPT_TYPE_INT, { 0 }, 0, 1, ENC },
206 207 208 209 210 211 212 213 214 215
    { NULL },
};

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

216
AVOutputFormat ff_wav_muxer = {
217 218 219 220 221 222 223 224 225 226
    .name              = "wav",
    .long_name         = NULL_IF_CONFIG_SMALL("WAV format"),
    .mime_type         = "audio/x-wav",
    .extensions        = "wav",
    .priv_data_size    = sizeof(WAVContext),
    .audio_codec       = CODEC_ID_PCM_S16LE,
    .video_codec       = CODEC_ID_NONE,
    .write_header      = wav_write_header,
    .write_packet      = wav_write_packet,
    .write_trailer     = wav_write_trailer,
227
    .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
228
    .priv_class = &wav_muxer_class,
229
};
230
#endif /* CONFIG_WAV_MUXER */
Fabrice Bellard's avatar
Fabrice Bellard committed
231

232 233

#if CONFIG_WAV_DEMUXER
234

235
static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
236
{
237 238
    *tag = avio_rl32(pb);
    return avio_rl32(pb);
239 240
}

Fabrice Bellard's avatar
Fabrice Bellard committed
241
/* return the size of the found tag */
242
static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
Fabrice Bellard's avatar
Fabrice Bellard committed
243 244
{
    unsigned int tag;
245
    int64_t size;
Fabrice Bellard's avatar
Fabrice Bellard committed
246

247
    for (;;) {
Fabrice Bellard's avatar
Fabrice Bellard committed
248 249
        if (url_feof(pb))
            return -1;
250
        size = next_tag(pb, &tag);
Fabrice Bellard's avatar
Fabrice Bellard committed
251 252
        if (tag == tag1)
            break;
253
        avio_skip(pb, size);
Fabrice Bellard's avatar
Fabrice Bellard committed
254 255 256 257
    }
    return size;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
258 259 260 261 262
static int wav_probe(AVProbeData *p)
{
    /* check file header */
    if (p->buf_size <= 32)
        return 0;
263 264
    if (!memcmp(p->buf + 8, "WAVE", 4)) {
        if (!memcmp(p->buf, "RIFF", 4))
Daniel Verkamp's avatar
Daniel Verkamp committed
265 266 267 268 269 270
            /*
              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;
271 272 273 274
        else if (!memcmp(p->buf,      "RF64", 4) &&
                 !memcmp(p->buf + 12, "ds64", 4))
            return AVPROBE_SCORE_MAX;
    }
Daniel Verkamp's avatar
Daniel Verkamp committed
275
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
276 277
}

278 279 280 281 282 283
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
{
    AVIOContext *pb = s->pb;
    int ret;

    /* parse fmt header */
284
    *st = avformat_new_stream(s, NULL);
285 286 287
    if (!*st)
        return AVERROR(ENOMEM);

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

293
    avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);
294 295 296 297

    return 0;
}

298 299
static inline int wav_parse_bext_string(AVFormatContext *s, const char *key,
                                        int length)
300 301 302 303
{
    char temp[257];
    int ret;

304
    av_assert0(length <= sizeof(temp));
305 306 307 308 309 310
    if ((ret = avio_read(s->pb, temp, length)) < 0)
        return ret;

    temp[length] = 0;

    if (strlen(temp))
311
        return av_dict_set(&s->metadata, key, temp, 0);
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330

    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);
331
    snprintf(temp, sizeof(temp), "%"PRIu64, time_reference);
332
    if ((ret = av_dict_set(&s->metadata, "time_reference", temp, 0)) < 0)
333 334 335 336 337 338 339 340 341 342 343
        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 */
344
                snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64,
345 346 347
                         umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3]);
            } else {
                /* extended UMID */
348
                snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64
349
                                               "%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64,
350 351 352 353
                         umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3],
                         umid_parts[4], umid_parts[5], umid_parts[6], umid_parts[7]);
            }

354
            if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0)
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
                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;
373
        if ((ret = av_dict_set(&s->metadata, "coding_history", coding_history,
374
                               AV_DICT_DONT_STRDUP_VAL)) < 0)
375 376 377 378 379 380
            return ret;
    }

    return 0;
}

381 382 383 384 385 386 387 388
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
389 390 391 392
/* wav input */
static int wav_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
393
    int64_t size, av_uninit(data_size);
394
    int64_t sample_count=0;
395
    int rf64;
396
    uint32_t tag, list_type;
397
    AVIOContext *pb = s->pb;
398
    AVStream *st = NULL;
399
    WAVContext *wav = s->priv_data;
400
    int ret, got_fmt = 0;
401
    int64_t next_tag_ofs, data_ofs = -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
402

403 404
    wav->smv_data_ofs = -1;

Fabrice Bellard's avatar
Fabrice Bellard committed
405
    /* check RIFF header */
406
    tag = avio_rl32(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
407

408 409
    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
Fabrice Bellard's avatar
Fabrice Bellard committed
410
        return -1;
411 412
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
413 414
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return -1;
415

416
    if (rf64) {
417
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
418
            return -1;
419
        size = avio_rl32(pb);
420
        if (size < 24)
421
            return -1;
422 423 424
        avio_rl64(pb); /* RIFF size */
        data_size = avio_rl64(pb);
        sample_count = avio_rl64(pb);
425 426
        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
427
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
428 429 430
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
431
        avio_skip(pb, size - 24); /* skip rest of ds64 chunk */
432

433 434
    }

435
    for (;;) {
436
        AVStream *vst;
437
        size = next_tag(pb, &tag);
438
        next_tag_ofs = avio_tell(pb) + size;
439

440
        if (url_feof(pb))
441 442
            break;

443 444
        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
445
            /* only parse the first 'fmt ' tag found */
446
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st)) < 0) {
447 448 449 450 451
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
452 453
            break;
        case MKTAG('d', 'a', 't', 'a'):
454 455 456 457 458
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

459 460 461 462
            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size = size;
463
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
464 465
            }

466 467
            data_ofs = avio_tell(pb);

468 469 470 471
            /* 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))
Tomas Härdin's avatar
Tomas Härdin committed
472
                goto break_loop;
473
            break;
474
        case MKTAG('f','a','c','t'):
475
            if (!sample_count)
Tomas Härdin's avatar
Tomas Härdin committed
476
                sample_count = avio_rl32(pb);
477
            break;
478 479 480 481
        case MKTAG('b','e','x','t'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
482 483 484 485 486 487 488
        case MKTAG('S','M','V','0'):
            // SMV file, a wav file with video appended.
            if (size != MKTAG('0','2','0','0')) {
                av_log(s, AV_LOG_ERROR, "Unknown SMV version found\n");
                goto break_loop;
            }
            av_log(s, AV_LOG_DEBUG, "Found SMV data\n");
489
            vst = avformat_new_stream(s, NULL);
490 491 492
            if (!vst)
                return AVERROR(ENOMEM);
            avio_r8(pb);
493
            vst->id = 1;
494 495 496 497 498 499 500 501
            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
            vst->codec->codec_id = CODEC_ID_MJPEG;
            vst->codec->width  = avio_rl24(pb);
            vst->codec->height = avio_rl24(pb);
            size = avio_rl24(pb);
            wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
            avio_rl24(pb);
            wav->smv_block_size = avio_rl24(pb);
502
            avpriv_set_pts_info(vst, 32, 1, avio_rl24(pb));
503 504 505 506 507
            vst->duration = avio_rl24(pb);
            avio_rl24(pb);
            avio_rl24(pb);
            wav->smv_frames_per_jpeg = avio_rl24(pb);
            goto break_loop;
508 509 510 511 512 513 514 515 516 517 518 519
        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;
520
        }
521 522 523 524 525 526

        /* 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;
        }
527
    }
528
break_loop:
529 530 531 532 533 534
    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);
535 536

    if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
537
        sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
538 539
    if (sample_count)
        st->duration = sample_count;
540 541

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
542
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
543

Fabrice Bellard's avatar
Fabrice Bellard committed
544 545 546
    return 0;
}

547 548 549
/** Find chunk with w64 GUID by skipping over other chunks
 * @return the size of the found chunk
 */
550
static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16])
551 552 553 554 555
{
    uint8_t guid[16];
    int64_t size;

    while (!url_feof(pb)) {
556 557
        avio_read(pb, guid, 16);
        size = avio_rl64(pb);
558 559 560 561
        if (size <= 24)
            return -1;
        if (!memcmp(guid, guid1, 16))
            return size;
562
        avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24);
563 564 565 566 567 568 569
    }
    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
570 571 572 573 574
#define MAX_SIZE 4096

static int wav_read_packet(AVFormatContext *s,
                           AVPacket *pkt)
{
Daniel Verkamp's avatar
Daniel Verkamp committed
575 576
    int ret, size;
    int64_t left;
577
    AVStream *st;
578
    WAVContext *wav = s->priv_data;
Fabrice Bellard's avatar
Fabrice Bellard committed
579

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
    if (wav->smv_data_ofs > 0) {
        int64_t audio_dts, video_dts;
smv_retry:
        audio_dts = s->streams[0]->cur_dts;
        video_dts = s->streams[1]->cur_dts;
        if (audio_dts != AV_NOPTS_VALUE && video_dts != AV_NOPTS_VALUE) {
            audio_dts = av_rescale_q(audio_dts, s->streams[0]->time_base, AV_TIME_BASE_Q);
            video_dts = av_rescale_q(video_dts, s->streams[1]->time_base, AV_TIME_BASE_Q);
            wav->smv_last_stream = video_dts >= audio_dts;
        }
        wav->smv_last_stream = !wav->smv_last_stream;
        wav->smv_last_stream |= wav->audio_eof;
        wav->smv_last_stream &= !wav->smv_eof;
        if (wav->smv_last_stream) {
            uint64_t old_pos = avio_tell(s->pb);
            uint64_t new_pos = wav->smv_data_ofs +
                wav->smv_block * wav->smv_block_size;
            if (avio_seek(s->pb, new_pos, SEEK_SET) < 0) {
                ret = AVERROR_EOF;
                goto smv_out;
            }
            size = avio_rl24(s->pb);
            ret  = av_get_packet(s->pb, pkt, size);
            if (ret < 0)
                goto smv_out;
            pkt->pos -= 3;
            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
            wav->smv_block++;
            pkt->stream_index = 1;
smv_out:
            avio_seek(s->pb, old_pos, SEEK_SET);
            if (ret == AVERROR_EOF) {
                wav->smv_eof = 1;
                goto smv_retry;
            }
            return ret;
        }
    }

619 620
    st = s->streams[0];

621
    left = wav->data_end - avio_tell(s->pb);
622 623
    if (wav->ignore_length)
        left= INT_MAX;
624 625
    if (left <= 0){
        if (CONFIG_W64_DEMUXER && wav->w64)
Daniel Verkamp's avatar
Daniel Verkamp committed
626
            left = find_guid(s->pb, guid_data) - 24;
627 628
        else
            left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
629 630 631 632
        if (left < 0) {
            wav->audio_eof = 1;
            if (wav->smv_data_ofs > 0 && !wav->smv_eof)
                goto smv_retry;
633
            return AVERROR_EOF;
634
        }
635
        wav->data_end= avio_tell(s->pb) + left;
636 637
    }

638
    size = MAX_SIZE;
639 640 641 642
    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;
643
    }
644 645
    size = FFMIN(size, left);
    ret  = av_get_packet(s->pb, pkt, size);
646 647
    if (ret < 0)
        return ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
648 649 650 651 652
    pkt->stream_index = 0;

    return ret;
}

653
static int wav_read_seek(AVFormatContext *s,
654
                         int stream_index, int64_t timestamp, int flags)
655
{
656
    WAVContext *wav = s->priv_data;
657
    AVStream *st;
658 659 660 661 662 663 664 665 666 667
    wav->smv_eof = 0;
    wav->audio_eof = 0;
    if (wav->smv_data_ofs > 0) {
        int64_t smv_timestamp = timestamp;
        if (stream_index == 0)
            smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base);
        else
            timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
        wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
    }
668 669

    st = s->streams[0];
670
    switch (st->codec->codec_id) {
671 672 673
    case CODEC_ID_MP2:
    case CODEC_ID_MP3:
    case CODEC_ID_AC3:
674
    case CODEC_ID_DTS:
675 676 677 678 679
        /* use generic seeking with dynamically generated indexes */
        return -1;
    default:
        break;
    }
680
    return pcm_read_seek(s, stream_index, timestamp, flags);
681 682
}

683 684 685 686 687 688 689 690 691 692 693 694 695
#define OFFSET(x) offsetof(WAVContext, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption demux_options[] = {
    { "ignore_length", "Ignore length", OFFSET(ignore_length), AV_OPT_TYPE_INT, { 0 }, 0, 1, DEC },
    { NULL },
};

static const AVClass wav_demuxer_class = {
    .class_name = "WAV demuxer",
    .item_name  = av_default_item_name,
    .option     = demux_options,
    .version    = LIBAVUTIL_VERSION_INT,
};
696
AVInputFormat ff_wav_demuxer = {
697 698 699 700 701 702 703
    .name           = "wav",
    .long_name      = NULL_IF_CONFIG_SMALL("WAV format"),
    .priv_data_size = sizeof(WAVContext),
    .read_probe     = wav_probe,
    .read_header    = wav_read_header,
    .read_packet    = wav_read_packet,
    .read_seek      = wav_read_seek,
704
    .flags= AVFMT_GENERIC_INDEX,
705
    .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
706
    .priv_class     = &wav_demuxer_class,
Fabrice Bellard's avatar
Fabrice Bellard committed
707
};
708
#endif /* CONFIG_WAV_DEMUXER */
709 710


Daniel Verkamp's avatar
Daniel Verkamp committed
711
#if CONFIG_W64_DEMUXER
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
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;
}

static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
    int64_t size;
735
    AVIOContext *pb  = s->pb;
736 737 738
    WAVContext    *wav = s->priv_data;
    AVStream *st;
    uint8_t guid[16];
739
    int ret;
740

741
    avio_read(pb, guid, 16);
742 743 744
    if (memcmp(guid, guid_riff, 16))
        return -1;

745
    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */
746 747
        return -1;

748
    avio_read(pb, guid, 16);
749 750 751 752 753 754 755 756 757 758 759
    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;
    }

760
    st = avformat_new_stream(s, NULL);
761 762 763 764
    if (!st)
        return AVERROR(ENOMEM);

    /* subtract chunk header size - normal wav file doesn't count it */
765 766 767
    ret = ff_get_wav_header(pb, st->codec, size - 24);
    if (ret < 0)
        return ret;
768
    avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);
769 770 771

    st->need_parsing = AVSTREAM_PARSE_FULL;

772
    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
773 774 775 776 777 778

    size = find_guid(pb, guid_data);
    if (size < 0) {
        av_log(s, AV_LOG_ERROR, "could not find data guid\n");
        return -1;
    }
779
    wav->data_end = avio_tell(pb) + size - 24;
780 781 782 783 784
    wav->w64      = 1;

    return 0;
}

785
AVInputFormat ff_w64_demuxer = {
786 787 788 789 790 791 792
    .name           = "w64",
    .long_name      = NULL_IF_CONFIG_SMALL("Sony Wave64 format"),
    .priv_data_size = sizeof(WAVContext),
    .read_probe     = w64_probe,
    .read_header    = w64_read_header,
    .read_packet    = wav_read_packet,
    .read_seek      = wav_read_seek,
Daniel Verkamp's avatar
Daniel Verkamp committed
793 794 795
    .flags = AVFMT_GENERIC_INDEX,
    .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0},
};
796
#endif /* CONFIG_W64_DEMUXER */