Mercurial > libavformat.hg
annotate swfdec.c @ 4536:b94bedbb59d7 libavformat
always use multi track since timecode track is present
author | bcoudurier |
---|---|
date | Wed, 18 Feb 2009 07:13:57 +0000 |
parents | 77e0c7511d41 |
children | a3f213a1d3a8 |
rev | line source |
---|---|
0 | 1 /* |
3357 | 2 * Flash Compatible Streaming Format demuxer |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4201
diff
changeset
|
3 * Copyright (c) 2000 Fabrice Bellard |
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4201
diff
changeset
|
4 * Copyright (c) 2003 Tinic Uro |
0 | 5 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
6 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
7 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
0 | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
0 | 12 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
0 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 21 */ |
3286 | 22 |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3424
diff
changeset
|
23 #include "libavutil/intreadwrite.h" |
3302 | 24 #include "swf.h" |
0 | 25 |
26 static int get_swf_tag(ByteIOContext *pb, int *len_ptr) | |
27 { | |
28 int tag, len; | |
885 | 29 |
0 | 30 if (url_feof(pb)) |
31 return -1; | |
32 | |
33 tag = get_le16(pb); | |
34 len = tag & 0x3f; | |
35 tag = tag >> 6; | |
36 if (len == 0x3f) { | |
37 len = get_le32(pb); | |
38 } | |
806 | 39 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len); |
0 | 40 *len_ptr = len; |
41 return tag; | |
42 } | |
43 | |
44 | |
45 static int swf_probe(AVProbeData *p) | |
46 { | |
47 /* check file header */ | |
806 | 48 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' && |
0 | 49 p->buf[2] == 'S') |
50 return AVPROBE_SCORE_MAX; | |
51 else | |
52 return 0; | |
53 } | |
54 | |
55 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
56 { | |
1641 | 57 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
58 ByteIOContext *pb = s->pb; |
2310 | 59 int nbits, len, tag; |
359 | 60 |
806 | 61 tag = get_be32(pb) & 0xffffff00; |
62 | |
2309 | 63 if (tag == MKBETAG('C', 'W', 'S', 0)) { |
887 | 64 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n"); |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
65 return AVERROR(EIO); |
806 | 66 } |
67 if (tag != MKBETAG('F', 'W', 'S', 0)) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
68 return AVERROR(EIO); |
0 | 69 get_le32(pb); |
70 /* skip rectangle size */ | |
71 nbits = get_byte(pb) >> 3; | |
72 len = (4 * nbits - 3 + 7) / 8; | |
73 url_fskip(pb, len); | |
1889 | 74 swf->frame_rate = get_le16(pb); /* 8.8 fixed */ |
0 | 75 get_le16(pb); /* frame count */ |
885 | 76 |
359 | 77 swf->samples_per_frame = 0; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
78 s->ctx_flags |= AVFMTCTX_NOHEADER; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
79 return 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
80 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
81 |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
82 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
83 { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
84 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
85 ByteIOContext *pb = s->pb; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
86 AVStream *vst = NULL, *ast = NULL, *st = 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
87 int tag, len, i, frame, v; |
0 | 88 |
89 for(;;) { | |
90 tag = get_swf_tag(pb, &len); | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
91 if (tag < 0) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
92 return AVERROR(EIO); |
2309 | 93 if (tag == TAG_VIDEOSTREAM && !vst) { |
1637 | 94 int ch_id = get_le16(pb); |
359 | 95 get_le16(pb); |
96 get_le16(pb); | |
97 get_le16(pb); | |
98 get_byte(pb); | |
99 /* Check for FLV1 */ | |
1637 | 100 vst = av_new_stream(s, ch_id); |
2913 | 101 if (!vst) |
102 return -1; | |
1635 | 103 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
104 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb)); | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
105 av_set_pts_info(vst, 64, 256, swf->frame_rate); |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
106 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
107 len -= 10; |
2309 | 108 } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) { |
0 | 109 /* streaming found */ |
1642 | 110 int sample_rate_code; |
0 | 111 get_byte(pb); |
112 v = get_byte(pb); | |
359 | 113 swf->samples_per_frame = get_le16(pb); |
1638 | 114 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */ |
2913 | 115 if (!ast) |
116 return -1; | |
1638 | 117 swf->audio_stream_index = ast->index; |
1636 | 118 ast->codec->channels = 1 + (v&1); |
119 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
1833 | 120 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15); |
2023 | 121 ast->need_parsing = AVSTREAM_PARSE_FULL; |
1642 | 122 sample_rate_code= (v>>2) & 3; |
123 if (!sample_rate_code) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
124 return AVERROR(EIO); |
1642 | 125 ast->codec->sample_rate = 11025 << (sample_rate_code-1); |
1890
04f9a3ae30af
seems safer to set pts timebase to sample rate, fix some mp3
bcoudurier
parents:
1889
diff
changeset
|
126 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
127 len -= 4; |
2308 | 128 } else if (tag == TAG_VIDEOFRAME) { |
1637 | 129 int ch_id = get_le16(pb); |
1639 | 130 len -= 2; |
2309 | 131 for(i=0; i<s->nb_streams; i++) { |
887 | 132 st = s->streams[i]; |
1637 | 133 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) { |
134 frame = get_le16(pb); | |
1639 | 135 av_get_packet(pb, pkt, len-2); |
1889 | 136 pkt->pts = frame; |
1637 | 137 pkt->stream_index = st->index; |
138 return pkt->size; | |
359 | 139 } |
885 | 140 } |
359 | 141 } else if (tag == TAG_STREAMBLOCK) { |
1638 | 142 st = s->streams[swf->audio_stream_index]; |
143 if (st->codec->codec_id == CODEC_ID_MP3) { | |
144 url_fskip(pb, 4); | |
145 av_get_packet(pb, pkt, len-4); | |
1833 | 146 } else { // ADPCM, PCM |
147 av_get_packet(pb, pkt, len); | |
359 | 148 } |
1833 | 149 pkt->stream_index = st->index; |
150 return pkt->size; | |
1640 | 151 } else if (tag == TAG_JPEG2) { |
152 for (i=0; i<s->nb_streams; i++) { | |
153 st = s->streams[i]; | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
154 if (st->id == -2) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
155 break; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
156 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
157 if (i == s->nb_streams) { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
158 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */ |
2913 | 159 if (!vst) |
160 return -1; | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
161 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
162 vst->codec->codec_id = CODEC_ID_MJPEG; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
163 av_set_pts_info(vst, 64, 256, swf->frame_rate); |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
164 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
165 st = vst; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
166 } |
2308 | 167 get_le16(pb); /* BITMAP_ID */ |
168 av_new_packet(pkt, len-2); | |
169 get_buffer(pb, pkt->data, 4); | |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
170 if (AV_RB32(pkt->data) == 0xffd8ffd9 || |
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
171 AV_RB32(pkt->data) == 0xffd9ffd8) { |
2308 | 172 /* old SWF files containing SOI/EOI as data start */ |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
173 /* files created by swink have reversed tag */ |
2308 | 174 pkt->size -= 4; |
175 get_buffer(pb, pkt->data, pkt->size); | |
176 } else { | |
177 get_buffer(pb, pkt->data + 4, pkt->size - 4); | |
178 } | |
179 pkt->stream_index = st->index; | |
180 return pkt->size; | |
0 | 181 } |
1639 | 182 url_fskip(pb, len); |
0 | 183 } |
184 return 0; | |
185 } | |
186 | |
1169 | 187 AVInputFormat swf_demuxer = { |
0 | 188 "swf", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3357
diff
changeset
|
189 NULL_IF_CONFIG_SMALL("Flash format"), |
359 | 190 sizeof(SWFContext), |
0 | 191 swf_probe, |
192 swf_read_header, | |
193 swf_read_packet, | |
194 }; |