wtvdec.c 38.3 KB
Newer Older
1 2
/*
 * Windows Television (WTV) demuxer
3
 * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file
 * Windows Television (WTV) demuxer
 * @author Peter Ross <pross@xvid.org>
 */

#include "libavutil/intreadwrite.h"
29
#include "libavutil/intfloat.h"
30
#include "avformat.h"
31
#include "internal.h"
32
#include "wtv.h"
33
#include "mpegts.h"
34
#include <strings.h>
35 36

/* Macros for formating GUIDs */
37 38 39 40 41 42 43 44 45 46 47 48
#define PRI_PRETTY_GUID \
    "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x"
#define ARG_PRETTY_GUID(g) \
    AV_RL32(g),AV_RL16(g+4),AV_RL16(g+6),g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15]
#define LEN_PRETTY_GUID 34

/*
 *
 * File system routines
 *
 */

49
typedef struct {
50
    AVIOContext *pb_filesystem;  /** file system (AVFormatContext->pb) */
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
    int sector_bits;     /** sector shift bits; used to convert sector number into pb_filesystem offset */
    uint32_t *sectors;   /** file allocation table */
    int nb_sectors;      /** number of sectors */

    int error;
    int64_t position;
    int64_t length;
} WtvFile;

/**
 * @return bytes read, 0 on end of file, or <0 on error
 */
static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size)
{
    WtvFile *wf = opaque;
67
    AVIOContext *pb = wf->pb_filesystem;
68 69
    int nread = 0;

70
    if (wf->error || pb->error)
71 72 73 74 75 76 77 78 79 80
        return -1;
    if (wf->position >= wf->length || url_feof(pb))
        return 0;

    buf_size = FFMIN(buf_size, wf->length - wf->position);
    while(nread < buf_size) {
        int n;
        int remaining_in_sector = (1 << wf->sector_bits) - (wf->position & ((1 << wf->sector_bits) - 1));
        int read_request        = FFMIN(buf_size - nread, remaining_in_sector);

81
        n = avio_read(pb, buf, read_request);
82 83 84 85 86 87 88 89 90
        if (n <= 0)
            break;
        nread += n;
        buf += n;
        wf->position += n;
        if (n == remaining_in_sector) {
            int i = wf->position >> wf->sector_bits;
            if (i >= wf->nb_sectors ||
                (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) &&
91
                avio_seek(pb, (int64_t)wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) {
92 93 94 95 96 97 98 99 100 101 102 103 104 105
                wf->error = 1;
                break;
            }
        }
    }
    return nread;
}

/**
 * @return position (or file length)
 */
static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence)
{
    WtvFile *wf = opaque;
106
    AVIOContext *pb = wf->pb_filesystem;
107 108 109 110 111 112 113 114 115

    if (whence == AVSEEK_SIZE)
        return wf->length;
    else if (whence == SEEK_CUR)
        offset = wf->position + offset;
    else if (whence == SEEK_END)
        offset = wf->length;

    wf->error = offset < 0 || offset >= wf->length ||
116
                avio_seek(pb, ((int64_t)wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS)
117 118 119 120 121 122 123 124 125 126 127 128
                              + (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0;
    wf->position = offset;
    return offset;
}

/**
 * read non-zero integers (le32) from input stream
 * @param pb
 * @param[out] data destination
 * @param     count maximum number of integers to read
 * @return    total number of integers read
 */
129
static int read_ints(AVIOContext *pb, uint32_t *data, int count)
130 131 132
{
    int i, total = 0;
    for (i = 0; i < count; i++) {
133
        if ((data[total] = avio_rl32(pb)))
134 135 136 137 138 139 140 141 142 143 144 145
           total++;
    }
    return total;
}

/**
 * Open file
 * @param first_sector  First sector
 * @param length        Length of file (bytes)
 * @param depth         File allocation table depth
 * @return NULL on error
 */
146
static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int depth, AVFormatContext *s)
147
{
148
    AVIOContext *pb;
149 150 151
    WtvFile *wf;
    uint8_t *buffer;

152
    if (avio_seek(s->pb, first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0)
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
        return NULL;

    wf = av_mallocz(sizeof(WtvFile));
    if (!wf)
        return NULL;

    if (depth == 0) {
        wf->sectors = av_malloc(sizeof(uint32_t));
        if (!wf->sectors) {
            av_free(wf);
            return NULL;
        }
        wf->sectors[0]  = first_sector;
        wf->nb_sectors  = 1;
    } else if (depth == 1) {
        wf->sectors = av_malloc(WTV_SECTOR_SIZE);
        if (!wf->sectors) {
            av_free(wf);
            return NULL;
        }
        wf->nb_sectors  = read_ints(s->pb, wf->sectors, WTV_SECTOR_SIZE / 4);
    } else if (depth == 2) {
        uint32_t sectors1[WTV_SECTOR_SIZE / 4];
        int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4);
        int i;

        wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS);
        if (!wf->sectors) {
            av_free(wf);
            return NULL;
        }
        wf->nb_sectors = 0;
        for (i = 0; i < nb_sectors1; i++) {
186
            if (avio_seek(s->pb, (int64_t)sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)
187 188 189 190 191 192 193 194
                break;
            wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4);
        }
    } else {
        av_log(s, AV_LOG_ERROR, "unsupported file allocation table depth (0x%x)\n", depth);
        av_free(wf);
        return NULL;
    }
195
    wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS;
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

    if (!wf->nb_sectors) {
        av_free(wf->sectors);
        av_free(wf);
        return NULL;
    }

    /* check length */
    length &= 0xFFFFFFFFFFFF;
    if (length > ((int64_t)wf->nb_sectors << wf->sector_bits)) {
        av_log(s, AV_LOG_WARNING, "reported file length (0x%"PRIx64") exceeds number of available sectors (0x%"PRIx64")\n", length, (int64_t)wf->nb_sectors << wf->sector_bits);
        length = (int64_t)wf->nb_sectors <<  wf->sector_bits;
    }
    wf->length = length;

    /* seek to intial sector */
    wf->position = 0;
213
    if (avio_seek(s->pb, (int64_t)wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) {
214 215 216 217 218 219 220 221 222 223 224 225
        av_free(wf->sectors);
        av_free(wf);
        return NULL;
    }

    wf->pb_filesystem = s->pb;
    buffer = av_malloc(1 << wf->sector_bits);
    if (!buffer) {
        av_free(wf->sectors);
        av_free(wf);
        return NULL;
    }
226

227
    pb = avio_alloc_context(buffer, 1 << wf->sector_bits, 0, wf,
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
                           wtvfile_read_packet, NULL, wtvfile_seek);
    if (!pb) {
        av_free(buffer);
        av_free(wf->sectors);
        av_free(wf);
    }
    return pb;
}

/**
 * Open file using filename
 * @param[in]  buf       directory buffer
 * @param      buf_size  directory buffer size
 * @param[in]  filename
 * @param      filename_size size of filename
 * @return NULL on error
 */
245
static AVIOContext * wtvfile_open2(AVFormatContext *s, const uint8_t *buf, int buf_size, const uint8_t *filename, int filename_size)
246
{
247 248 249 250 251 252
    const uint8_t *buf_end = buf + buf_size;

    while(buf + 48 <= buf_end) {
        int dir_length, name_size, first_sector, depth;
        uint64_t file_length;
        const uint8_t *name;
253
        if (ff_guidcmp(buf, ff_dir_entry_guid)) {
254 255
            av_log(s, AV_LOG_ERROR, "unknown guid "FF_PRI_GUID", expected dir_entry_guid; "
                   "remaining directory entries ignored\n", FF_ARG_GUID(buf));
256 257 258 259 260
            break;
        }
        dir_length  = AV_RL16(buf + 16);
        file_length = AV_RL64(buf + 24);
        name_size   = 2 * AV_RL32(buf + 32);
261
        if (buf + 48 + (int64_t)name_size > buf_end || name_size<0) {
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
            av_log(s, AV_LOG_ERROR, "filename exceeds buffer size; remaining directory entries ignored\n");
            break;
        }
        first_sector = AV_RL32(buf + 40 + name_size);
        depth        = AV_RL32(buf + 44 + name_size);

        /* compare file name; test optional null terminator */
        name = buf + 40;
        if (name_size >= filename_size &&
            !memcmp(name, filename, filename_size) &&
            (name_size < filename_size + 2 || !AV_RN16(name + filename_size)))
            return wtvfile_open_sector(first_sector, file_length, depth, s);

        buf += dir_length;
    }
    return 0;
278 279
}

280 281 282 283 284 285
#define wtvfile_open(s, buf, buf_size, filename) \
    wtvfile_open2(s, buf, buf_size, filename, sizeof(filename))

/**
 * Close file opened with wtvfile_open_sector(), or wtv_open()
 */
286
static void wtvfile_close(AVIOContext *pb)
287 288 289
{
    WtvFile *wf = pb->opaque;
    av_free(wf->sectors);
290 291
    av_freep(&pb->opaque);
    av_freep(&pb->buffer);
292 293 294 295 296 297 298 299 300 301 302 303 304 305
    av_free(pb);
}

/*
 *
 * Main demuxer
 *
 */

typedef struct {
    int seen_data;
} WtvStream;

typedef struct {
306
    AVIOContext *pb;       /** timeline file */
307 308 309 310 311 312 313 314 315 316 317
    int64_t epoch;
    int64_t pts;             /** pts for next data chunk */
    int64_t last_valid_pts;  /** latest valid pts, used for interative seeking */

    /* maintain private seek index, as the AVIndexEntry->pos is relative to the
       start of the 'timeline' file, not the file system (AVFormatContext->pb) */
    AVIndexEntry *index_entries;
    int nb_index_entries;
    unsigned int index_entries_allocated_size;
} WtvContext;

318
/* WTV GUIDs */
319
static const ff_asf_guid EVENTID_SubtitleSpanningEvent =
320
    {0x48,0xC0,0xCE,0x5D,0xB9,0xD0,0x63,0x41,0x87,0x2C,0x4F,0x32,0x22,0x3B,0xE8,0x8A};
321
static const ff_asf_guid EVENTID_LanguageSpanningEvent =
322
    {0x6D,0x66,0x92,0xE2,0x02,0x9C,0x8D,0x44,0xAA,0x8D,0x78,0x1A,0x93,0xFD,0xC3,0x95};
323 324 325 326 327 328
static const ff_asf_guid EVENTID_AudioDescriptorSpanningEvent =
    {0x1C,0xD4,0x7B,0x10,0xDA,0xA6,0x91,0x46,0x83,0x69,0x11,0xB2,0xCD,0xAA,0x28,0x8E};
static const ff_asf_guid EVENTID_CtxADescriptorSpanningEvent =
    {0xE6,0xA2,0xB4,0x3A,0x47,0x42,0x34,0x4B,0x89,0x6C,0x30,0xAF,0xA5,0xD2,0x1C,0x24};
static const ff_asf_guid EVENTID_CSDescriptorSpanningEvent =
    {0xD9,0x79,0xE7,0xEf,0xF0,0x97,0x86,0x47,0x80,0x0D,0x95,0xCF,0x50,0x5D,0xDC,0x66};
329 330
static const ff_asf_guid EVENTID_DVBScramblingControlSpanningEvent =
    {0xC4,0xE1,0xD4,0x4B,0xA1,0x90,0x09,0x41,0x82,0x36,0x27,0xF0,0x0E,0x7D,0xCC,0x5B};
331 332 333 334
static const ff_asf_guid EVENTID_StreamIDSpanningEvent =
    {0x68,0xAB,0xF1,0xCA,0x53,0xE1,0x41,0x4D,0xA6,0xB3,0xA7,0xC9,0x98,0xDB,0x75,0xEE};
static const ff_asf_guid EVENTID_TeletextSpanningEvent =
    {0x50,0xD9,0x99,0x95,0x33,0x5F,0x17,0x46,0xAF,0x7C,0x1E,0x54,0xB5,0x10,0xDA,0xA3};
335 336
static const ff_asf_guid EVENTID_AudioTypeSpanningEvent =
    {0xBE,0xBF,0x1C,0x50,0x49,0xB8,0xCE,0x42,0x9B,0xE9,0x3D,0xB8,0x69,0xFB,0x82,0xB3};
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

/* Windows media GUIDs */

/* Media types */
static const ff_asf_guid mediasubtype_mpeg1payload =
    {0x81,0xEB,0x36,0xE4,0x4F,0x52,0xCE,0x11,0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70};
static const ff_asf_guid mediatype_mpeg2_sections =
    {0x6C,0x17,0x5F,0x45,0x06,0x4B,0xCE,0x47,0x9A,0xEF,0x8C,0xAE,0xF7,0x3D,0xF7,0xB5};
static const ff_asf_guid mediatype_mpeg2_pes =
    {0x20,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA};
static const ff_asf_guid mediatype_mstvcaption =
    {0x89,0x8A,0x8B,0xB8,0x49,0xB0,0x80,0x4C,0xAD,0xCF,0x58,0x98,0x98,0x5E,0x22,0xC1};

/* Media subtypes */
static const ff_asf_guid mediasubtype_dvb_subtitle =
    {0xC3,0xCB,0xFF,0x34,0xB3,0xD5,0x71,0x41,0x90,0x02,0xD4,0xC6,0x03,0x01,0x69,0x7F};
static const ff_asf_guid mediasubtype_teletext =
    {0xE3,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};
static const ff_asf_guid mediasubtype_dtvccdata =
    {0xAA,0xDD,0x2A,0xF5,0xF0,0x36,0xF5,0x43,0x95,0xEA,0x6D,0x86,0x64,0x84,0x26,0x2A};
static const ff_asf_guid mediasubtype_mpeg2_sections =
    {0x79,0x85,0x9F,0x4A,0xF8,0x6B,0x92,0x43,0x8A,0x6D,0xD2,0xDD,0x09,0xFA,0x78,0x61};

/* Formats */
static const ff_asf_guid format_videoinfo2 =
    {0xA0,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};

static int read_probe(AVProbeData *p)
{
366
    return ff_guidcmp(p->buf, ff_wtv_guid) ? 0 : AVPROBE_SCORE_MAX;
367 368
}

369 370 371 372 373 374
/**
 * Convert win32 FILETIME to ISO-8601 string
 */
static void filetime_to_iso8601(char *buf, int buf_size, int64_t value)
{
    time_t t = (value / 10000000LL) - 11644473600LL;
375 376 377 378 379
    struct tm *tm = gmtime(&t);
    if (tm)
        strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t));
    else
        buf[0] = '\0';
380 381 382 383 384 385 386 387
}

/**
 * Convert crazy time (100ns since 1 Jan 0001) to ISO-8601 string
 */
static void crazytime_to_iso8601(char *buf, int buf_size, int64_t value)
{
    time_t t = (value / 10000000LL) - 719162LL*86400LL;
388 389 390 391 392
    struct tm *tm = gmtime(&t);
    if (tm)
        strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t));
    else
        buf[0] = '\0';
393 394 395 396
}

/**
 * Convert OLE DATE to ISO-8601 string
397
 * @return <0 on error
398
 */
399
static int oledate_to_iso8601(char *buf, int buf_size, int64_t value)
400
{
401
    time_t t = (av_int2double(value) - 25569.0) * 86400;
402 403
    struct tm *result= gmtime(&t);
    if (!result)
404
        return -1;
405
    strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", result);
406
    return 0;
407 408
}

409
static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
410 411 412 413 414
{
    char mime[1024];
    char description[1024];
    unsigned int filesize;
    AVStream *st;
415
    int64_t pos = avio_tell(pb);
416 417 418 419 420

    avio_get_str16le(pb, INT_MAX, mime, sizeof(mime));
    if (strcmp(mime, "image/jpeg"))
        goto done;

421
    avio_r8(pb);
422
    avio_get_str16le(pb, INT_MAX, description, sizeof(description));
423
    filesize = avio_rl32(pb);
424 425 426
    if (!filesize)
        goto done;

427
    st = avformat_new_stream(s, NULL);
428 429
    if (!st)
        goto done;
430
    av_dict_set(&st->metadata, "title", description, 0);
431 432 433 434 435 436
    st->codec->codec_id   = CODEC_ID_MJPEG;
    st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
    st->codec->extradata  = av_mallocz(filesize);
    if (!st->codec->extradata)
        goto done;
    st->codec->extradata_size = filesize;
437
    avio_read(pb, st->codec->extradata, filesize);
438
done:
439
    avio_seek(pb, pos + length, SEEK_SET);
440 441
}

442
static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int type, int length)
443 444 445 446 447 448 449
{
    int buf_size = FFMAX(2*length, LEN_PRETTY_GUID) + 1;
    char *buf = av_malloc(buf_size);
    if (!buf)
        return;

    if (type == 0 && length == 4) {
450
        snprintf(buf, buf_size, "%"PRIi32, avio_rl32(pb));
451 452 453 454 455 456 457
    } else if (type == 1) {
        avio_get_str16le(pb, length, buf, buf_size);
        if (!strlen(buf)) {
           av_free(buf);
           return;
        }
    } else if (type == 3 && length == 4) {
458
        strcpy(buf, avio_rl32(pb) ? "true" : "false");
459
    } else if (type == 4 && length == 8) {
460
        int64_t num = avio_rl64(pb);
461 462 463 464 465 466
        if (!strcmp(key, "WM/EncodingTime") ||
            !strcmp(key, "WM/MediaOriginalBroadcastDateTime"))
            filetime_to_iso8601(buf, buf_size, num);
        else if (!strcmp(key, "WM/WMRVEncodeTime") ||
                 !strcmp(key, "WM/WMRVEndTime"))
            crazytime_to_iso8601(buf, buf_size, num);
467 468 469 470 471 472
        else if (!strcmp(key, "WM/WMRVExpirationDate")) {
            if (oledate_to_iso8601(buf, buf_size, num) < 0 ) {
                av_free(buf);
                return;
            }
        } else if (!strcmp(key, "WM/WMRVBitrate"))
473
            snprintf(buf, buf_size, "%f", av_int2double(num));
474 475 476
        else
            snprintf(buf, buf_size, "%"PRIi64, num);
    } else if (type == 5 && length == 2) {
477
        snprintf(buf, buf_size, "%"PRIi16, avio_rl16(pb));
478 479
    } else if (type == 6 && length == 16) {
        ff_asf_guid guid;
480
        avio_read(pb, guid, 16);
481 482 483 484 485 486 487 488
        snprintf(buf, buf_size, PRI_PRETTY_GUID, ARG_PRETTY_GUID(guid));
    } else if (type == 2 && !strcmp(key, "WM/Picture")) {
        get_attachment(s, pb, length);
        av_freep(&buf);
        return;
    } else {
        av_freep(&buf);
        av_log(s, AV_LOG_WARNING, "unsupported metadata entry; key:%s, type:%d, length:0x%x\n", key, type, length);
489
        avio_skip(pb, length);
490 491 492
        return;
    }

493
    av_dict_set(&s->metadata, key, buf, 0);
494 495 496 497 498 499
    av_freep(&buf);
}

/**
 * Parse metadata entries
 */
500
static void parse_legacy_attrib(AVFormatContext *s, AVIOContext *pb)
501 502 503 504 505 506
{
    ff_asf_guid guid;
    int length, type;
    while(!url_feof(pb)) {
        char key[1024];
        ff_get_guid(pb, &guid);
507 508
        type   = avio_rl32(pb);
        length = avio_rl32(pb);
509 510
        if (!length)
            break;
511
        if (ff_guidcmp(&guid, ff_metadata_guid)) {
512 513
            av_log(s, AV_LOG_WARNING, "unknown guid "FF_PRI_GUID", expected metadata_guid; "
                   "remaining metadata entries ignored\n", FF_ARG_GUID(guid));
514 515 516 517 518 519 520 521 522
            break;
        }
        avio_get_str16le(pb, INT_MAX, key, sizeof(key));
        get_tag(s, pb, key, type, length);
    }

    ff_metadata_conv(&s->metadata, NULL, ff_asf_metadata_conv);
}

523 524 525 526 527 528
/**
 * parse VIDEOINFOHEADER2 structure
 * @return bytes consumed
 */
static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st)
{
529
    WtvContext *wtv = s->priv_data;
530
    AVIOContext *pb = wtv->pb;
531

532
    avio_skip(pb, 72);  // picture aspect ratio is unreliable
533
    ff_get_bmp_header(pb, st, NULL);
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558

    return 72 + 40;
}

/**
 * Parse MPEG1WAVEFORMATEX extradata structure
 */
static void parse_mpeg1waveformatex(AVStream *st)
{
    /* fwHeadLayer */
    switch (AV_RL16(st->codec->extradata)) {
    case 0x0001 : st->codec->codec_id = CODEC_ID_MP1; break;
    case 0x0002 : st->codec->codec_id = CODEC_ID_MP2; break;
    case 0x0004 : st->codec->codec_id = CODEC_ID_MP3; break;
    }

    st->codec->bit_rate = AV_RL32(st->codec->extradata + 2); /* dwHeadBitrate */

    /* dwHeadMode */
    switch (AV_RL16(st->codec->extradata + 6)) {
    case 1 : case 2 : case 4 : st->codec->channels = 2; break;
    case 8 :                   st->codec->channels = 1; break;
    }
}

559 560 561 562 563 564
/**
 * Initialise stream
 * @param st Stream to initialise, or NULL to create and initialise new stream
 * @return NULL on error
 */
static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int codec_type)
565
{
566 567 568 569 570 571
    if (st) {
        if (st->codec->extradata) {
            av_freep(&st->codec->extradata);
            st->codec->extradata_size = 0;
        }
    } else {
572 573 574
        WtvStream *wst = av_mallocz(sizeof(WtvStream));
        if (!wst)
            return NULL;
575
        st = avformat_new_stream(s, NULL);
576 577
        if (!st)
            return NULL;
578
        st->id = sid;
579
        st->priv_data = wst;
580
    }
581 582
    st->codec->codec_type = codec_type;
    st->need_parsing      = AVSTREAM_PARSE_FULL;
583
    avpriv_set_pts_info(st, 64, 1, 10000000);
584 585 586 587
    return st;
}

/**
588 589
 * parse Media Type structure and populate stream
 * @param st         Stream, or NULL to create new stream
590 591 592 593 594 595
 * @param mediatype  Mediatype GUID
 * @param subtype    Subtype GUID
 * @param formattype Format GUID
 * @param size       Size of format buffer
 * @return NULL on error
 */
596
static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
597 598 599
                                   ff_asf_guid mediatype, ff_asf_guid subtype,
                                   ff_asf_guid formattype, int size)
{
600
    WtvContext *wtv = s->priv_data;
601
    AVIOContext *pb = wtv->pb;
602 603
    if (!ff_guidcmp(subtype, ff_mediasubtype_cpfilters_processed) &&
        !ff_guidcmp(formattype, ff_format_cpfilters_processed)) {
604 605 606 607 608
        ff_asf_guid actual_subtype;
        ff_asf_guid actual_formattype;

        if (size < 32) {
            av_log(s, AV_LOG_WARNING, "format buffer size underflow\n");
609
            avio_skip(pb, size);
610 611 612
            return NULL;
        }

613
        avio_skip(pb, size - 32);
614 615
        ff_get_guid(pb, &actual_subtype);
        ff_get_guid(pb, &actual_formattype);
616
        avio_seek(pb, -size, SEEK_CUR);
617

618
        st = parse_media_type(s, st, sid, mediatype, actual_subtype, actual_formattype, size - 32);
619
        avio_skip(pb, 32);
620
        return st;
621
    } else if (!ff_guidcmp(mediatype, ff_mediatype_audio)) {
622
        st = new_stream(s, st, sid, AVMEDIA_TYPE_AUDIO);
623 624
        if (!st)
            return NULL;
625
        if (!ff_guidcmp(formattype, ff_format_waveformatex)) {
626 627 628
            int ret = ff_get_wav_header(pb, st->codec, size);
            if (ret < 0)
                return NULL;
629
        } else {
630
            if (ff_guidcmp(formattype, ff_format_none))
631
                av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
632
            avio_skip(pb, size);
633 634
        }

635
        if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) {
636 637 638 639 640 641 642
            st->codec->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codec->bits_per_coded_sample);
        } else if (!ff_guidcmp(subtype, mediasubtype_mpeg1payload)) {
            if (st->codec->extradata && st->codec->extradata_size >= 22)
                parse_mpeg1waveformatex(st);
            else
                av_log(s, AV_LOG_WARNING, "MPEG1WAVEFORMATEX underflow\n");
        } else {
643
            st->codec->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype);
644
            if (st->codec->codec_id == CODEC_ID_NONE)
645
                av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
646 647
        }
        return st;
648
    } else if (!ff_guidcmp(mediatype, ff_mediatype_video)) {
649
        st = new_stream(s, st, sid, AVMEDIA_TYPE_VIDEO);
650 651 652 653
        if (!st)
            return NULL;
        if (!ff_guidcmp(formattype, format_videoinfo2)) {
            int consumed = parse_videoinfoheader2(s, st);
654
            avio_skip(pb, FFMAX(size - consumed, 0));
655
        } else if (!ff_guidcmp(formattype, ff_format_mpeg2_video)) {
656
            int consumed = parse_videoinfoheader2(s, st);
657
            avio_skip(pb, FFMAX(size - consumed, 0));
658
        } else {
659
            if (ff_guidcmp(formattype, ff_format_none))
660
                av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
661
            avio_skip(pb, size);
662 663
        }

664
        if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) {
665 666
            st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype));
        } else {
667
            st->codec->codec_id = ff_codec_guid_get_id(ff_video_guids, subtype);
668 669
        }
        if (st->codec->codec_id == CODEC_ID_NONE)
670
            av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
671 672 673
        return st;
    } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_pes) &&
               !ff_guidcmp(subtype, mediasubtype_dvb_subtitle)) {
674
        st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE);
675 676
        if (!st)
            return NULL;
677
        if (ff_guidcmp(formattype, ff_format_none))
678
            av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
679
        avio_skip(pb, size);
680 681 682 683
        st->codec->codec_id = CODEC_ID_DVB_SUBTITLE;
        return st;
    } else if (!ff_guidcmp(mediatype, mediatype_mstvcaption) &&
               (!ff_guidcmp(subtype, mediasubtype_teletext) || !ff_guidcmp(subtype, mediasubtype_dtvccdata))) {
684
        st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE);
685 686
        if (!st)
            return NULL;
687
        if (ff_guidcmp(formattype, ff_format_none))
688
            av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
689
        avio_skip(pb, size);
690 691 692 693
        st->codec->codec_id   = CODEC_ID_DVB_TELETEXT;
        return st;
    } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) &&
               !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) {
694
        if (ff_guidcmp(formattype, ff_format_none))
695
            av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
696
        avio_skip(pb, size);
697 698 699
        return NULL;
    }

700 701 702
    av_log(s, AV_LOG_WARNING, "unknown media type, mediatype:"FF_PRI_GUID
                              ", subtype:"FF_PRI_GUID", formattype:"FF_PRI_GUID"\n",
                              FF_ARG_GUID(mediatype), FF_ARG_GUID(subtype), FF_ARG_GUID(formattype));
703
    avio_skip(pb, size);
704 705 706 707 708 709 710 711 712 713
    return NULL;
}

enum {
    SEEK_TO_DATA = 0,
    SEEK_TO_PTS,
};

/**
 * Parse WTV chunks
714 715
 * @param mode SEEK_TO_DATA or SEEK_TO_PTS
 * @param seekts timestamp
716
 * @param[out] len_ptr Length of data chunk
717 718 719 720 721
 * @return stream index of data chunk, or <0 on error
 */
static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_ptr)
{
    WtvContext *wtv = s->priv_data;
722
    AVIOContext *pb = wtv->pb;
723 724 725 726 727
    while (!url_feof(pb)) {
        ff_asf_guid g;
        int len, sid, consumed;

        ff_get_guid(pb, &g);
728
        len = avio_rl32(pb);
729 730
        if (len < 32)
            break;
731
        sid = avio_rl32(pb) & 0x7FFF;
732
        avio_skip(pb, 8);
733 734
        consumed = 32;

735
        if (!ff_guidcmp(g, ff_stream_guid)) {
736 737 738
            if (ff_find_stream_index(s, sid) < 0) {
                ff_asf_guid mediatype, subtype, formattype;
                int size;
739
                avio_skip(pb, 28);
Peter Ross's avatar
Peter Ross committed
740 741
                ff_get_guid(pb, &mediatype);
                ff_get_guid(pb, &subtype);
742
                avio_skip(pb, 12);
Peter Ross's avatar
Peter Ross committed
743
                ff_get_guid(pb, &formattype);
744
                size = avio_rl32(pb);
Peter Ross's avatar
Peter Ross committed
745 746
                parse_media_type(s, 0, sid, mediatype, subtype, formattype, size);
                consumed += 92 + size;
747
            }
748
        } else if (!ff_guidcmp(g, ff_stream2_guid)) {
749
            int stream_index = ff_find_stream_index(s, sid);
750
            if (stream_index >= 0 && !((WtvStream*)s->streams[stream_index]->priv_data)->seen_data) {
751 752
                ff_asf_guid mediatype, subtype, formattype;
                int size;
753
                avio_skip(pb, 12);
754 755
                ff_get_guid(pb, &mediatype);
                ff_get_guid(pb, &subtype);
756
                avio_skip(pb, 12);
757
                ff_get_guid(pb, &formattype);
758
                size = avio_rl32(pb);
759 760 761
                parse_media_type(s, s->streams[stream_index], sid, mediatype, subtype, formattype, size);
                consumed += 76 + size;
            }
762 763 764 765 766 767
        } else if (!ff_guidcmp(g, EVENTID_AudioDescriptorSpanningEvent) ||
                   !ff_guidcmp(g, EVENTID_CtxADescriptorSpanningEvent) ||
                   !ff_guidcmp(g, EVENTID_CSDescriptorSpanningEvent) ||
                   !ff_guidcmp(g, EVENTID_StreamIDSpanningEvent) ||
                   !ff_guidcmp(g, EVENTID_SubtitleSpanningEvent) ||
                   !ff_guidcmp(g, EVENTID_TeletextSpanningEvent)) {
768 769 770
            int stream_index = ff_find_stream_index(s, sid);
            if (stream_index >= 0) {
                AVStream *st = s->streams[stream_index];
771 772 773 774
                uint8_t buf[258];
                const uint8_t *pbuf = buf;
                int buf_size;

775
                avio_skip(pb, 8);
776 777 778
                consumed += 8;
                if (!ff_guidcmp(g, EVENTID_CtxADescriptorSpanningEvent) ||
                    !ff_guidcmp(g, EVENTID_CSDescriptorSpanningEvent)) {
779
                    avio_skip(pb, 6);
780 781
                    consumed += 6;
                }
782

783
                buf_size = FFMIN(len - consumed, sizeof(buf));
784
                avio_read(pb, buf, buf_size);
785
                consumed += buf_size;
786
                ff_parse_mpeg2_descriptor(s, st, 0, &pbuf, buf + buf_size, NULL, 0, 0, NULL);
787
            }
788 789 790 791 792
        } else if (!ff_guidcmp(g, EVENTID_AudioTypeSpanningEvent)) {
            int stream_index = ff_find_stream_index(s, sid);
            if (stream_index >= 0) {
                AVStream *st = s->streams[stream_index];
                int audio_type;
793
                avio_skip(pb, 8);
794
                audio_type = avio_r8(pb);
795 796 797 798 799 800
                if (audio_type == 2)
                    st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
                else if (audio_type == 3)
                    st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED;
                consumed += 9;
            }
801 802 803
        } else if (!ff_guidcmp(g, EVENTID_DVBScramblingControlSpanningEvent)) {
            int stream_index = ff_find_stream_index(s, sid);
            if (stream_index >= 0) {
804
                avio_skip(pb, 12);
805
                if (avio_rl32(pb))
806 807 808
                    av_log(s, AV_LOG_WARNING, "DVB scrambled stream detected (st:%d), decoding will likely fail\n", stream_index);
                consumed += 16;
            }
809
        } else if (!ff_guidcmp(g, EVENTID_LanguageSpanningEvent)) {
810 811 812
            int stream_index = ff_find_stream_index(s, sid);
            if (stream_index >= 0) {
                AVStream *st = s->streams[stream_index];
813
                uint8_t language[4];
814
                avio_skip(pb, 12);
815
                avio_read(pb, language, 3);
816 817
                if (language[0]) {
                    language[3] = 0;
818
                    av_dict_set(&st->metadata, "language", language, 0);
819 820
                    if (!strcmp(language, "nar") || !strcmp(language, "NAR"))
                        st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED;
821
                }
822 823
                consumed += 15;
            }
824
        } else if (!ff_guidcmp(g, ff_timestamp_guid)) {
825 826
            int stream_index = ff_find_stream_index(s, sid);
            if (stream_index >= 0) {
827
                avio_skip(pb, 8);
828
                wtv->pts = avio_rl64(pb);
Peter Ross's avatar
Peter Ross committed
829 830 831
                consumed += 16;
                if (wtv->pts == -1)
                    wtv->pts = AV_NOPTS_VALUE;
832 833 834 835
                else {
                    wtv->last_valid_pts = wtv->pts;
                    if (wtv->epoch == AV_NOPTS_VALUE || wtv->pts < wtv->epoch)
                        wtv->epoch = wtv->pts;
Peter Ross's avatar
Peter Ross committed
836
                if (mode == SEEK_TO_PTS && wtv->pts >= seekts) {
837
                    avio_skip(pb, WTV_PAD8(len) - consumed);
Peter Ross's avatar
Peter Ross committed
838 839
                    return 0;
                }
840
                }
841
            }
842
        } else if (!ff_guidcmp(g, ff_data_guid)) {
843
            int stream_index = ff_find_stream_index(s, sid);
844
            if (mode == SEEK_TO_DATA && stream_index >= 0 && len > 32 && s->streams[stream_index]->priv_data) {
845 846
                WtvStream *wst = s->streams[stream_index]->priv_data;
                wst->seen_data = 1;
847 848 849 850 851 852 853 854
                if (len_ptr) {
                    *len_ptr = len;
                }
                return stream_index;
            }
        } else if (
            !ff_guidcmp(g, /* DSATTRIB_CAPTURE_STREAMTIME */ (const ff_asf_guid){0x14,0x56,0x1A,0x0C,0xCD,0x30,0x40,0x4F,0xBC,0xBF,0xD0,0x3E,0x52,0x30,0x62,0x07}) ||
            !ff_guidcmp(g, /* DSATTRIB_PicSampleSeq */ (const ff_asf_guid){0x02,0xAE,0x5B,0x2F,0x8F,0x7B,0x60,0x4F,0x82,0xD6,0xE4,0xEA,0x2F,0x1F,0x4C,0x99}) ||
855
            !ff_guidcmp(g, /* DSATTRIB_TRANSPORT_PROPERTIES */ ff_DSATTRIB_TRANSPORT_PROPERTIES) ||
856 857 858 859 860 861 862 863 864 865 866 867 868 869
            !ff_guidcmp(g, /* dvr_ms_vid_frame_rep_data */ (const ff_asf_guid){0xCC,0x32,0x64,0xDD,0x29,0xE2,0xDB,0x40,0x80,0xF6,0xD2,0x63,0x28,0xD2,0x76,0x1F}) ||
            !ff_guidcmp(g, /* EVENTID_ChannelChangeSpanningEvent */ (const ff_asf_guid){0xE5,0xC5,0x67,0x90,0x5C,0x4C,0x05,0x42,0x86,0xC8,0x7A,0xFE,0x20,0xFE,0x1E,0xFA}) ||
            !ff_guidcmp(g, /* EVENTID_ChannelInfoSpanningEvent */ (const ff_asf_guid){0x80,0x6D,0xF3,0x41,0x32,0x41,0xC2,0x4C,0xB1,0x21,0x01,0xA4,0x32,0x19,0xD8,0x1B}) ||
            !ff_guidcmp(g, /* EVENTID_ChannelTypeSpanningEvent */ (const ff_asf_guid){0x51,0x1D,0xAB,0x72,0xD2,0x87,0x9B,0x48,0xBA,0x11,0x0E,0x08,0xDC,0x21,0x02,0x43}) ||
            !ff_guidcmp(g, /* EVENTID_PIDListSpanningEvent */ (const ff_asf_guid){0x65,0x8F,0xFC,0x47,0xBB,0xE2,0x34,0x46,0x9C,0xEF,0xFD,0xBF,0xE6,0x26,0x1D,0x5C}) ||
            !ff_guidcmp(g, /* EVENTID_SignalAndServiceStatusSpanningEvent */ (const ff_asf_guid){0xCB,0xC5,0x68,0x80,0x04,0x3C,0x2B,0x49,0xB4,0x7D,0x03,0x08,0x82,0x0D,0xCE,0x51}) ||
            !ff_guidcmp(g, /* EVENTID_StreamTypeSpanningEvent */ (const ff_asf_guid){0xBC,0x2E,0xAF,0x82,0xA6,0x30,0x64,0x42,0xA8,0x0B,0xAD,0x2E,0x13,0x72,0xAC,0x60}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x1E,0xBE,0xC3,0xC5,0x43,0x92,0xDC,0x11,0x85,0xE5,0x00,0x12,0x3F,0x6F,0x73,0xB9}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x3B,0x86,0xA2,0xB1,0xEB,0x1E,0xC3,0x44,0x8C,0x88,0x1C,0xA3,0xFF,0xE3,0xE7,0x6A}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x4E,0x7F,0x4C,0x5B,0xC4,0xD0,0x38,0x4B,0xA8,0x3E,0x21,0x7F,0x7B,0xBF,0x52,0xE7}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x63,0x36,0xEB,0xFE,0xA1,0x7E,0xD9,0x11,0x83,0x08,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x70,0xE9,0xF1,0xF8,0x89,0xA4,0x4C,0x4D,0x83,0x73,0xB8,0x12,0xE0,0xD5,0xF8,0x1E}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x96,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0x97,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
870 871
            !ff_guidcmp(g, (const ff_asf_guid){0xA1,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
            !ff_guidcmp(g, (const ff_asf_guid){0xF7,0x10,0x02,0xB9,0xEE,0x7C,0xED,0x4E,0xBD,0x7F,0x05,0x40,0x35,0x86,0x18,0xA1})) {
872 873
            //ignore known guids
        } else
874
            av_log(s, AV_LOG_WARNING, "unsupported chunk:"FF_PRI_GUID"\n", FF_ARG_GUID(g));
875

876
        avio_skip(pb, WTV_PAD8(len) - consumed);
877 878 879 880
    }
    return AVERROR_EOF;
}

881
static int read_header(AVFormatContext *s)
882
{
883 884 885
    WtvContext *wtv = s->priv_data;
    int root_sector, root_size;
    uint8_t root[WTV_SECTOR_SIZE];
886
    AVIOContext *pb;
887
    int64_t timeline_pos;
888 889
    int ret;

890 891 892 893 894
    wtv->epoch          =
    wtv->pts            =
    wtv->last_valid_pts = AV_NOPTS_VALUE;

    /* read root directory sector */
895
    avio_skip(s->pb, 0x30);
896
    root_size = avio_rl32(s->pb);
897 898 899 900
    if (root_size > sizeof(root)) {
        av_log(s, AV_LOG_ERROR, "root directory size exceeds sector size\n");
        return AVERROR_INVALIDDATA;
    }
901
    avio_skip(s->pb, 4);
902
    root_sector = avio_rl32(s->pb);
903

904
    avio_seek(s->pb, root_sector << WTV_SECTOR_BITS, SEEK_SET);
905
    root_size = avio_read(s->pb, root, root_size);
906 907 908 909
    if (root_size < 0)
        return AVERROR_INVALIDDATA;

    /* parse chunks up until first data chunk */
910
    wtv->pb = wtvfile_open(s, root, root_size, ff_timeline_le16);
911 912 913 914 915
    if (!wtv->pb) {
        av_log(s, AV_LOG_ERROR, "timeline data missing\n");
        return AVERROR_INVALIDDATA;
    }

916 917 918
    ret = parse_chunks(s, SEEK_TO_DATA, 0, 0);
    if (ret < 0)
        return ret;
919
    avio_seek(wtv->pb, -32, SEEK_CUR);
920

921
    timeline_pos = avio_tell(s->pb); // save before opening another file
922 923

    /* read metadata */
924
    pb = wtvfile_open(s, root, root_size, ff_table_0_entries_legacy_attrib_le16);
925 926 927 928 929 930 931 932
    if (pb) {
        parse_legacy_attrib(s, pb);
        wtvfile_close(pb);
    }

    /* read seek index */
    if (s->nb_streams) {
        AVStream *st = s->streams[0];
933
        pb = wtvfile_open(s, root, root_size, ff_table_0_entries_time_le16);
934 935
        if (pb) {
            while(1) {
936 937
                uint64_t timestamp = avio_rl64(pb);
                uint64_t frame_nb  = avio_rl64(pb);
938 939 940 941 942 943
                if (url_feof(pb))
                    break;
                ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,
                                   0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME);
            }
            wtvfile_close(pb);
944

945
            if (wtv->nb_index_entries) {
946
                pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);
947 948 949
                if (pb) {
                    int i;
                    while (1) {
950 951
                        uint64_t frame_nb = avio_rl64(pb);
                        uint64_t position = avio_rl64(pb);
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
                        if (url_feof(pb))
                            break;
                        for (i = wtv->nb_index_entries - 1; i >= 0; i--) {
                            AVIndexEntry *e = wtv->index_entries + i;
                            if (frame_nb > e->size)
                                break;
                            if (position > e->pos)
                                e->pos = position;
                        }
                    }
                    wtvfile_close(pb);
                    st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp;
                }
            }
        }
    }

969
    avio_seek(s->pb, timeline_pos, SEEK_SET);
970 971 972 973 974 975
    return 0;
}

static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
    WtvContext *wtv = s->priv_data;
976
    AVIOContext *pb = wtv->pb;
977 978 979 980 981 982 983 984 985 986 987
    int stream_index, len, ret;

    stream_index = parse_chunks(s, SEEK_TO_DATA, 0, &len);
    if (stream_index < 0)
        return stream_index;

    ret = av_get_packet(pb, pkt, len - 32);
    if (ret < 0)
        return ret;
    pkt->stream_index = stream_index;
    pkt->pts          = wtv->pts;
988
    avio_skip(pb, WTV_PAD8(len) - len);
989 990 991
    return 0;
}

992 993
static int read_seek(AVFormatContext *s, int stream_index,
                     int64_t ts, int flags)
994 995
{
    WtvContext *wtv = s->priv_data;
996
    AVIOContext *pb = wtv->pb;
997 998
    AVStream *st = s->streams[0];
    int64_t ts_relative;
999 1000
    int i;

1001
    if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
1002
        return AVERROR(ENOSYS);
1003 1004 1005 1006 1007 1008 1009 1010 1011

    /* timestamp adjustment is required because wtv->pts values are absolute,
     * whereas AVIndexEntry->timestamp values are relative to epoch. */
    ts_relative = ts;
    if (wtv->epoch != AV_NOPTS_VALUE)
        ts_relative -= wtv->epoch;

    i = ff_index_search_timestamp(wtv->index_entries, wtv->nb_index_entries, ts_relative, flags);
    if (i < 0) {
1012 1013 1014 1015 1016 1017 1018
        if (wtv->last_valid_pts == AV_NOPTS_VALUE || ts < wtv->last_valid_pts) {
            if (avio_seek(pb, 0, SEEK_SET) < 0)
                return -1;
        } else if (st->duration != AV_NOPTS_VALUE && ts_relative > st->duration && wtv->nb_index_entries) {
            if (avio_seek(pb, wtv->index_entries[wtv->nb_index_entries - 1].pos, SEEK_SET) < 0)
                return -1;
        }
1019
        if (parse_chunks(s, SEEK_TO_PTS, ts, 0) < 0)
1020 1021 1022
            return AVERROR(ERANGE);
        return 0;
    }
1023 1024
    if (avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET) < 0)
        return -1;
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
    wtv->pts = wtv->index_entries[i].timestamp;
    if (wtv->epoch != AV_NOPTS_VALUE)
        wtv->pts += wtv->epoch;
    wtv->last_valid_pts = wtv->pts;
    return 0;
}

static int read_close(AVFormatContext *s)
{
    WtvContext *wtv = s->priv_data;
1035
    av_freep(&wtv->index_entries);
1036 1037
    wtvfile_close(wtv->pb);
    return 0;
1038 1039
}

1040
AVInputFormat ff_wtv_demuxer = {
1041 1042 1043 1044 1045 1046
    .name           = "wtv",
    .long_name      = NULL_IF_CONFIG_SMALL("Windows Television (WTV)"),
    .priv_data_size = sizeof(WtvContext),
    .read_probe     = read_probe,
    .read_header    = read_header,
    .read_packet    = read_packet,
1047 1048 1049
    .read_seek      = read_seek,
    .read_close     = read_close,
    .flags          = AVFMT_SHOW_IDS,
1050
};