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.
30 #include "stream/stream.h"
33 #include "libvo/fastmemcpy.h"
35 #include "loader/wine/winbase.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 typedef WINAPI AVS_ScriptEnvironment
* (*imp_avs_create_script_environment
)(int version
);
47 typedef WINAPI
AVS_Value (*imp_avs_invoke
)(AVS_ScriptEnvironment
*, const char * name
, AVS_Value args
, const char** arg_names
);
48 typedef WINAPI
const AVS_VideoInfo
*(*imp_avs_get_video_info
)(AVS_Clip
*);
49 typedef WINAPI AVS_Clip
* (*imp_avs_take_clip
)(AVS_Value
, AVS_ScriptEnvironment
*);
50 typedef WINAPI
void (*imp_avs_release_clip
)(AVS_Clip
*);
51 typedef WINAPI AVS_VideoFrame
* (*imp_avs_get_frame
)(AVS_Clip
*, int n
);
52 typedef WINAPI
void (*imp_avs_release_video_frame
)(AVS_VideoFrame
*);
53 typedef WINAPI
int (*imp_avs_get_audio
)(AVS_Clip
*, void * buf
, uint64_t start
, uint64_t count
);
55 #define Q(string) # string
56 #define IMPORT_FUNC(x) \
57 AVS->x = ( imp_##x ) GetProcAddress(AVS->dll, Q(x)); \
58 if (!AVS->x) { mp_msg(MSGT_DEMUX,MSGL_V,"AVS: failed to load "Q(x)"()\n"); return 0; }
62 AVS_ScriptEnvironment
*avs_env
;
65 const AVS_VideoInfo
*video_info
;
74 imp_avs_create_script_environment avs_create_script_environment
;
75 imp_avs_invoke avs_invoke
;
76 imp_avs_get_video_info avs_get_video_info
;
77 imp_avs_take_clip avs_take_clip
;
78 imp_avs_release_clip avs_release_clip
;
79 imp_avs_get_frame avs_get_frame
;
80 imp_avs_release_video_frame avs_release_video_frame
;
81 imp_avs_get_audio avs_get_audio
;
84 static AVS_T
*initAVS(const char *filename
)
86 AVS_T
*AVS
= malloc (sizeof(AVS_T
));
87 AVS_Value arg0
= avs_new_value_string(filename
);
88 AVS_Value args
= avs_new_value_array(&arg0
, 1);
90 memset(AVS
, 0, sizeof(AVS_T
));
93 AVS
->ldt_fs
= Setup_LDT_Keeper();
96 AVS
->dll
= LoadLibraryA("avisynth.dll");
99 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: failed to load avisynth.dll\n");
103 /* Dynamic import of needed stuff from avisynth.dll */
104 IMPORT_FUNC(avs_create_script_environment
);
105 IMPORT_FUNC(avs_invoke
);
106 IMPORT_FUNC(avs_get_video_info
);
107 IMPORT_FUNC(avs_take_clip
);
108 IMPORT_FUNC(avs_release_clip
);
109 IMPORT_FUNC(avs_get_frame
);
110 IMPORT_FUNC(avs_release_video_frame
);
111 IMPORT_FUNC(avs_get_audio
);
113 AVS
->avs_env
= AVS
->avs_create_script_environment(AVISYNTH_INTERFACE_VERSION
);
116 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_create_script_environment failed\n");
121 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "Import", args
, 0);
123 if (avs_is_error(AVS
->handler
))
125 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth error: %s\n", avs_as_string(AVS
->handler
));
129 if (!avs_is_clip(AVS
->handler
))
131 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Avisynth doesn't return a clip\n");
138 if (AVS
->dll
) FreeLibrary(AVS
->dll
);
140 Restore_LDT_Keeper(AVS
->ldt_fs
);
146 /* Implement RGB MODES ?? */
148 static __inline
int get_mmioFOURCC(const AVS_VideoInfo
*v
)
150 if (avs_is_rgb(v
)) return mmioFOURCC(8, 'R', 'G', 'B');
151 if (avs_is_rgb24(v
)) return mmioFOURCC(24, 'R', 'G', 'B');
152 if (avs_is_rgb32(v
)) return mmioFOURCC(32, 'R', 'G', 'B');
153 if (avs_is_yv12(v
)) return mmioFOURCC('Y', 'V', '1', '2');
154 if (avs_is_yuy(v
)) return mmioFOURCC('Y', 'U', 'Y', ' ');
155 if (avs_is_yuy2(v
)) return mmioFOURCC('Y', 'U', 'Y', '2');
160 static int demux_avs_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
162 AVS_VideoFrame
*curr_frame
;
163 demux_packet_t
*dp
= NULL
;
164 AVS_T
*AVS
= demuxer
->priv
;
166 if (ds
== demuxer
->video
)
168 sh_video_t
*sh_video
= demuxer
->video
->sh
;
171 if (AVS
->video_info
->num_frames
<= AVS
->frameno
) return 0; // EOF
173 curr_frame
= AVS
->avs_get_frame(AVS
->clip
, AVS
->frameno
);
176 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: error getting frame -- EOF??\n");
179 w
= curr_frame
->row_size
;
180 h
= curr_frame
->height
;
182 dp
= new_demux_packet(w
* h
+ 2 * (w
/ 2) * (h
/ 2));
184 dp
->pts
=AVS
->frameno
/ sh_video
->fps
;
187 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offset
,
188 w
, h
, w
, curr_frame
->pitch
);
191 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetV
,
192 w
, h
, w
, curr_frame
->pitchUV
);
194 memcpy_pic(dst
, curr_frame
->vfb
->data
+ curr_frame
->offsetU
,
195 w
, h
, w
, curr_frame
->pitchUV
);
196 ds_add_packet(demuxer
->video
, dp
);
199 AVS
->avs_release_video_frame(curr_frame
);
203 if (ds
== demuxer
->audio
)
205 sh_audio_t
*sh_audio
= ds
->sh
;
206 int samples
= sh_audio
->samplerate
;
208 samples
= FFMIN(samples
, AVS
->video_info
->num_audio_samples
- AVS
->sampleno
);
209 if (!samples
) return 0;
210 l
= samples
* sh_audio
->channels
* sh_audio
->samplesize
;
212 mp_msg(MSGT_DEMUX
, MSGL_FATAL
, "AVS: audio packet too big\n");
215 dp
= new_demux_packet(l
);
216 dp
->pts
= AVS
->sampleno
/ sh_audio
->samplerate
;
218 if (AVS
->avs_get_audio(AVS
->clip
, dp
->buffer
, AVS
->sampleno
, samples
))
220 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_audio() failed\n");
223 ds_add_packet(demuxer
->audio
, dp
);
225 AVS
->sampleno
+= samples
;
231 static demuxer_t
* demux_open_avs(demuxer_t
* demuxer
)
234 AVS_T
*AVS
= demuxer
->priv
;
235 int audio_samplesize
= 0;
239 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: demux_open_avs()\n");
240 demuxer
->seekable
= 1;
242 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
245 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
249 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
250 if (!AVS
->video_info
)
252 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
256 if (!avs_is_yv12(AVS
->video_info
))
258 AVS
->handler
= AVS
->avs_invoke(AVS
->avs_env
, "ConvertToYV12", avs_new_value_array(&AVS
->handler
, 1), 0);
259 if (avs_is_error(AVS
->handler
))
261 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Cannot convert input video to YV12: %s\n", avs_as_string(AVS
->handler
));
265 AVS
->clip
= AVS
->avs_take_clip(AVS
->handler
, AVS
->avs_env
);
269 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_take_clip() failed\n");
273 AVS
->video_info
= AVS
->avs_get_video_info(AVS
->clip
);
274 if (!AVS
->video_info
)
276 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_get_video_info() call failed\n");
281 // TODO check field-based ??
284 if (avs_has_video(AVS
->video_info
))
286 sh_video_t
*sh_video
= new_sh_video(demuxer
, 0);
289 if (demuxer
->video
->id
== -1) demuxer
->video
->id
= 0;
290 if (demuxer
->video
->id
== 0)
291 demuxer
->video
->sh
= sh_video
;
292 sh_video
->ds
= demuxer
->video
;
294 sh_video
->disp_w
= AVS
->video_info
->width
;
295 sh_video
->disp_h
= AVS
->video_info
->height
;
297 //sh_video->format = get_mmioFOURCC(AVS->video_info);
298 sh_video
->format
= mmioFOURCC('Y', 'V', '1', '2');
299 sh_video
->fps
= (double) AVS
->video_info
->fps_numerator
/ (double) AVS
->video_info
->fps_denominator
;
300 sh_video
->frametime
= 1.0 / sh_video
->fps
;
302 sh_video
->bih
= malloc(sizeof(*sh_video
->bih
) + (256 * 4));
303 sh_video
->bih
->biCompression
= sh_video
->format
;
304 sh_video
->bih
->biBitCount
= avs_bits_per_pixel(AVS
->video_info
);
305 //sh_video->bih->biPlanes = 2;
307 sh_video
->bih
->biWidth
= AVS
->video_info
->width
;
308 sh_video
->bih
->biHeight
= AVS
->video_info
->height
;
309 sh_video
->num_frames
= 0;
310 sh_video
->num_frames_decoded
= 0;
314 if (avs_has_audio(AVS
->video_info
))
315 switch (AVS
->video_info
->sample_type
) {
316 case AVS_SAMPLE_INT8
: audio_samplesize
= 1; break;
317 case AVS_SAMPLE_INT16
: audio_samplesize
= 2; break;
318 case AVS_SAMPLE_INT24
: audio_samplesize
= 3; break;
319 case AVS_SAMPLE_INT32
:
320 case AVS_SAMPLE_FLOAT
: audio_samplesize
= 4; break;
322 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "AVS: unknown audio type, disabling\n");
324 if (audio_samplesize
)
326 sh_audio_t
*sh_audio
= new_sh_audio(demuxer
, 0);
328 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
);
330 if (demuxer
->audio
->id
== -1) demuxer
->audio
->id
= 0;
331 if (demuxer
->audio
->id
== 0)
332 demuxer
->audio
->sh
= sh_audio
;
333 sh_audio
->ds
= demuxer
->audio
;
335 sh_audio
->wf
= malloc(sizeof(*sh_audio
->wf
));
336 sh_audio
->wf
->wFormatTag
= sh_audio
->format
=
337 (AVS
->video_info
->sample_type
== AVS_SAMPLE_FLOAT
) ? 0x3 : 0x1;
338 sh_audio
->wf
->nChannels
= sh_audio
->channels
= AVS
->video_info
->nchannels
;
339 sh_audio
->wf
->nSamplesPerSec
= sh_audio
->samplerate
= AVS
->video_info
->audio_samples_per_second
;
340 sh_audio
->samplesize
= audio_samplesize
;
341 sh_audio
->wf
->nAvgBytesPerSec
= sh_audio
->channels
* sh_audio
->samplesize
* sh_audio
->samplerate
;
342 sh_audio
->wf
->nBlockAlign
= sh_audio
->channels
* sh_audio
->samplesize
;
343 sh_audio
->wf
->wBitsPerSample
= sh_audio
->samplesize
* 8;
344 sh_audio
->wf
->cbSize
= 0;
345 sh_audio
->i_bps
= sh_audio
->wf
->nAvgBytesPerSec
;
355 static int demux_avs_control(demuxer_t
*demuxer
, int cmd
, void *arg
)
357 sh_video_t
*sh_video
=demuxer
->video
->sh
;
358 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
359 AVS_T
*AVS
= demuxer
->priv
;
363 case DEMUXER_CTRL_GET_TIME_LENGTH
:
365 double res
= sh_video
? (double)AVS
->video_info
->num_frames
/ sh_video
->fps
: 0;
367 res
= FFMAX(res
, (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
);
368 *((double *)arg
) = res
;
369 return DEMUXER_CTRL_OK
;
371 case DEMUXER_CTRL_GET_PERCENT_POS
:
374 *((int *)arg
) = AVS
->frameno
* 100 / AVS
->video_info
->num_frames
;
376 *((int *)arg
) = AVS
->sampleno
* 100 / AVS
->video_info
->num_audio_samples
;
377 return DEMUXER_CTRL_OK
;
380 return DEMUXER_CTRL_NOTIMPL
;
384 static void demux_close_avs(demuxer_t
* demuxer
)
386 AVS_T
*AVS
= demuxer
->priv
;
393 AVS
->avs_release_clip(AVS
->clip
);
394 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: Unloading avisynth.dll\n");
395 FreeLibrary(AVS
->dll
);
398 Restore_LDT_Keeper(AVS
->ldt_fs
);
404 static void demux_seek_avs(demuxer_t
*demuxer
, float rel_seek_secs
, float audio_delay
, int flags
)
406 sh_video_t
*sh_video
=demuxer
->video
->sh
;
407 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
408 AVS_T
*AVS
= demuxer
->priv
;
409 double video_pos
= sh_video
?
410 (double)AVS
->frameno
/ sh_video
->fps
:
411 (double)AVS
->sampleno
/ sh_audio
->samplerate
;
412 double duration
= sh_video
?
413 (double)AVS
->video_info
->num_frames
/ sh_video
->fps
:
414 (double)AVS
->video_info
->num_audio_samples
/ sh_audio
->samplerate
;
416 //mp_msg(MSGT_DEMUX, MSGL_V, "AVS: seek rel_seek_secs = %f - flags = %x\n", rel_seek_secs, flags);
418 if (flags
&SEEK_ABSOLUTE
) video_pos
=0;
419 if (flags
&SEEK_FACTOR
) rel_seek_secs
*= duration
;
421 video_pos
+= rel_seek_secs
;
422 if (video_pos
< 0) video_pos
= 0;
425 AVS
->frameno
= FFMIN(video_pos
* sh_video
->fps
,
426 AVS
->video_info
->num_frames
);
427 sh_video
->num_frames_decoded
= AVS
->frameno
;
428 sh_video
->num_frames
= AVS
->frameno
;
430 video_pos
+= audio_delay
;
431 if (video_pos
< 0) video_pos
= 0;
433 AVS
->sampleno
= FFMIN(video_pos
* sh_audio
->samplerate
,
434 AVS
->video_info
->num_audio_samples
);
437 static int avs_check_file(demuxer_t
*demuxer
)
439 mp_msg(MSGT_DEMUX
, MSGL_V
, "AVS: avs_check_file - attempting to open file %s\n", demuxer
->filename
);
441 if (!demuxer
->filename
) return 0;
443 /* Avoid crazy memory eating when passing an mpg stream */
444 if (demuxer
->movi_end
> MAX_AVS_SIZE
)
446 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: File is too big, aborting...\n");
450 demuxer
->priv
= initAVS(demuxer
->filename
);
454 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init Ok\n");
455 return DEMUXER_TYPE_AVS
;
457 mp_msg(MSGT_DEMUX
,MSGL_V
, "AVS: Init failed\n");
462 const demuxer_desc_t demuxer_desc_avs
= {
467 "Requires binary dll",
469 0, // unsafe autodetect
471 demux_avs_fill_buffer
,