3 * Copyright (c) 2005 Gianluigi Tiesi <sherpya@netfarm.it>
5 * This file is part of MPlayer.
7 * MPlayer 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 * MPlayer 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 License
18 * along with MPlayer; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "stream/stream.h"
34 #include "libvo/fastmemcpy.h"
36 #include "loader/wine/windef.h"
39 #include "loader/ldt_keeper.h"
42 #include "demux_avs.h"
44 #define MAX_AVS_SIZE 16 * 1024 /* 16k should be enough */
46 HMODULE WINAPI
LoadLibraryA(LPCSTR
);
47 FARPROC WINAPI
GetProcAddress(HMODULE
,LPCSTR
);
48 int WINAPI
FreeLibrary(HMODULE
);
50 typedef WINAPI AVS_ScriptEnvironment
* (*imp_avs_create_script_environment
)(int version
);
51 typedef WINAPI
AVS_Value (*imp_avs_invoke
)(AVS_ScriptEnvironment
*, const char * name
, AVS_Value args
, const char** arg_names
);
52 typedef WINAPI
const AVS_VideoInfo
*(*imp_avs_get_video_info
)(AVS_Clip
*);
53 typedef WINAPI AVS_Clip
* (*imp_avs_take_clip
)(AVS_Value
, AVS_ScriptEnvironment
*);
54 typedef WINAPI
void (*imp_avs_release_clip
)(AVS_Clip
*);
55 typedef WINAPI AVS_VideoFrame
* (*imp_avs_get_frame
)(AVS_Clip
*, int n
);
56 typedef WINAPI
void (*imp_avs_release_video_frame
)(AVS_VideoFrame
*);
57 typedef WINAPI
int (*imp_avs_get_audio
)(AVS_Clip
*, void * buf
, uint64_t start
, uint64_t count
);
59 #define Q(string) # string
60 #define IMPORT_FUNC(x) \
61 AVS->x = ( imp_##x ) GetProcAddress(AVS->dll, Q(x)); \
62 if (!AVS->x) { mp_msg(MSGT_DEMUX,MSGL_V,"AVS: failed to load "Q(x)"()\n"); return 0; }
66 AVS_ScriptEnvironment
*avs_env
;
69 const AVS_VideoInfo
*video_info
;
78 imp_avs_create_script_environment avs_create_script_environment
;
79 imp_avs_invoke avs_invoke
;
80 imp_avs_get_video_info avs_get_video_info
;
81 imp_avs_take_clip avs_take_clip
;
82 imp_avs_release_clip avs_release_clip
;
83 imp_avs_get_frame avs_get_frame
;
84 imp_avs_release_video_frame avs_release_video_frame
;
85 imp_avs_get_audio avs_get_audio
;
88 AVS_T
*initAVS(const char *filename
)
90 AVS_T
*AVS
= malloc (sizeof(AVS_T
));
91 AVS_Value arg0
= avs_new_value_string(filename
);
92 AVS_Value args
= avs_new_value_array(&arg0
, 1);
94 memset(AVS
, 0, sizeof(AVS_T
));
97 AVS
->ldt_fs
= Setup_LDT_Keeper();
100 AVS
->dll
= LoadLibraryA("avisynth.dll");
103 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: failed to load avisynth.dll\n");
107 /* Dynamic import of needed stuff from avisynth.dll */
108 IMPORT_FUNC(avs_create_script_environment
);
109 IMPORT_FUNC(avs_invoke
);
110 IMPORT_FUNC(avs_get_video_info
);
111 IMPORT_FUNC(avs_take_clip
);
112 IMPORT_FUNC(avs_release_clip
);
113 IMPORT_FUNC(avs_get_frame
);
114 IMPORT_FUNC(avs_release_video_frame
);
115 IMPORT_FUNC(avs_get_audio
);
117 AVS
->avs_env
= AVS
->avs_create_script_environment(AVISYNTH_INTERFACE_VERSION
);
120 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_create_script_environment failed\n");
125 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "Import", args
, 0);
127 if (avs_is_error(AVS
->handler
))
129 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth error: %s\n", avs_as_string(AVS
->handler
));
133 if (!avs_is_clip(AVS
->handler
))
135 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth doesn't return a clip\n");
142 if (AVS
->dll
) FreeLibrary(AVS
->dll
);
144 Restore_LDT_Keeper(AVS
->ldt_fs
);
150 /* Implement RGB MODES ?? */
152 static __inline
int get_mmioFOURCC(const AVS_VideoInfo
*v
)
154 if (avs_is_rgb(v
)) return mmioFOURCC(8, 'R', 'G', 'B');
155 if (avs_is_rgb24(v
)) return mmioFOURCC(24, 'R', 'G', 'B');
156 if (avs_is_rgb32(v
)) return mmioFOURCC(32, 'R', 'G', 'B');
157 if (avs_is_yv12(v
)) return mmioFOURCC('Y', 'V', '1', '2');
158 if (avs_is_yuy(v
)) return mmioFOURCC('Y', 'U', 'Y', ' ');
159 if (avs_is_yuy2(v
)) return mmioFOURCC('Y', 'U', 'Y', '2');
164 static int demux_avs_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
166 AVS_VideoFrame
*curr_frame
;
167 demux_packet_t
*dp
= NULL
;
168 AVS_T
*AVS
= demuxer
->priv
;
170 if (ds
== demuxer
->video
)
172 sh_video_t
*sh_video
= demuxer
->video
->sh
;
175 if (AVS
->video_info
->num_frames
<= AVS
->frameno
) return 0; // EOF
177 curr_frame
= AVS
->avs_get_frame(AVS
->clip
, AVS
->frameno
);
180 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: error getting frame -- EOF??\n");
183 w
= curr_frame
->row_size
;
184 h
= curr_frame
->height
;
186 dp
= new_demux_packet(w
* h
+ 2 * (w
/ 2) * (h
/ 2));
188 dp
->pts
=AVS
->frameno
/ sh_video
->fps
;
191 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offset
,
192 w
, h
, w
, curr_frame
->pitch
);
195 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetV
,
196 w
, h
, w
, curr_frame
->pitchUV
);
198 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetU
,
199 w
, h
, w
, curr_frame
->pitchUV
);
200 ds_add_packet(demuxer
->video
, dp
);
203 AVS
->avs_release_video_frame(curr_frame
);
207 if (ds
== demuxer
->audio
)
209 sh_audio_t
*sh_audio
= ds
->sh
;
210 int samples
= sh_audio
->samplerate
;
212 samples
= FFMIN(samples
, AVS
->video_info
->num_audio_samples
- AVS
->sampleno
);
213 if (!samples
) return 0;
214 l
= samples
* sh_audio
->channels
* sh_audio
->samplesize
;
216 mp_msg(MSGT_DEMUX
, MSGL_FATAL
, "AVS: audio packet too big\n");
219 dp
= new_demux_packet(l
);
220 dp
->pts
= AVS
->sampleno
/ sh_audio
->samplerate
;
222 if (AVS
->avs_get_audio(AVS
->clip
, dp
->buffer
, AVS
->sampleno
, samples
))
224 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_audio() failed\n");
227 ds_add_packet(demuxer
->audio
, dp
);
229 AVS
->sampleno
+= samples
;
235 static demuxer_t
* demux_open_avs(demuxer_t
* demuxer
)
238 AVS_T
*AVS
= demuxer
->priv
;
239 int audio_samplesize
= 0;
243 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: demux_open_avs()\n");
244 demuxer
->seekable
= 1;
246 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
249 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
253 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
254 if (!AVS
->video_info
)
256 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
260 if (!avs_is_yv12(AVS
->video_info
))
262 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "ConvertToYV12", avs_new_value_array(&AVS
->handler
, 1), 0);
263 if (avs_is_error(AVS
->handler
))
265 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Cannot convert input video to YV12: %s\n", avs_as_string(AVS
->handler
));
269 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
273 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
277 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
278 if (!AVS
->video_info
)
280 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
285 // TODO check field-based ??
288 if (avs_has_video(AVS
->video_info
))
290 sh_video_t
*sh_video
= new_sh_video(demuxer
, 0);
293 if (demuxer
->video
->id
== -1) demuxer
->video
->id
= 0;
294 if (demuxer
->video
->id
== 0)
295 demuxer
->video
->sh
= sh_video
;
296 sh_video
->ds
= demuxer
->video
;
298 sh_video
->disp_w
= AVS
->video_info
->width
;
299 sh_video
->disp_h
= AVS
->video_info
->height
;
301 //sh_video->format = get_mmioFOURCC(AVS->video_info);
302 sh_video
->format
= mmioFOURCC('Y', 'V', '1', '2');
303 sh_video
->fps
= (double) AVS
->video_info
->fps_numerator
/ (double) AVS
->video_info
->fps_denominator
;
304 sh_video
->frametime
= 1.0 / sh_video
->fps
;
306 sh_video
->bih
= malloc(sizeof(BITMAPINFOHEADER
) + (256 * 4));
307 sh_video
->bih
->biCompression
= sh_video
->format
;
308 sh_video
->bih
->biBitCount
= avs_bits_per_pixel(AVS
->video_info
);
309 //sh_video->bih->biPlanes = 2;
311 sh_video
->bih
->biWidth
= AVS
->video_info
->width
;
312 sh_video
->bih
->biHeight
= AVS
->video_info
->height
;
313 sh_video
->num_frames
= 0;
314 sh_video
->num_frames_decoded
= 0;
318 if (avs_has_audio(AVS
->video_info
))
319 switch (AVS
->video_info
->sample_type
) {
320 case AVS_SAMPLE_INT8
: audio_samplesize
= 1; break;
321 case AVS_SAMPLE_INT16
: audio_samplesize
= 2; break;
322 case AVS_SAMPLE_INT24
: audio_samplesize
= 3; break;
323 case AVS_SAMPLE_INT32
:
324 case AVS_SAMPLE_FLOAT
: audio_samplesize
= 4; break;
326 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "AVS: unknown audio type, disabling\n");
328 if (audio_samplesize
)
330 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
332 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
);
334 if (demuxer
->audio
->id
== -1) demuxer
->audio
->id
= 0;
335 if (demuxer
->audio
->id
== 0)
336 demuxer
->audio
->sh
= sh_audio
;
337 sh_audio
->ds
= demuxer
->audio
;
339 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
340 sh_audio
->wf
->wFormatTag
= sh_audio
->format
=
341 (AVS
->video_info
->sample_type
== AVS_SAMPLE_FLOAT
) ? 0x3 : 0x1;
342 sh_audio
->wf
->nChannels
= sh_audio
->channels
= AVS
->video_info
->nchannels
;
343 sh_audio
->wf
->nSamplesPerSec
= sh_audio
->samplerate
= AVS
->video_info
->audio_samples_per_second
;
344 sh_audio
->samplesize
= audio_samplesize
;
345 sh_audio
->wf
->nAvgBytesPerSec
= sh_audio
->channels
* sh_audio
->samplesize
* sh_audio
->samplerate
;
346 sh_audio
->wf
->nBlockAlign
= sh_audio
->channels
* sh_audio
->samplesize
;
347 sh_audio
->wf
->wBitsPerSample
= sh_audio
->samplesize
* 8;
348 sh_audio
->wf
->cbSize
= 0;
349 sh_audio
->i_bps
= sh_audio
->wf
->nAvgBytesPerSec
;
359 static int demux_avs_control(demuxer_t
*demuxer
, int cmd
, void *arg
)
361 sh_video_t
*sh_video
=demuxer
->video
->sh
;
362 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
363 AVS_T
*AVS
= demuxer
->priv
;
367 case DEMUXER_CTRL_GET_TIME_LENGTH
:
369 double res
= sh_video
? (double)AVS
->video_info
->num_frames
/ sh_video
->fps
: 0;
371 res
= FFMAX(res
, (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
);
372 *((double *)arg
) = res
;
373 return DEMUXER_CTRL_OK
;
375 case DEMUXER_CTRL_GET_PERCENT_POS
:
378 *((int *)arg
) = AVS
->frameno
* 100 / AVS
->video_info
->num_frames
;
380 *((int *)arg
) = AVS
->sampleno
* 100 / AVS
->video_info
->num_audio_samples
;
381 return DEMUXER_CTRL_OK
;
384 return DEMUXER_CTRL_NOTIMPL
;
388 static void demux_close_avs(demuxer_t
* demuxer
)
390 AVS_T
*AVS
= demuxer
->priv
;
397 AVS
->avs_release_clip(AVS
->clip
);
398 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Unloading avisynth.dll\n");
399 FreeLibrary(AVS
->dll
);
402 Restore_LDT_Keeper(AVS
->ldt_fs
);
408 static void demux_seek_avs(demuxer_t
*demuxer
, float rel_seek_secs
, float audio_delay
, int flags
)
410 sh_video_t
*sh_video
=demuxer
->video
->sh
;
411 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
412 AVS_T
*AVS
= demuxer
->priv
;
413 double video_pos
= sh_video
?
414 (double)AVS
->frameno
/ sh_video
->fps
:
415 (double)AVS
->sampleno
/ sh_audio
->samplerate
;
416 double duration
= sh_video
?
417 (double)AVS
->video_info
->num_frames
/ sh_video
->fps
:
418 (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
;
420 //mp_msg(MSGT_DEMUX, MSGL_V, "AVS: seek rel_seek_secs = %f - flags = %x\n", rel_seek_secs, flags);
422 if (flags
&SEEK_ABSOLUTE
) video_pos
=0;
423 if (flags
&SEEK_FACTOR
) rel_seek_secs
*= duration
;
425 video_pos
+= rel_seek_secs
;
426 if (video_pos
< 0) video_pos
= 0;
429 AVS
->frameno
= FFMIN(video_pos
* sh_video
->fps
,
430 AVS
->video_info
->num_frames
);
431 sh_video
->num_frames_decoded
= AVS
->frameno
;
432 sh_video
->num_frames
= AVS
->frameno
;
434 video_pos
+= audio_delay
;
435 if (video_pos
< 0) video_pos
= 0;
437 AVS
->sampleno
= FFMIN(video_pos
* sh_audio
->samplerate
,
438 AVS
->video_info
->num_audio_samples
);
441 static int avs_check_file(demuxer_t
*demuxer
)
443 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_check_file - attempting to open file %s\n", demuxer
->filename
);
445 if (!demuxer
->filename
) return 0;
447 /* Avoid crazy memory eating when passing an mpg stream */
448 if (demuxer
->movi_end
> MAX_AVS_SIZE
)
450 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: File is too big, aborting...\n");
454 demuxer
->priv
= initAVS(demuxer
->filename
);
458 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init Ok\n");
459 return DEMUXER_TYPE_AVS
;
461 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init failed\n");
466 const demuxer_desc_t demuxer_desc_avs
= {
471 "Requires binary dll",
473 0, // unsafe autodetect
475 demux_avs_fill_buffer
,