ffmpeg / libavformat / avisynth.c @ 2912e87a
History | View | Annotate | Download (6.69 KB)
1 | 9dc5607b | Guillaume Poirier | /*
|
---|---|---|---|
2 | * AVISynth support for ffmpeg system
|
||
3 | 6f2009bf | Diego Biurrun | * Copyright (c) 2006 DivX, Inc.
|
4 | 9dc5607b | Guillaume Poirier | *
|
5 | 2912e87a | Mans Rullgard | * This file is part of Libav.
|
6 | b78e7197 | Diego Biurrun | *
|
7 | 2912e87a | Mans Rullgard | * Libav is free software; you can redistribute it and/or
|
8 | 9dc5607b | Guillaume Poirier | * modify it under the terms of the GNU Lesser General Public
|
9 | * License as published by the Free Software Foundation; either
|
||
10 | b78e7197 | Diego Biurrun | * version 2.1 of the License, or (at your option) any later version.
|
11 | 9dc5607b | Guillaume Poirier | *
|
12 | 2912e87a | Mans Rullgard | * Libav is distributed in the hope that it will be useful,
|
13 | 9dc5607b | Guillaume Poirier | * 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
|
||
18 | 2912e87a | Mans Rullgard | * License along with Libav; if not, write to the Free Software
|
19 | 9dc5607b | Guillaume Poirier | * 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 | 72415b2a | Stefano Sabatini | st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
89 | 9dc5607b | Guillaume Poirier | |
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 | 00adc1e5 | Baptiste Coudurier | st->codec->bits_per_coded_sample = wvfmt.wBitsPerSample; |
95 | 9dc5607b | Guillaume Poirier | |
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 | |||
99 | e0769997 | Steve L'Homme | st->codec->codec_tag = wvfmt.wFormatTag; |
100 | 1a40491e | Daniel Verkamp | st->codec->codec_id = ff_wav_codec_get_id(wvfmt.wFormatTag, st->codec->bits_per_coded_sample); |
101 | 9dc5607b | Guillaume Poirier | } |
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 | 72415b2a | Stefano Sabatini | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
115 | 9dc5607b | Guillaume Poirier | 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 | |||
121 | 00adc1e5 | Baptiste Coudurier | st->codec->bits_per_coded_sample = imgfmt.bmiHeader.biBitCount; |
122 | 9dc5607b | Guillaume Poirier | st->codec->bit_rate = (uint64_t)stream->info.dwSampleSize * (uint64_t)stream->info.dwRate * 8 / (uint64_t)stream->info.dwScale;
|
123 | e0769997 | Steve L'Homme | st->codec->codec_tag = imgfmt.bmiHeader.biCompression; |
124 | 1a40491e | Daniel Verkamp | st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, imgfmt.bmiHeader.biCompression); |
125 | 9dc5607b | Guillaume Poirier | |
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)
|
||
159 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
160 | 9dc5607b | Guillaume Poirier | |
161 | if (av_new_packet(pkt, stream->chunck_size))
|
||
162 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
163 | 9dc5607b | Guillaume Poirier | 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 | c6610a21 | Diego Elio Pettenò | AVInputFormat ff_avisynth_demuxer = { |
211 | 9dc5607b | Guillaume Poirier | "avs",
|
212 | bde15e74 | Stefano Sabatini | NULL_IF_CONFIG_SMALL("AVISynth"),
|
213 | 9dc5607b | Guillaume Poirier | 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 | }; |