Mercurial > libavformat.hg
annotate swfdec.c @ 5130:b26fba4bb776 libavformat
actually define AVSEEK_FLAG_FRAME as described in avformat_seek_file() doc
author | aurel |
---|---|
date | Mon, 10 Aug 2009 20:48:05 +0000 |
parents | 33a244b7ca65 |
children | 536e5527c1e0 |
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(;;) { | |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
90 uint64_t pos = url_ftell(pb); |
0 | 91 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
|
92 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
|
93 return AVERROR(EIO); |
4706 | 94 if (tag == TAG_VIDEOSTREAM) { |
1637 | 95 int ch_id = get_le16(pb); |
4706 | 96 len -= 2; |
97 | |
98 for (i=0; i<s->nb_streams; i++) { | |
99 st = s->streams[i]; | |
100 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) | |
101 goto skip; | |
102 } | |
103 | |
359 | 104 get_le16(pb); |
105 get_le16(pb); | |
106 get_le16(pb); | |
107 get_byte(pb); | |
108 /* Check for FLV1 */ | |
1637 | 109 vst = av_new_stream(s, ch_id); |
2913 | 110 if (!vst) |
111 return -1; | |
1635 | 112 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4715
diff
changeset
|
113 vst->codec->codec_id = ff_codec_get_id(swf_codec_tags, get_byte(pb)); |
4715 | 114 av_set_pts_info(vst, 16, 256, swf->frame_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
|
115 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
4706 | 116 len -= 8; |
117 } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) { | |
0 | 118 /* streaming found */ |
1642 | 119 int sample_rate_code; |
4706 | 120 |
121 for (i=0; i<s->nb_streams; i++) { | |
122 st = s->streams[i]; | |
123 if (st->codec->codec_type == CODEC_TYPE_AUDIO && st->id == -1) | |
124 goto skip; | |
125 } | |
126 | |
0 | 127 get_byte(pb); |
128 v = get_byte(pb); | |
359 | 129 swf->samples_per_frame = get_le16(pb); |
1638 | 130 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */ |
2913 | 131 if (!ast) |
132 return -1; | |
1636 | 133 ast->codec->channels = 1 + (v&1); |
134 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4715
diff
changeset
|
135 ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15); |
2023 | 136 ast->need_parsing = AVSTREAM_PARSE_FULL; |
1642 | 137 sample_rate_code= (v>>2) & 3; |
138 if (!sample_rate_code) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
139 return AVERROR(EIO); |
1642 | 140 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
|
141 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
|
142 len -= 4; |
2308 | 143 } else if (tag == TAG_VIDEOFRAME) { |
1637 | 144 int ch_id = get_le16(pb); |
1639 | 145 len -= 2; |
2309 | 146 for(i=0; i<s->nb_streams; i++) { |
887 | 147 st = s->streams[i]; |
1637 | 148 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) { |
149 frame = get_le16(pb); | |
1639 | 150 av_get_packet(pb, pkt, len-2); |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
151 pkt->pos = pos; |
1889 | 152 pkt->pts = frame; |
1637 | 153 pkt->stream_index = st->index; |
154 return pkt->size; | |
359 | 155 } |
885 | 156 } |
359 | 157 } else if (tag == TAG_STREAMBLOCK) { |
4706 | 158 for (i = 0; i < s->nb_streams; i++) { |
159 st = s->streams[i]; | |
160 if (st->codec->codec_type == CODEC_TYPE_AUDIO && st->id == -1) { | |
1638 | 161 if (st->codec->codec_id == CODEC_ID_MP3) { |
162 url_fskip(pb, 4); | |
163 av_get_packet(pb, pkt, len-4); | |
1833 | 164 } else { // ADPCM, PCM |
165 av_get_packet(pb, pkt, len); | |
359 | 166 } |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
167 pkt->pos = pos; |
1833 | 168 pkt->stream_index = st->index; |
169 return pkt->size; | |
4706 | 170 } |
171 } | |
1640 | 172 } else if (tag == TAG_JPEG2) { |
173 for (i=0; i<s->nb_streams; i++) { | |
174 st = s->streams[i]; | |
4706 | 175 if (st->codec->codec_id == CODEC_ID_MJPEG && st->id == -2) |
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
|
176 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
|
177 } |
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
|
178 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
|
179 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */ |
2913 | 180 if (!vst) |
181 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
|
182 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
|
183 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
|
184 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
|
185 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
|
186 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
|
187 } |
2308 | 188 get_le16(pb); /* BITMAP_ID */ |
189 av_new_packet(pkt, len-2); | |
190 get_buffer(pb, pkt->data, 4); | |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
191 if (AV_RB32(pkt->data) == 0xffd8ffd9 || |
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
192 AV_RB32(pkt->data) == 0xffd9ffd8) { |
2308 | 193 /* 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
|
194 /* files created by swink have reversed tag */ |
2308 | 195 pkt->size -= 4; |
196 get_buffer(pb, pkt->data, pkt->size); | |
197 } else { | |
198 get_buffer(pb, pkt->data + 4, pkt->size - 4); | |
199 } | |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
200 pkt->pos = pos; |
2308 | 201 pkt->stream_index = st->index; |
202 return pkt->size; | |
0 | 203 } |
4706 | 204 skip: |
1639 | 205 url_fskip(pb, len); |
0 | 206 } |
207 return 0; | |
208 } | |
209 | |
1169 | 210 AVInputFormat swf_demuxer = { |
0 | 211 "swf", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3357
diff
changeset
|
212 NULL_IF_CONFIG_SMALL("Flash format"), |
359 | 213 sizeof(SWFContext), |
0 | 214 swf_probe, |
215 swf_read_header, | |
216 swf_read_packet, | |
217 }; |