2 * AVISynth support for ffmpeg system
3 * Copyright (c) 2006 DivX, Inc.
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38 AVISynthStream
*streams
;
43 static int avisynth_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
45 AVISynthContext
*avs
= s
->priv_data
;
50 AVISynthStream
*stream
;
54 res
= AVIFileOpen(&avs
->file
, s
->filename
, OF_READ
|OF_SHARE_DENY_WRITE
, NULL
);
57 av_log(s
, AV_LOG_ERROR
, "AVIFileOpen failed with error %ld", res
);
62 res
= AVIFileInfo(avs
->file
, &info
, sizeof(info
));
65 av_log(s
, AV_LOG_ERROR
, "AVIFileInfo failed with error %ld", res
);
70 avs
->streams
= av_mallocz(info
.dwStreams
* sizeof(AVISynthStream
));
72 for (id
=0; id
<info
.dwStreams
; id
++)
74 stream
= &avs
->streams
[id
];
76 if (AVIFileGetStream(avs
->file
, &stream
->handle
, 0, id
) == S_OK
)
78 if (AVIStreamInfo(stream
->handle
, &stream
->info
, sizeof(stream
->info
)) == S_OK
)
80 if (stream
->info
.fccType
== streamtypeAUDIO
)
83 LONG struct_size
= sizeof(WAVEFORMATEX
);
84 if (AVIStreamReadFormat(stream
->handle
, 0, &wvfmt
, &struct_size
) != S_OK
)
87 st
= av_new_stream(s
, id
);
88 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
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_coded_sample
= wvfmt
.wBitsPerSample
;
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;
99 st
->codec
->codec_tag
= wvfmt
.wFormatTag
;
100 st
->codec
->codec_id
= wav_codec_get_id(wvfmt
.wFormatTag
, st
->codec
->bits_per_coded_sample
);
102 else if (stream
->info
.fccType
== streamtypeVIDEO
)
105 LONG struct_size
= sizeof(BITMAPINFO
);
107 stream
->chunck_size
= stream
->info
.dwSampleSize
;
108 stream
->chunck_samples
= 1;
110 if (AVIStreamReadFormat(stream
->handle
, 0, &imgfmt
, &struct_size
) != S_OK
)
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
;
118 st
->codec
->width
= imgfmt
.bmiHeader
.biWidth
;
119 st
->codec
->height
= imgfmt
.bmiHeader
.biHeight
;
121 st
->codec
->bits_per_coded_sample
= imgfmt
.bmiHeader
.biBitCount
;
122 st
->codec
->bit_rate
= (uint64_t)stream
->info
.dwSampleSize
* (uint64_t)stream
->info
.dwRate
* 8 / (uint64_t)stream
->info
.dwScale
;
123 st
->codec
->codec_tag
= imgfmt
.bmiHeader
.biCompression
;
124 st
->codec
->codec_id
= codec_get_id(codec_bmp_tags
, imgfmt
.bmiHeader
.biCompression
);
126 st
->duration
= stream
->info
.dwLength
;
130 AVIStreamRelease(stream
->handle
);
136 st
->codec
->stream_codec_tag
= stream
->info
.fccHandler
;
138 av_set_pts_info(st
, 64, info
.dwScale
, info
.dwRate
);
139 st
->start_time
= stream
->info
.dwStart
;
147 static int avisynth_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
149 AVISynthContext
*avs
= s
->priv_data
;
151 AVISynthStream
*stream
;
152 int stream_id
= avs
->next_stream
;
155 // handle interleaving manually...
156 stream
= &avs
->streams
[stream_id
];
158 if (stream
->read
>= stream
->info
.dwLength
)
161 if (av_new_packet(pkt
, stream
->chunck_size
))
163 pkt
->stream_index
= stream_id
;
164 pkt
->pts
= avs
->streams
[stream_id
].read
/ avs
->streams
[stream_id
].chunck_samples
;
166 res
= AVIStreamRead(stream
->handle
, stream
->read
, stream
->chunck_samples
, pkt
->data
, stream
->chunck_size
, &read_size
, NULL
);
168 pkt
->pts
= stream
->read
;
169 pkt
->size
= read_size
;
171 stream
->read
+= stream
->chunck_samples
;
173 // prepare for the next stream to read
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
);
178 return (res
== S_OK
) ? pkt
->size
: -1;
181 static int avisynth_read_close(AVFormatContext
*s
)
183 AVISynthContext
*avs
= s
->priv_data
;
186 for (i
=0;i
<avs
->nb_streams
;i
++)
188 AVIStreamRelease(avs
->streams
[i
].handle
);
191 av_free(avs
->streams
);
192 AVIFileRelease(avs
->file
);
197 static int avisynth_read_seek(AVFormatContext
*s
, int stream_index
, int64_t pts
, int flags
)
199 AVISynthContext
*avs
= s
->priv_data
;
202 for (stream_id
= 0; stream_id
< avs
->nb_streams
; stream_id
++)
204 avs
->streams
[stream_id
].read
= pts
* avs
->streams
[stream_id
].chunck_samples
;
210 AVInputFormat avisynth_demuxer
= {
212 NULL_IF_CONFIG_SMALL("AVISynth"),
213 sizeof(AVISynthContext
),
215 avisynth_read_header
,
216 avisynth_read_packet
,