Mercurial > libavformat.hg
annotate avisynth.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 7a0230981402 |
children | 5b915da6dd7e |
rev | line source |
---|---|
1283 | 1 /* |
2 * AVISynth support for ffmpeg system | |
3 * Copyright (c) 2006 DivX, Inc. | |
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); | |
88 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
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; | |
94 st->codec->bits_per_sample = wvfmt.wBitsPerSample; | |
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; |
1283 | 100 st->codec->codec_id = wav_codec_get_id(wvfmt.wFormatTag, st->codec->bits_per_sample); |
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); | |
114 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
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 | |
1346 | 121 st->codec->bits_per_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; |
124 st->codec->codec_id = codec_get_id(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 }; |