Mercurial > libavformat.hg
annotate swfdec.c @ 3532:a741556d452c libavformat
Change mtv_read_packet so it does not break after seeking (displaying a shifted image).
author | reimar |
---|---|
date | Sat, 28 Jun 2008 09:01:16 +0000 |
parents | 7a0230981402 |
children | 7d2f3f1b68d8 |
rev | line source |
---|---|
0 | 1 /* |
3357 | 2 * Flash Compatible Streaming Format demuxer |
0 | 3 * Copyright (c) 2000 Fabrice Bellard. |
359 | 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 |
3302 | 23 #include "swf.h" |
0 | 24 |
25 static int get_swf_tag(ByteIOContext *pb, int *len_ptr) | |
26 { | |
27 int tag, len; | |
885 | 28 |
0 | 29 if (url_feof(pb)) |
30 return -1; | |
31 | |
32 tag = get_le16(pb); | |
33 len = tag & 0x3f; | |
34 tag = tag >> 6; | |
35 if (len == 0x3f) { | |
36 len = get_le32(pb); | |
37 } | |
806 | 38 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len); |
0 | 39 *len_ptr = len; |
40 return tag; | |
41 } | |
42 | |
43 | |
44 static int swf_probe(AVProbeData *p) | |
45 { | |
46 /* check file header */ | |
806 | 47 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' && |
0 | 48 p->buf[2] == 'S') |
49 return AVPROBE_SCORE_MAX; | |
50 else | |
51 return 0; | |
52 } | |
53 | |
54 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
55 { | |
1641 | 56 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
57 ByteIOContext *pb = s->pb; |
2310 | 58 int nbits, len, tag; |
359 | 59 |
806 | 60 tag = get_be32(pb) & 0xffffff00; |
61 | |
2309 | 62 if (tag == MKBETAG('C', 'W', 'S', 0)) { |
887 | 63 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
|
64 return AVERROR(EIO); |
806 | 65 } |
66 if (tag != MKBETAG('F', 'W', 'S', 0)) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
67 return AVERROR(EIO); |
0 | 68 get_le32(pb); |
69 /* skip rectangle size */ | |
70 nbits = get_byte(pb) >> 3; | |
71 len = (4 * nbits - 3 + 7) / 8; | |
72 url_fskip(pb, len); | |
1889 | 73 swf->frame_rate = get_le16(pb); /* 8.8 fixed */ |
0 | 74 get_le16(pb); /* frame count */ |
885 | 75 |
359 | 76 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
|
77 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
|
78 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
|
79 } |
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 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
|
82 { |
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 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
84 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
|
85 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
|
86 int tag, len, i, frame, v; |
0 | 87 |
88 for(;;) { | |
89 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
|
90 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
|
91 return AVERROR(EIO); |
2309 | 92 if (tag == TAG_VIDEOSTREAM && !vst) { |
1637 | 93 int ch_id = get_le16(pb); |
359 | 94 get_le16(pb); |
95 get_le16(pb); | |
96 get_le16(pb); | |
97 get_byte(pb); | |
98 /* Check for FLV1 */ | |
1637 | 99 vst = av_new_stream(s, ch_id); |
2913 | 100 if (!vst) |
101 return -1; | |
1635 | 102 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
103 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
|
104 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
|
105 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
|
106 len -= 10; |
2309 | 107 } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) { |
0 | 108 /* streaming found */ |
1642 | 109 int sample_rate_code; |
0 | 110 get_byte(pb); |
111 v = get_byte(pb); | |
359 | 112 swf->samples_per_frame = get_le16(pb); |
1638 | 113 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */ |
2913 | 114 if (!ast) |
115 return -1; | |
1638 | 116 swf->audio_stream_index = ast->index; |
1636 | 117 ast->codec->channels = 1 + (v&1); |
118 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
1833 | 119 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15); |
2023 | 120 ast->need_parsing = AVSTREAM_PARSE_FULL; |
1642 | 121 sample_rate_code= (v>>2) & 3; |
122 if (!sample_rate_code) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
123 return AVERROR(EIO); |
1642 | 124 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
|
125 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
|
126 len -= 4; |
2308 | 127 } else if (tag == TAG_VIDEOFRAME) { |
1637 | 128 int ch_id = get_le16(pb); |
1639 | 129 len -= 2; |
2309 | 130 for(i=0; i<s->nb_streams; i++) { |
887 | 131 st = s->streams[i]; |
1637 | 132 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) { |
133 frame = get_le16(pb); | |
1639 | 134 av_get_packet(pb, pkt, len-2); |
1889 | 135 pkt->pts = frame; |
1637 | 136 pkt->stream_index = st->index; |
137 return pkt->size; | |
359 | 138 } |
885 | 139 } |
359 | 140 } else if (tag == TAG_STREAMBLOCK) { |
1638 | 141 st = s->streams[swf->audio_stream_index]; |
142 if (st->codec->codec_id == CODEC_ID_MP3) { | |
143 url_fskip(pb, 4); | |
144 av_get_packet(pb, pkt, len-4); | |
1833 | 145 } else { // ADPCM, PCM |
146 av_get_packet(pb, pkt, len); | |
359 | 147 } |
1833 | 148 pkt->stream_index = st->index; |
149 return pkt->size; | |
1640 | 150 } else if (tag == TAG_JPEG2) { |
151 for (i=0; i<s->nb_streams; i++) { | |
152 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
|
153 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
|
154 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
|
155 } |
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 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
|
157 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */ |
2913 | 158 if (!vst) |
159 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
|
160 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
|
161 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
|
162 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
|
163 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
|
164 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
|
165 } |
2308 | 166 get_le16(pb); /* BITMAP_ID */ |
167 av_new_packet(pkt, len-2); | |
168 get_buffer(pb, pkt->data, 4); | |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
169 if (AV_RB32(pkt->data) == 0xffd8ffd9 || |
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
170 AV_RB32(pkt->data) == 0xffd9ffd8) { |
2308 | 171 /* 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
|
172 /* files created by swink have reversed tag */ |
2308 | 173 pkt->size -= 4; |
174 get_buffer(pb, pkt->data, pkt->size); | |
175 } else { | |
176 get_buffer(pb, pkt->data + 4, pkt->size - 4); | |
177 } | |
178 pkt->stream_index = st->index; | |
179 return pkt->size; | |
0 | 180 } |
1639 | 181 url_fskip(pb, len); |
0 | 182 } |
183 return 0; | |
184 } | |
185 | |
1169 | 186 AVInputFormat swf_demuxer = { |
0 | 187 "swf", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3357
diff
changeset
|
188 NULL_IF_CONFIG_SMALL("Flash format"), |
359 | 189 sizeof(SWFContext), |
0 | 190 swf_probe, |
191 swf_read_header, | |
192 swf_read_packet, | |
193 }; |