3 * Copyright (c) 2005 Gianluigi Tiesi <sherpya@netfarm.it>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
30 #include "stream/stream.h"
33 #include "libvo/fastmemcpy.h"
35 #include "loader/wine/windef.h"
38 #include "loader/ldt_keeper.h"
41 #include "demux_avs.h"
43 #define MAX_AVS_SIZE 16 * 1024 /* 16k should be enough */
45 HMODULE WINAPI
LoadLibraryA(LPCSTR
);
46 FARPROC WINAPI
GetProcAddress(HMODULE
,LPCSTR
);
47 int WINAPI
FreeLibrary(HMODULE
);
49 typedef WINAPI AVS_ScriptEnvironment
* (*imp_avs_create_script_environment
)(int version
);
50 typedef WINAPI
AVS_Value (*imp_avs_invoke
)(AVS_ScriptEnvironment
*, const char * name
, AVS_Value args
, const char** arg_names
);
51 typedef WINAPI
const AVS_VideoInfo
*(*imp_avs_get_video_info
)(AVS_Clip
*);
52 typedef WINAPI AVS_Clip
* (*imp_avs_take_clip
)(AVS_Value
, AVS_ScriptEnvironment
*);
53 typedef WINAPI
void (*imp_avs_release_clip
)(AVS_Clip
*);
54 typedef WINAPI AVS_VideoFrame
* (*imp_avs_get_frame
)(AVS_Clip
*, int n
);
55 typedef WINAPI
void (*imp_avs_release_video_frame
)(AVS_VideoFrame
*);
56 typedef WINAPI
int (*imp_avs_get_audio
)(AVS_Clip
*, void * buf
, uint64_t start
, uint64_t count
);
58 #define Q(string) # string
59 #define IMPORT_FUNC(x) \
60 AVS->x = ( imp_##x ) GetProcAddress(AVS->dll, Q(x)); \
61 if (!AVS->x) { mp_msg(MSGT_DEMUX,MSGL_V,"AVS: failed to load "Q(x)"()\n"); return 0; }
65 AVS_ScriptEnvironment
*avs_env
;
68 const AVS_VideoInfo
*video_info
;
77 imp_avs_create_script_environment avs_create_script_environment
;
78 imp_avs_invoke avs_invoke
;
79 imp_avs_get_video_info avs_get_video_info
;
80 imp_avs_take_clip avs_take_clip
;
81 imp_avs_release_clip avs_release_clip
;
82 imp_avs_get_frame avs_get_frame
;
83 imp_avs_release_video_frame avs_release_video_frame
;
84 imp_avs_get_audio avs_get_audio
;
87 AVS_T
*initAVS(const char *filename
)
89 AVS_T
*AVS
= malloc (sizeof(AVS_T
));
90 AVS_Value arg0
= avs_new_value_string(filename
);
91 AVS_Value args
= avs_new_value_array(&arg0
, 1);
93 memset(AVS
, 0, sizeof(AVS_T
));
96 AVS
->ldt_fs
= Setup_LDT_Keeper();
99 AVS
->dll
= LoadLibraryA("avisynth.dll");
102 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: failed to load avisynth.dll\n");
106 /* Dynamic import of needed stuff from avisynth.dll */
107 IMPORT_FUNC(avs_create_script_environment
);
108 IMPORT_FUNC(avs_invoke
);
109 IMPORT_FUNC(avs_get_video_info
);
110 IMPORT_FUNC(avs_take_clip
);
111 IMPORT_FUNC(avs_release_clip
);
112 IMPORT_FUNC(avs_get_frame
);
113 IMPORT_FUNC(avs_release_video_frame
);
114 IMPORT_FUNC(avs_get_audio
);
116 AVS
->avs_env
= AVS
->avs_create_script_environment(AVISYNTH_INTERFACE_VERSION
);
119 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_create_script_environment failed\n");
124 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "Import", args
, 0);
126 if (avs_is_error(AVS
->handler
))
128 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth error: %s\n", avs_as_string(AVS
->handler
));
132 if (!avs_is_clip(AVS
->handler
))
134 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth doesn't return a clip\n");
141 if (AVS
->dll
) FreeLibrary(AVS
->dll
);
143 Restore_LDT_Keeper(AVS
->ldt_fs
);
149 /* Implement RGB MODES ?? */
151 static __inline
int get_mmioFOURCC(const AVS_VideoInfo
*v
)
153 if (avs_is_rgb(v
)) return mmioFOURCC(8, 'R', 'G', 'B');
154 if (avs_is_rgb24(v
)) return mmioFOURCC(24, 'R', 'G', 'B');
155 if (avs_is_rgb32(v
)) return mmioFOURCC(32, 'R', 'G', 'B');
156 if (avs_is_yv12(v
)) return mmioFOURCC('Y', 'V', '1', '2');
157 if (avs_is_yuy(v
)) return mmioFOURCC('Y', 'U', 'Y', ' ');
158 if (avs_is_yuy2(v
)) return mmioFOURCC('Y', 'U', 'Y', '2');
163 static int demux_avs_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
165 AVS_VideoFrame
*curr_frame
;
166 demux_packet_t
*dp
= NULL
;
167 AVS_T
*AVS
= demuxer
->priv
;
169 if (ds
== demuxer
->video
)
171 sh_video_t
*sh_video
= demuxer
->video
->sh
;
174 if (AVS
->video_info
->num_frames
<= AVS
->frameno
) return 0; // EOF
176 curr_frame
= AVS
->avs_get_frame(AVS
->clip
, AVS
->frameno
);
179 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: error getting frame -- EOF??\n");
182 w
= curr_frame
->row_size
;
183 h
= curr_frame
->height
;
185 dp
= new_demux_packet(w
* h
+ 2 * (w
/ 2) * (h
/ 2));
187 dp
->pts
=AVS
->frameno
/ sh_video
->fps
;
190 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offset
,
191 w
, h
, w
, curr_frame
->pitch
);
194 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetV
,
195 w
, h
, w
, curr_frame
->pitchUV
);
197 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetU
,
198 w
, h
, w
, curr_frame
->pitchUV
);
199 ds_add_packet(demuxer
->video
, dp
);
202 AVS
->avs_release_video_frame(curr_frame
);
206 if (ds
== demuxer
->audio
)
208 sh_audio_t
*sh_audio
= ds
->sh
;
209 int samples
= sh_audio
->samplerate
;
211 samples
= FFMIN(samples
, AVS
->video_info
->num_audio_samples
- AVS
->sampleno
);
212 if (!samples
) return 0;
213 l
= samples
* sh_audio
->channels
* sh_audio
->samplesize
;
215 mp_msg(MSGT_DEMUX
, MSGL_FATAL
, "AVS: audio packet too big\n");
218 dp
= new_demux_packet(l
);
219 dp
->pts
= AVS
->sampleno
/ sh_audio
->samplerate
;
221 if (AVS
->avs_get_audio(AVS
->clip
, dp
->buffer
, AVS
->sampleno
, samples
))
223 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_audio() failed\n");
226 ds_add_packet(demuxer
->audio
, dp
);
228 AVS
->sampleno
+= samples
;
234 static demuxer_t
* demux_open_avs(demuxer_t
* demuxer
)
237 AVS_T
*AVS
= demuxer
->priv
;
238 int audio_samplesize
= 0;
242 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: demux_open_avs()\n");
243 demuxer
->seekable
= 1;
245 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
248 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
252 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
253 if (!AVS
->video_info
)
255 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
259 if (!avs_is_yv12(AVS
->video_info
))
261 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "ConvertToYV12", avs_new_value_array(&AVS
->handler
, 1), 0);
262 if (avs_is_error(AVS
->handler
))
264 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Cannot convert input video to YV12: %s\n", avs_as_string(AVS
->handler
));
268 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
272 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
276 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
277 if (!AVS
->video_info
)
279 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
284 // TODO check field-based ??
287 if (avs_has_video(AVS
->video_info
))
289 sh_video_t
*sh_video
= new_sh_video(demuxer
, 0);
292 if (demuxer
->video
->id
== -1) demuxer
->video
->id
= 0;
293 if (demuxer
->video
->id
== 0)
294 demuxer
->video
->sh
= sh_video
;
295 sh_video
->ds
= demuxer
->video
;
297 sh_video
->disp_w
= AVS
->video_info
->width
;
298 sh_video
->disp_h
= AVS
->video_info
->height
;
300 //sh_video->format = get_mmioFOURCC(AVS->video_info);
301 sh_video
->format
= mmioFOURCC('Y', 'V', '1', '2');
302 sh_video
->fps
= (double) AVS
->video_info
->fps_numerator
/ (double) AVS
->video_info
->fps_denominator
;
303 sh_video
->frametime
= 1.0 / sh_video
->fps
;
305 sh_video
->bih
= malloc(sizeof(BITMAPINFOHEADER
) + (256 * 4));
306 sh_video
->bih
->biCompression
= sh_video
->format
;
307 sh_video
->bih
->biBitCount
= avs_bits_per_pixel(AVS
->video_info
);
308 //sh_video->bih->biPlanes = 2;
310 sh_video
->bih
->biWidth
= AVS
->video_info
->width
;
311 sh_video
->bih
->biHeight
= AVS
->video_info
->height
;
312 sh_video
->num_frames
= 0;
313 sh_video
->num_frames_decoded
= 0;
317 if (avs_has_audio(AVS
->video_info
))
318 switch (AVS
->video_info
->sample_type
) {
319 case AVS_SAMPLE_INT8
: audio_samplesize
= 1; break;
320 case AVS_SAMPLE_INT16
: audio_samplesize
= 2; break;
321 case AVS_SAMPLE_INT24
: audio_samplesize
= 3; break;
322 case AVS_SAMPLE_INT32
:
323 case AVS_SAMPLE_FLOAT
: audio_samplesize
= 4; break;
325 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "AVS: unknown audio type, disabling\n");
327 if (audio_samplesize
)
329 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
331 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Clip has audio -> Channels = %d - Freq = %d\n", AVS
->video_info
->nchannels
, AVS
->video_info
->audio_samples_per_second
);
333 if (demuxer
->audio
->id
== -1) demuxer
->audio
->id
= 0;
334 if (demuxer
->audio
->id
== 0)
335 demuxer
->audio
->sh
= sh_audio
;
336 sh_audio
->ds
= demuxer
->audio
;
338 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
339 sh_audio
->wf
->wFormatTag
= sh_audio
->format
=
340 (AVS
->video_info
->sample_type
== AVS_SAMPLE_FLOAT
) ? 0x3 : 0x1;
341 sh_audio
->wf
->nChannels
= sh_audio
->channels
= AVS
->video_info
->nchannels
;
342 sh_audio
->wf
->nSamplesPerSec
= sh_audio
->samplerate
= AVS
->video_info
->audio_samples_per_second
;
343 sh_audio
->samplesize
= audio_samplesize
;
344 sh_audio
->wf
->nAvgBytesPerSec
= sh_audio
->channels
* sh_audio
->samplesize
* sh_audio
->samplerate
;
345 sh_audio
->wf
->nBlockAlign
= sh_audio
->channels
* sh_audio
->samplesize
;
346 sh_audio
->wf
->wBitsPerSample
= sh_audio
->samplesize
* 8;
347 sh_audio
->wf
->cbSize
= 0;
348 sh_audio
->i_bps
= sh_audio
->wf
->nAvgBytesPerSec
;
358 static int demux_avs_control(demuxer_t
*demuxer
, int cmd
, void *arg
)
360 sh_video_t
*sh_video
=demuxer
->video
->sh
;
361 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
362 AVS_T
*AVS
= demuxer
->priv
;
366 case DEMUXER_CTRL_GET_TIME_LENGTH
:
368 double res
= sh_video
? (double)AVS
->video_info
->num_frames
/ sh_video
->fps
: 0;
370 res
= FFMAX(res
, (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
);
371 *((double *)arg
) = res
;
372 return DEMUXER_CTRL_OK
;
374 case DEMUXER_CTRL_GET_PERCENT_POS
:
377 *((int *)arg
) = AVS
->frameno
* 100 / AVS
->video_info
->num_frames
;
379 *((int *)arg
) = AVS
->sampleno
* 100 / AVS
->video_info
->num_audio_samples
;
380 return DEMUXER_CTRL_OK
;
383 return DEMUXER_CTRL_NOTIMPL
;
387 static void demux_close_avs(demuxer_t
* demuxer
)
389 AVS_T
*AVS
= demuxer
->priv
;
396 AVS
->avs_release_clip(AVS
->clip
);
397 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Unloading avisynth.dll\n");
398 FreeLibrary(AVS
->dll
);
401 Restore_LDT_Keeper(AVS
->ldt_fs
);
407 static void demux_seek_avs(demuxer_t
*demuxer
, float rel_seek_secs
, float audio_delay
, int flags
)
409 sh_video_t
*sh_video
=demuxer
->video
->sh
;
410 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
411 AVS_T
*AVS
= demuxer
->priv
;
412 double video_pos
= sh_video
?
413 (double)AVS
->frameno
/ sh_video
->fps
:
414 (double)AVS
->sampleno
/ sh_audio
->samplerate
;
415 double duration
= sh_video
?
416 (double)AVS
->video_info
->num_frames
/ sh_video
->fps
:
417 (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
;
419 //mp_msg(MSGT_DEMUX, MSGL_V, "AVS: seek rel_seek_secs = %f - flags = %x\n", rel_seek_secs, flags);
421 if (flags
&SEEK_ABSOLUTE
) video_pos
=0;
422 if (flags
&SEEK_FACTOR
) rel_seek_secs
*= duration
;
424 video_pos
+= rel_seek_secs
;
425 if (video_pos
< 0) video_pos
= 0;
428 AVS
->frameno
= FFMIN(video_pos
* sh_video
->fps
,
429 AVS
->video_info
->num_frames
);
430 sh_video
->num_frames_decoded
= AVS
->frameno
;
431 sh_video
->num_frames
= AVS
->frameno
;
433 video_pos
+= audio_delay
;
434 if (video_pos
< 0) video_pos
= 0;
436 AVS
->sampleno
= FFMIN(video_pos
* sh_audio
->samplerate
,
437 AVS
->video_info
->num_audio_samples
);
440 static int avs_check_file(demuxer_t
*demuxer
)
442 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_check_file - attempting to open file %s\n", demuxer
->filename
);
444 if (!demuxer
->filename
) return 0;
446 /* Avoid crazy memory eating when passing an mpg stream */
447 if (demuxer
->movi_end
> MAX_AVS_SIZE
)
449 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: File is too big, aborting...\n");
453 demuxer
->priv
= initAVS(demuxer
->filename
);
457 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init Ok\n");
458 return DEMUXER_TYPE_AVS
;
460 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init failed\n");
465 const demuxer_desc_t demuxer_desc_avs
= {
470 "Requires binary dll",
472 0, // unsafe autodetect
474 demux_avs_fill_buffer
,