Mercurial > libavformat.hg
annotate avisynth.c @ 6491:b7f807b4cd88 libavformat tip
In mov demuxer, check that nb_streams is valid before using it in read_dac3
| author | bcoudurier |
|---|---|
| date | Tue, 28 Sep 2010 00:33:21 +0000 |
| parents | 536e5527c1e0 |
| children |
| rev | line source |
|---|---|
| 1283 | 1 /* |
| 2 * AVISynth support for ffmpeg system | |
|
4253
b43c5c858f25
Restore mistakenly removed period after "DivX, Inc".
diego
parents:
4251
diff
changeset
|
3 * Copyright (c) 2006 DivX, Inc. |
| 1283 | 4 * |
|
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1346
diff
changeset
|
5 * This file is part of FFmpeg. |
|
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1346
diff
changeset
|
6 * |
|
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1346
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
| 1283 | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * 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:
1346
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
| 1283 | 11 * |
|
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1346
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
| 1283 | 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 | |
|
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1346
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
| 1283 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 */ | |
| 21 | |
| 22 #include "avformat.h" | |
| 23 #include "riff.h" | |
| 24 | |
| 25 #include <windows.h> | |
| 26 #include <vfw.h> | |
| 27 | |
| 28 typedef struct { | |
| 29 PAVISTREAM handle; | |
| 30 AVISTREAMINFO info; | |
| 31 DWORD read; | |
| 32 LONG chunck_size; | |
| 33 LONG chunck_samples; | |
| 34 } AVISynthStream; | |
| 35 | |
| 36 typedef struct { | |
| 37 PAVIFILE file; | |
| 38 AVISynthStream *streams; | |
| 39 int nb_streams; | |
| 40 int next_stream; | |
| 41 } AVISynthContext; | |
| 42 | |
| 43 static int avisynth_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
| 44 { | |
| 45 AVISynthContext *avs = s->priv_data; | |
| 46 HRESULT res; | |
| 47 AVIFILEINFO info; | |
| 48 DWORD id; | |
| 49 AVStream *st; | |
| 50 AVISynthStream *stream; | |
| 51 | |
| 52 AVIFileInit(); | |
| 53 | |
| 54 res = AVIFileOpen(&avs->file, s->filename, OF_READ|OF_SHARE_DENY_WRITE, NULL); | |
| 55 if (res != S_OK) | |
| 56 { | |
| 57 av_log(s, AV_LOG_ERROR, "AVIFileOpen failed with error %ld", res); | |
| 58 AVIFileExit(); | |
| 59 return -1; | |
| 60 } | |
| 61 | |
| 62 res = AVIFileInfo(avs->file, &info, sizeof(info)); | |
| 63 if (res != S_OK) | |
| 64 { | |
| 65 av_log(s, AV_LOG_ERROR, "AVIFileInfo failed with error %ld", res); | |
| 66 AVIFileExit(); | |
| 67 return -1; | |
| 68 } | |
| 69 | |
| 70 avs->streams = av_mallocz(info.dwStreams * sizeof(AVISynthStream)); | |
| 71 | |
| 72 for (id=0; id<info.dwStreams; id++) | |
| 73 { | |
| 74 stream = &avs->streams[id]; | |
| 75 stream->read = 0; | |
| 76 if (AVIFileGetStream(avs->file, &stream->handle, 0, id) == S_OK) | |
| 77 { | |
| 78 if (AVIStreamInfo(stream->handle, &stream->info, sizeof(stream->info)) == S_OK) | |
| 79 { | |
| 80 if (stream->info.fccType == streamtypeAUDIO) | |
| 81 { | |
| 82 WAVEFORMATEX wvfmt; | |
| 83 LONG struct_size = sizeof(WAVEFORMATEX); | |
| 84 if (AVIStreamReadFormat(stream->handle, 0, &wvfmt, &struct_size) != S_OK) | |
| 85 continue; | |
| 86 | |
| 87 st = av_new_stream(s, id); | |
|
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5058
diff
changeset
|
88 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
| 1283 | 89 |
| 90 st->codec->block_align = wvfmt.nBlockAlign; | |
| 91 st->codec->channels = wvfmt.nChannels; | |
| 92 st->codec->sample_rate = wvfmt.nSamplesPerSec; | |
| 93 st->codec->bit_rate = wvfmt.nAvgBytesPerSec * 8; | |
|
3917
5b915da6dd7e
set bits_per_coded_sample according to new lavc api
bcoudurier
parents:
3424
diff
changeset
|
94 st->codec->bits_per_coded_sample = wvfmt.wBitsPerSample; |
| 1283 | 95 |
| 96 stream->chunck_samples = wvfmt.nSamplesPerSec * (uint64_t)info.dwScale / (uint64_t)info.dwRate; | |
| 97 stream->chunck_size = stream->chunck_samples * wvfmt.nChannels * wvfmt.wBitsPerSample / 8; | |
| 98 | |
| 1346 | 99 st->codec->codec_tag = wvfmt.wFormatTag; |
|
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4253
diff
changeset
|
100 st->codec->codec_id = ff_wav_codec_get_id(wvfmt.wFormatTag, st->codec->bits_per_coded_sample); |
| 1283 | 101 } |
| 102 else if (stream->info.fccType == streamtypeVIDEO) | |
| 103 { | |
| 104 BITMAPINFO imgfmt; | |
| 105 LONG struct_size = sizeof(BITMAPINFO); | |
| 106 | |
| 107 stream->chunck_size = stream->info.dwSampleSize; | |
| 108 stream->chunck_samples = 1; | |
| 109 | |
| 110 if (AVIStreamReadFormat(stream->handle, 0, &imgfmt, &struct_size) != S_OK) | |
| 111 continue; | |
| 112 | |
| 113 st = av_new_stream(s, id); | |
|
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5058
diff
changeset
|
114 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
| 1283 | 115 st->r_frame_rate.num = stream->info.dwRate; |
| 116 st->r_frame_rate.den = stream->info.dwScale; | |
| 117 | |
| 118 st->codec->width = imgfmt.bmiHeader.biWidth; | |
| 119 st->codec->height = imgfmt.bmiHeader.biHeight; | |
| 120 | |
|
3917
5b915da6dd7e
set bits_per_coded_sample according to new lavc api
bcoudurier
parents:
3424
diff
changeset
|
121 st->codec->bits_per_coded_sample = imgfmt.bmiHeader.biBitCount; |
| 1283 | 122 st->codec->bit_rate = (uint64_t)stream->info.dwSampleSize * (uint64_t)stream->info.dwRate * 8 / (uint64_t)stream->info.dwScale; |
| 1346 | 123 st->codec->codec_tag = imgfmt.bmiHeader.biCompression; |
|
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4253
diff
changeset
|
124 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, imgfmt.bmiHeader.biCompression); |
| 1283 | 125 |
| 126 st->duration = stream->info.dwLength; | |
| 127 } | |
| 128 else | |
| 129 { | |
| 130 AVIStreamRelease(stream->handle); | |
| 131 continue; | |
| 132 } | |
| 133 | |
| 134 avs->nb_streams++; | |
| 135 | |
| 136 st->codec->stream_codec_tag = stream->info.fccHandler; | |
| 137 | |
| 138 av_set_pts_info(st, 64, info.dwScale, info.dwRate); | |
| 139 st->start_time = stream->info.dwStart; | |
| 140 } | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 return 0; | |
| 145 } | |
| 146 | |
| 147 static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 148 { | |
| 149 AVISynthContext *avs = s->priv_data; | |
| 150 HRESULT res; | |
| 151 AVISynthStream *stream; | |
| 152 int stream_id = avs->next_stream; | |
| 153 LONG read_size; | |
| 154 | |
| 155 // handle interleaving manually... | |
| 156 stream = &avs->streams[stream_id]; | |
| 157 | |
| 158 if (stream->read >= stream->info.dwLength) | |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
1358
diff
changeset
|
159 return AVERROR(EIO); |
| 1283 | 160 |
| 161 if (av_new_packet(pkt, stream->chunck_size)) | |
|
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
1358
diff
changeset
|
162 return AVERROR(EIO); |
| 1283 | 163 pkt->stream_index = stream_id; |
| 164 pkt->pts = avs->streams[stream_id].read / avs->streams[stream_id].chunck_samples; | |
| 165 | |
| 166 res = AVIStreamRead(stream->handle, stream->read, stream->chunck_samples, pkt->data, stream->chunck_size, &read_size, NULL); | |
| 167 | |
| 168 pkt->pts = stream->read; | |
| 169 pkt->size = read_size; | |
| 170 | |
| 171 stream->read += stream->chunck_samples; | |
| 172 | |
| 173 // prepare for the next stream to read | |
| 174 do { | |
| 175 avs->next_stream = (avs->next_stream+1) % avs->nb_streams; | |
| 176 } while (avs->next_stream != stream_id && s->streams[avs->next_stream]->discard >= AVDISCARD_ALL); | |
| 177 | |
| 178 return (res == S_OK) ? pkt->size : -1; | |
| 179 } | |
| 180 | |
| 181 static int avisynth_read_close(AVFormatContext *s) | |
| 182 { | |
| 183 AVISynthContext *avs = s->priv_data; | |
| 184 int i; | |
| 185 | |
| 186 for (i=0;i<avs->nb_streams;i++) | |
| 187 { | |
| 188 AVIStreamRelease(avs->streams[i].handle); | |
| 189 } | |
| 190 | |
| 191 av_free(avs->streams); | |
| 192 AVIFileRelease(avs->file); | |
| 193 AVIFileExit(); | |
| 194 return 0; | |
| 195 } | |
| 196 | |
| 197 static int avisynth_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags) | |
| 198 { | |
| 199 AVISynthContext *avs = s->priv_data; | |
| 200 int stream_id; | |
| 201 | |
| 202 for (stream_id = 0; stream_id < avs->nb_streams; stream_id++) | |
| 203 { | |
| 204 avs->streams[stream_id].read = pts * avs->streams[stream_id].chunck_samples; | |
| 205 } | |
| 206 | |
| 207 return 0; | |
| 208 } | |
| 209 | |
| 210 AVInputFormat avisynth_demuxer = { | |
| 211 "avs", | |
|
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
2274
diff
changeset
|
212 NULL_IF_CONFIG_SMALL("AVISynth"), |
| 1283 | 213 sizeof(AVISynthContext), |
| 214 NULL, | |
| 215 avisynth_read_header, | |
| 216 avisynth_read_packet, | |
| 217 avisynth_read_close, | |
| 218 avisynth_read_seek, | |
| 219 NULL, | |
| 220 0, | |
| 221 "avs", | |
| 222 }; |
