1 /*
2 * Windows Television (WTV) demuxer
3 * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Windows Television (WTV) demuxer
25 * @author Peter Ross <pross@xvid.org>
26 */
27
28 #include <inttypes.h>
29
38
39 /* Macros for formatting GUIDs */
40 #define PRI_PRETTY_GUID \
41 "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x"
42 #define ARG_PRETTY_GUID(g) \
43 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]
44 #define LEN_PRETTY_GUID 34
45
46 /*
47 * File system routines
48 */
49
52
53 int sector_bits;
/**< sector shift bits; used to convert sector number into pb_filesystem offset */
54 uint32_t *
sectors;
/**< file allocation table */
56
61
63 {
65 }
66
67 /**
68 * @return bytes read, AVERROR_EOF on end of file, or <0 on error
69 */
71 {
74 int nread = 0, n = 0;
75
77 return -1;
80
82 while(nread < buf_size) {
84 int read_request =
FFMIN(buf_size - nread, remaining_in_sector);
85
87 if (n <= 0)
88 break;
89 nread += n;
90 buf += n;
92 if (n == remaining_in_sector) {
98 break;
99 }
100 }
101 }
102 return nread ? nread : n;
103 }
104
105 /**
106 * @return position (or file length)
107 */
109 {
112
115 else if (whence == SEEK_CUR)
117 else if (whence == SEEK_END)
119
125 }
126
127 /**
128 * read non-zero integers (le32) from input stream
129 * @param pb
130 * @param[out] data destination
131 * @param count maximum number of integers to read
132 * @return total number of integers read
133 */
135 {
137 for (
i = 0;
i < count;
i++) {
139 total++;
140 }
141 return total;
142 }
143
144 /**
145 * Open file
146 * @param first_sector First sector
147 * @param length Length of file (bytes)
148 * @param depth File allocation table depth
149 * @return NULL on error
150 */
152 {
157
160
162 if (!wf)
164
165 if (depth == 0) {
170 }
173 } else if (depth == 1) {
178 }
180 } else if (depth == 2) {
184
189 }
191 for (
i = 0;
i < nb_sectors1;
i++) {
193 break;
195 }
196 } else {
200 }
202
207 }
208
212
213 /* check length */
214 length &= 0xFFFFFFFFFFFF;
218 }
220
221 /* seek to initial sector */
227 }
228
235 }
236
239 if (!pb) {
243 }
244 return pb;
245 }
246
247 /**
248 * Open file using filename
249 * @param[in] buf directory buffer
250 * @param buf_size directory buffer size
251 * @param[in] filename
252 * @param filename_size size of filename
253 * @return NULL on error
254 */
256 {
257 const uint8_t *buf_end = buf + buf_size;
258
259 while(buf + 48 <= buf_end) {
260 int dir_length, name_size, first_sector, depth;
261 uint64_t file_length;
265 "remaining directory entries ignored\n",
FF_ARG_GUID(buf));
266 break;
267 }
268 dir_length =
AV_RL16(buf + 16);
269 file_length =
AV_RL64(buf + 24);
270 name_size = 2 *
AV_RL32(buf + 32);
271 if (name_size < 0) {
273 "bad filename length, remaining directory entries ignored\n");
274 break;
275 }
276 if (dir_length == 0) {
278 "bad dir length, remaining directory entries ignored\n");
279 break;
280 }
281 if (48 + (int64_t)name_size > buf_end - buf) {
282 av_log(
s,
AV_LOG_ERROR,
"filename exceeds buffer size; remaining directory entries ignored\n");
283 break;
284 }
285 first_sector =
AV_RL32(buf + 40 + name_size);
286 depth =
AV_RL32(buf + 44 + name_size);
287
288 /* compare file name; test optional null terminator */
290 if (name_size >= filename_size &&
291 !memcmp(
name, filename, filename_size) &&
292 (name_size < filename_size + 2 || !
AV_RN16(
name + filename_size)))
294
295 buf += dir_length;
296 }
298 }
299
300 #define wtvfile_open(s, buf, buf_size, filename) \
301 wtvfile_open2(s, buf, buf_size, filename, sizeof(filename))
302
303 /**
304 * Close file opened with wtvfile_open_sector(), or wtv_open()
305 */
307 {
313 }
314
315 /*
316 * Main demuxer
317 */
318
322
326 int64_t
pts;
/**< pts for next data chunk */
328
329 /* maintain private seek index, as the AVIndexEntry->pos is relative to the
330 start of the 'timeline' file, not the file system (AVFormatContext->pb) */
335
336 /* WTV GUIDs */
338 {0x48,0xC0,0xCE,0x5D,0xB9,0xD0,0x63,0x41,0x87,0x2C,0x4F,0x32,0x22,0x3B,0xE8,0x8A};
340 {0x6D,0x66,0x92,0xE2,0x02,0x9C,0x8D,0x44,0xAA,0x8D,0x78,0x1A,0x93,0xFD,0xC3,0x95};
342 {0x1C,0xD4,0x7B,0x10,0xDA,0xA6,0x91,0x46,0x83,0x69,0x11,0xB2,0xCD,0xAA,0x28,0x8E};
344 {0xE6,0xA2,0xB4,0x3A,0x47,0x42,0x34,0x4B,0x89,0x6C,0x30,0xAF,0xA5,0xD2,0x1C,0x24};
346 {0xD9,0x79,0xE7,0xEf,0xF0,0x97,0x86,0x47,0x80,0x0D,0x95,0xCF,0x50,0x5D,0xDC,0x66};
348 {0xC4,0xE1,0xD4,0x4B,0xA1,0x90,0x09,0x41,0x82,0x36,0x27,0xF0,0x0E,0x7D,0xCC,0x5B};
350 {0x68,0xAB,0xF1,0xCA,0x53,0xE1,0x41,0x4D,0xA6,0xB3,0xA7,0xC9,0x98,0xDB,0x75,0xEE};
352 {0x50,0xD9,0x99,0x95,0x33,0x5F,0x17,0x46,0xAF,0x7C,0x1E,0x54,0xB5,0x10,0xDA,0xA3};
354 {0xBE,0xBF,0x1C,0x50,0x49,0xB8,0xCE,0x42,0x9B,0xE9,0x3D,0xB8,0x69,0xFB,0x82,0xB3};
355
356 /* Windows media GUIDs */
357
358 /* Media types */
360 {0x81,0xEB,0x36,0xE4,0x4F,0x52,0xCE,0x11,0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70};
362 {0x6C,0x17,0x5F,0x45,0x06,0x4B,0xCE,0x47,0x9A,0xEF,0x8C,0xAE,0xF7,0x3D,0xF7,0xB5};
364 {0x20,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA};
366 {0x89,0x8A,0x8B,0xB8,0x49,0xB0,0x80,0x4C,0xAD,0xCF,0x58,0x98,0x98,0x5E,0x22,0xC1};
367
368 /* Media subtypes */
370 {0xC3,0xCB,0xFF,0x34,0xB3,0xD5,0x71,0x41,0x90,0x02,0xD4,0xC6,0x03,0x01,0x69,0x7F};
372 {0xE3,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};
374 {0xAA,0xDD,0x2A,0xF5,0xF0,0x36,0xF5,0x43,0x95,0xEA,0x6D,0x86,0x64,0x84,0x26,0x2A};
376 {0x79,0x85,0x9F,0x4A,0xF8,0x6B,0x92,0x43,0x8A,0x6D,0xD2,0xDD,0x09,0xFA,0x78,0x61};
377
379 {
381 }
382
383 /**
384 * Convert win32 FILETIME to ISO-8601 string
385 * @return <0 on error
386 */
388 {
389 time_t t = (
value / 10000000LL) - 11644473600LL;
390 struct tm tmbuf;
391 struct tm *tm =
gmtime_r(&t, &tmbuf);
392 if (!tm)
393 return -1;
394 if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
395 return -1;
396 return 0;
397 }
398
399 /**
400 * Convert crazy time (100ns since 1 Jan 0001) to ISO-8601 string
401 * @return <0 on error
402 */
404 {
405 time_t t = (
value / 10000000LL) - 719162LL*86400LL;
406 struct tm tmbuf;
407 struct tm *tm =
gmtime_r(&t, &tmbuf);
408 if (!tm)
409 return -1;
410 if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
411 return -1;
412 return 0;
413 }
414
415 /**
416 * Convert OLE DATE to ISO-8601 string
417 * @return <0 on error
418 */
420 {
422 struct tm tmbuf;
423 struct tm *tm=
gmtime_r(&t, &tmbuf);
424 if (!tm)
425 return -1;
426 if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
427 return -1;
428 return 0;
429 }
430
432 {
433 char mime[1024];
435 unsigned int filesize;
438
440 if (strcmp(mime, "image/jpeg"))
441 goto done;
442
446 if (!filesize)
447 goto done;
448
450 goto done;
451 st =
s->streams[
s->nb_streams - 1];
455 done:
457 }
458
460 {
461 int buf_size;
462 char *buf;
463
464 if (!strcmp(
key,
"WM/MediaThumbType")) {
466 return;
467 }
468
471 if (!buf)
472 return;
473
474 if (
type == 0 && length == 4) {
476 }
else if (
type == 1) {
478 if (!strlen(buf)) {
480 return;
481 }
482 }
else if (
type == 3 && length == 4) {
483 strcpy(buf,
avio_rl32(pb) ?
"true" :
"false");
484 }
else if (
type == 4 && length == 8) {
486 if (!strcmp(
key,
"WM/EncodingTime") ||
487 !strcmp(
key,
"WM/MediaOriginalBroadcastDateTime")) {
490 return;
491 }
492 }
else if (!strcmp(
key,
"WM/WMRVEncodeTime") ||
493 !strcmp(
key,
"WM/WMRVEndTime")) {
496 return;
497 }
498 }
else if (!strcmp(
key,
"WM/WMRVExpirationDate")) {
501 return;
502 }
503 }
else if (!strcmp(
key,
"WM/WMRVBitrate"))
505 else
506 snprintf(buf, buf_size,
"%"PRIi64, num);
507 }
else if (
type == 5 && length == 2) {
509 }
else if (
type == 6 && length == 16) {
513 }
else if (
type == 2 && !strcmp(
key,
"WM/Picture")) {
516 return;
517 } else {
521 return;
522 }
523
526 }
527
528 /**
529 * Parse metadata entries
530 */
532 {
540 if (!length)
541 break;
544 "remaining metadata entries ignored\n",
FF_ARG_GUID(guid));
545 break;
546 }
549 }
550
552 }
553
554 /**
555 * parse VIDEOINFOHEADER2 structure
556 * @return bytes consumed
557 */
559 {
562
563 avio_skip(pb, 72);
// picture aspect ratio is unreliable
565
566 return 72 + 40;
567 }
568
569 /**
570 * Parse MPEG1WAVEFORMATEX extradata structure
571 */
573 {
574 /* fwHeadLayer */
579 }
580
582
583 /* dwHeadMode */
585 case 1 :
586 case 2 :
589 break;
592 break;
593 }
594 }
595
596 /**
597 * Initialise stream
598 * @param st Stream to initialise, or NULL to create and initialise new stream
599 * @return NULL on error
600 */
602 {
603 if (st) {
607 }
608 } else {
610 if (!wst)
613 if (!st) {
616 }
619 }
623 return st;
624 }
625
626 /**
627 * parse Media Type structure and populate stream
628 * @param st Stream, or NULL to create new stream
629 * @param mediatype Mediatype GUID
630 * @param subtype Subtype GUID
631 * @param formattype Format GUID
632 * @param size Size of format buffer
633 * @return NULL on error
634 */
638 {
645
650 }
651
658
661 return st;
664 if (!st)
670 } else {
674 }
675
681 else
683 } else {
687 }
688 return st;
691 if (!st)
698 /* ignore extradata; files produced by windows media center contain meaningless mpeg1 sequence header */
700 } else {
704 }
705
708 } else {
710 }
713 return st;
717 if (!st)
723 return st;
727 if (!st)
733 return st;
740 }
741
747 }
748
749 enum {
752 };
753
754 /**
755 * Try to seek over a broken chunk
756 * @return <0 on error
757 */
759 {
768 return 0;
769 }
770 }
772 }
773
774 /**
775 * Parse WTV chunks
776 * @param mode SEEK_TO_DATA or SEEK_TO_PTS
777 * @param seekts timestamp
778 * @param[out] len_ptr Length of data chunk
779 * @return stream index of data chunk, or <0 on error
780 */
782 {
787 int len, sid, consumed;
788
791 if (len < 32 || len > INT_MAX - 7) {
798 continue;
799 }
802 consumed = 32;
803
814 if (size < 0 || size > INT_MAX - 92 - consumed)
817 consumed += 92 +
size;
818 }
821 if (stream_index >= 0 &&
s->streams[stream_index]->priv_data && !((
WtvStream*)
s->streams[stream_index]->priv_data)->seen_data) {
830 if (size < 0 || size > INT_MAX - 76 - consumed)
833 consumed += 76 +
size;
834 }
842 if (stream_index >= 0) {
844 uint8_t buf[258];
845 const uint8_t *pbuf = buf;
846 int buf_size;
847
849 consumed += 8;
853 consumed += 6;
854 }
855
856 buf_size =
FFMIN(
len - consumed,
sizeof(buf));
858 consumed += buf_size;
860 }
863 if (stream_index >= 0) {
865 int audio_type;
868 if (audio_type == 2)
870 else if (audio_type == 3)
872 consumed += 9;
873 }
876 if (stream_index >= 0) {
879 av_log(
s,
AV_LOG_WARNING,
"DVB scrambled stream detected (st:%d), decoding will likely fail\n", stream_index);
880 consumed += 16;
881 }
884 if (stream_index >= 0) {
894 }
895 consumed += 15;
896 }
899 if (stream_index >= 0) {
902 consumed += 16;
905 else {
911 return 0;
912 }
913 }
914 }
917 if (
mode ==
SEEK_TO_DATA && stream_index >= 0 &&
len > 32 &&
s->streams[stream_index]->priv_data) {
918 WtvStream *wst =
s->streams[stream_index]->priv_data;
920 if (len_ptr) {
922 }
923 return stream_index;
924 }
925 }
else if (!
ff_guidcmp(
g,
/* DSATTRIB_WMDRMProtectionInfo */ (
const ff_asf_guid){0x83,0x95,0x74,0x40,0x9D,0x6B,0xEC,0x4E,0xB4,0x3C,0x67,0xA1,0x80,0x1E,0x1A,0x9B})) {
927 if (stream_index >= 0)
928 av_log(
s,
AV_LOG_WARNING,
"encrypted stream detected (st:%d), decoding will likely fail\n", stream_index);
929 } else if (
930 !
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}) ||
931 !
ff_guidcmp(
g,
/* DSATTRIB_PBDATAG_ATTRIBUTE */ (
const ff_asf_guid){0x79,0x66,0xB5,0xE0,0xB9,0x12,0xCC,0x43,0xB7,0xDF,0x57,0x8C,0xAA,0x5A,0x7B,0x63}) ||
932 !
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}) ||
934 !
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}) ||
935 !
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}) ||
936 !
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}) ||
937 !
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}) ||
938 !
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}) ||
939 !
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}) ||
940 !
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}) ||
941 !
ff_guidcmp(
g, (
const ff_asf_guid){0x1E,0xBE,0xC3,0xC5,0x43,0x92,0xDC,0x11,0x85,0xE5,0x00,0x12,0x3F,0x6F,0x73,0xB9}) ||
942 !
ff_guidcmp(
g, (
const ff_asf_guid){0x3B,0x86,0xA2,0xB1,0xEB,0x1E,0xC3,0x44,0x8C,0x88,0x1C,0xA3,0xFF,0xE3,0xE7,0x6A}) ||
943 !
ff_guidcmp(
g, (
const ff_asf_guid){0x4E,0x7F,0x4C,0x5B,0xC4,0xD0,0x38,0x4B,0xA8,0x3E,0x21,0x7F,0x7B,0xBF,0x52,0xE7}) ||
944 !
ff_guidcmp(
g, (
const ff_asf_guid){0x63,0x36,0xEB,0xFE,0xA1,0x7E,0xD9,0x11,0x83,0x08,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
945 !
ff_guidcmp(
g, (
const ff_asf_guid){0x70,0xE9,0xF1,0xF8,0x89,0xA4,0x4C,0x4D,0x83,0x73,0xB8,0x12,0xE0,0xD5,0xF8,0x1E}) ||
949 !
ff_guidcmp(
g, (
const ff_asf_guid){0xF7,0x10,0x02,0xB9,0xEE,0x7C,0xED,0x4E,0xBD,0x7F,0x05,0x40,0x35,0x86,0x18,0xA1})) {
950 //ignore known guids
951 } else
953
955 break;
956
958 }
960 }
961
963 {
965 unsigned root_sector;
966 int root_size;
969 int64_t timeline_pos;
971
975
976 /* read root directory sector */
979 if (root_size > sizeof(root)) {
982 }
985
989 root_size =
avio_read(
s->pb, root, root_size);
990 if (root_size < 0)
992
993 /* parse chunks up until first data chunk */
998 }
999
1004 }
1006
1007 timeline_pos =
avio_tell(
s->pb);
// save before opening another file
1008
1009 /* read metadata */
1011 if (pb) {
1014 }
1015
1017
1018 /* read seek index */
1019 if (
s->nb_streams) {
1022 if (pb) {
1023 while(1) {
1027 break;
1030 }
1032
1035 if (pb) {
1038 uint64_t last_position = 0;
1039 while (1) {
1042 while (e <= e_end && frame_nb > e->
size) {
1043 e->
pos = last_position;
1044 e++;
1045 }
1047 break;
1048 last_position = position;
1049 }
1050 e_end->
pos = last_position;
1053 }
1054 }
1055 }
1056 }
1057
1059 return 0;
1060 }
1061
1063 {
1066 int stream_index,
len,
ret;
1067
1069 if (stream_index < 0)
1070 return stream_index;
1071
1078 return 0;
1079 }
1080
1082 int64_t ts,
int flags)
1083 {
1087 int64_t ts_relative;
1089
1092
1093 /* timestamp adjustment is required because wtv->pts values are absolute,
1094 * whereas AVIndexEntry->timestamp values are relative to epoch. */
1095 ts_relative = ts;
1097 ts_relative -= wtv->
epoch;
1098
1103 return -1;
1106 return -1;
1107 }
1110 return 0;
1111 }
1113 return -1;
1118 return 0;
1119 }
1120
1122 {
1126 return 0;
1127 }
1128
1139 };