1 /********************************************************************************
2 * avs_input.c
3 ********************************************************************************
4 * Copyright (C) 2012-2015 L-SMASH Works project
5 *
6 * Authors: Oka Motofumi <chikuzen.mo@gmail.com>
7 * Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *******************************************************************************/
27
28 /* This file is available under an MIT license.
29 * However, when distributing its binary file, it will be under LGPL or GPL.
30 * Don't distribute it if its license is GPL. */
31
32 #include "lwinput.h"
33
34 #define AVSC_NO_DECLSPEC
35 #undef EXTERN_C
36 #include "avisynth_c.h"
37
38 #define AVS_INTERFACE_25 2
39
40 #include <libavcodec/avcodec.h>
41 #include <libswscale/swscale.h>
42
43 #include "video_output.h"
44
45 typedef struct {
46 AVS_Clip *clip;
47 AVS_ScriptEnvironment *env;
48 const AVS_VideoInfo *vi;
49 HMODULE library;
50 struct
51 {
52 #define AVSC_DECLARE_FUNC( name ) name##_func name
53 AVSC_DECLARE_FUNC( avs_clip_get_error );
54 AVSC_DECLARE_FUNC( avs_create_script_environment );
55 AVSC_DECLARE_FUNC( avs_delete_script_environment );
56 AVSC_DECLARE_FUNC( avs_get_error );
57 AVSC_DECLARE_FUNC( avs_get_frame );
58 AVSC_DECLARE_FUNC( avs_get_audio );
59 AVSC_DECLARE_FUNC( avs_get_video_info );
60 AVSC_DECLARE_FUNC( avs_invoke );
61 AVSC_DECLARE_FUNC( avs_release_clip );
62 AVSC_DECLARE_FUNC( avs_release_value );
63 AVSC_DECLARE_FUNC( avs_release_video_frame );
64 AVSC_DECLARE_FUNC( avs_take_clip );
65 #undef AVSC_DECLARE_FUNC
66 } func;
67 /* Video stuff */
68 AVFrame *av_frame;
69 lw_video_output_handler_t voh;
70 int bit_depth;
71 } avs_handler_t;
72
load_avisynth_dll(avs_handler_t * hp)73 static int load_avisynth_dll( avs_handler_t *hp )
74 {
75 #define LOAD_AVS_FUNC( name, ignore_fail ) \
76 do \
77 { \
78 hp->func.name = (name##_func)GetProcAddress( hp->library, #name ); \
79 if( !ignore_fail && !hp->func.name ) \
80 goto fail; \
81 } while( 0 )
82 hp->library = LoadLibrary( "avisynth" );
83 if( !hp->library )
84 return -1;
85 LOAD_AVS_FUNC( avs_clip_get_error, 0 );
86 LOAD_AVS_FUNC( avs_create_script_environment, 0 );
87 LOAD_AVS_FUNC( avs_delete_script_environment, 1 );
88 LOAD_AVS_FUNC( avs_get_error, 1 );
89 LOAD_AVS_FUNC( avs_get_frame, 0 );
90 LOAD_AVS_FUNC( avs_get_audio, 0 );
91 LOAD_AVS_FUNC( avs_get_video_info, 0 );
92 LOAD_AVS_FUNC( avs_invoke, 0 );
93 LOAD_AVS_FUNC( avs_release_clip, 0 );
94 LOAD_AVS_FUNC( avs_release_value, 0 );
95 LOAD_AVS_FUNC( avs_release_video_frame, 0 );
96 LOAD_AVS_FUNC( avs_take_clip, 0 );
97 return 0;
98 fail:
99 FreeLibrary( hp->library );
100 return -1;
101 #undef LOAD_AVS_FUNC
102 }
103
invoke_filter(avs_handler_t * hp,AVS_Value before,const char * filter)104 static AVS_Value invoke_filter( avs_handler_t *hp, AVS_Value before, const char *filter )
105 {
106 hp->func.avs_release_clip( hp->clip );
107 AVS_Value after = hp->func.avs_invoke( hp->env, filter, before, NULL );
108 hp->func.avs_release_value( before );
109 hp->clip = hp->func.avs_take_clip( after, hp->env );
110 hp->vi = hp->func.avs_get_video_info( hp->clip );
111 return after;
112 }
113
initialize_avisynth(avs_handler_t * hp,char * input)114 static AVS_Value initialize_avisynth( avs_handler_t *hp, char *input )
115 {
116 if( load_avisynth_dll( hp ) )
117 return avs_void;
118 hp->env = hp->func.avs_create_script_environment( AVS_INTERFACE_25 );
119 if( hp->func.avs_get_error && hp->func.avs_get_error( hp->env ) )
120 return avs_void;
121 AVS_Value arg = avs_new_value_string( input );
122 AVS_Value res = hp->func.avs_invoke( hp->env, "Import", arg, NULL );
123 if( avs_is_error( res ) )
124 return res;
125 AVS_Value mt_test = hp->func.avs_invoke( hp->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
126 int mt_mode = avs_is_int( mt_test ) ? avs_as_int( mt_test ) : 0;
127 hp->func.avs_release_value( mt_test );
128 if( mt_mode > 0 && mt_mode < 5 )
129 {
130 AVS_Value temp = hp->func.avs_invoke( hp->env, "Distributor", res, NULL );
131 hp->func.avs_release_value( res );
132 res = temp;
133 }
134 hp->clip = hp->func.avs_take_clip( res, hp->env );
135 hp->vi = hp->func.avs_get_video_info( hp->clip );
136 if( hp->vi->sample_type & AVS_SAMPLE_FLOAT )
137 res = invoke_filter( hp, res, "ConvertAudioTo16bit" );
138 return res;
139 }
140
close_avisynth_dll(avs_handler_t * hp)141 static void close_avisynth_dll( avs_handler_t *hp )
142 {
143 if( hp->clip )
144 hp->func.avs_release_clip( hp->clip );
145 if( hp->func.avs_delete_script_environment )
146 hp->func.avs_delete_script_environment( hp->env );
147 FreeLibrary( hp->library );
148 }
149
as_to_av_input_pixel_format(int as_input_pixel_format,int as_input_bit_depth,int * input_width)150 static enum AVPixelFormat as_to_av_input_pixel_format
151 (
152 int as_input_pixel_format,
153 int as_input_bit_depth,
154 int *input_width
155 )
156 {
157 if( as_input_bit_depth > 8 && (*input_width & 1) )
158 {
159 UINT uType = MB_ICONERROR | MB_OK;
160 lw_log_handler_t lh = { 0 };
161 lh.level = LW_LOG_WARNING;
162 lh.priv = &uType;
163 au_message_box_desktop( &lh, LW_LOG_WARNING, "Width of interleaved fake high bit-depth format must be mod2." );
164 /* Treat as 8-bit depth. */
165 as_input_bit_depth = 8;
166 }
167 static const struct
168 {
169 int as_input_pixel_format;
170 enum AVPixelFormat av_input_pixel_format;
171 int as_input_bit_depth;
172 } format_table[] =
173 {
174 { AVS_CS_I420, AV_PIX_FMT_YUV420P, 8 },
175 { AVS_CS_I420, AV_PIX_FMT_YUV420P9LE, 9 },
176 { AVS_CS_I420, AV_PIX_FMT_YUV420P10LE,10 },
177 { AVS_CS_I420, AV_PIX_FMT_YUV420P16LE,16 },
178 { AVS_CS_YV12, AV_PIX_FMT_YUV420P, 8 },
179 { AVS_CS_YV12, AV_PIX_FMT_YUV420P9LE, 9 },
180 { AVS_CS_YV12, AV_PIX_FMT_YUV420P10LE,10 },
181 { AVS_CS_YV12, AV_PIX_FMT_YUV420P16LE,16 },
182 { AVS_CS_YV16, AV_PIX_FMT_YUV422P, 8 },
183 { AVS_CS_YV16, AV_PIX_FMT_YUV422P9LE, 9 },
184 { AVS_CS_YV16, AV_PIX_FMT_YUV422P10LE,10 },
185 { AVS_CS_YV16, AV_PIX_FMT_YUV422P16LE,16 },
186 { AVS_CS_YV24, AV_PIX_FMT_YUV444P, 8 },
187 { AVS_CS_YV24, AV_PIX_FMT_YUV444P9LE, 9 },
188 { AVS_CS_YV24, AV_PIX_FMT_YUV444P10LE,10 },
189 { AVS_CS_YV24, AV_PIX_FMT_YUV444P16LE,16 },
190 { AVS_CS_YUV9, AV_PIX_FMT_YUV410P, 8 },
191 { AVS_CS_YV411, AV_PIX_FMT_YUV411P, 8 },
192 { AVS_CS_BGR24, AV_PIX_FMT_BGR24, 8 },
193 { AVS_CS_BGR24, AV_PIX_FMT_BGR48LE, 16 },
194 { AVS_CS_BGR32, AV_PIX_FMT_BGRA, 8 },
195 { AVS_CS_YUY2, AV_PIX_FMT_YUYV422, 8 },
196 { AVS_CS_Y8, AV_PIX_FMT_GRAY8, 8 },
197 { AVS_CS_Y8, AV_PIX_FMT_GRAY16LE, 16 },
198 { AVS_CS_UNKNOWN, AV_PIX_FMT_NONE, 0 }
199 };
200 for( int i = 0; format_table[i].as_input_pixel_format != AVS_CS_UNKNOWN; i++ )
201 if( as_input_pixel_format == format_table[i].as_input_pixel_format
202 && as_input_bit_depth == format_table[i].as_input_bit_depth )
203 {
204 if( as_input_bit_depth > 8 )
205 *input_width >>= 1;
206 return format_table[i].av_input_pixel_format;
207 }
208 return AV_PIX_FMT_NONE;
209 }
210
prepare_video_decoding(lsmash_handler_t * h,video_option_t * opt)211 static int prepare_video_decoding( lsmash_handler_t *h, video_option_t *opt )
212 {
213 avs_handler_t *hp = (avs_handler_t *)h->video_private;
214 h->video_sample_count = hp->vi->num_frames;
215 h->framerate_num = hp->vi->fps_numerator;
216 h->framerate_den = hp->vi->fps_denominator;
217 /* Set up video rendering. */
218 int input_width = hp->vi->width;
219 enum AVPixelFormat input_pixel_format = as_to_av_input_pixel_format( hp->vi->pixel_type, opt->avs.bit_depth, &input_width );
220 return au_setup_video_rendering( &hp->voh, opt, &h->video_format, input_width, hp->vi->height, input_pixel_format );
221 }
222
prepare_audio_decoding(lsmash_handler_t * h,audio_option_t * opt)223 static int prepare_audio_decoding( lsmash_handler_t *h, audio_option_t *opt )
224 {
225 avs_handler_t *hp = (avs_handler_t *)h->audio_private;
226 h->audio_pcm_sample_count = hp->vi->num_audio_samples;
227 /* Support of WAVEFORMATEXTENSIBLE is much restrictive on AviUtl, so we always use WAVEFORMATEX instead. */
228 WAVEFORMATEX *Format = &h->audio_format.Format;
229 Format->nChannels = hp->vi->nchannels;
230 Format->nSamplesPerSec = hp->vi->audio_samples_per_second;
231 Format->wBitsPerSample = avs_bytes_per_channel_sample( hp->vi ) * 8;
232 Format->nBlockAlign = avs_bytes_per_audio_sample( hp->vi );
233 Format->nAvgBytesPerSec = Format->nSamplesPerSec * Format->nBlockAlign;
234 Format->wFormatTag = WAVE_FORMAT_PCM;
235 Format->cbSize = 0;
236 return 0;
237 }
238
open_file(char * file_name,reader_option_t * opt)239 static void *open_file( char *file_name, reader_option_t *opt )
240 {
241 /* Check file extension. */
242 if( lw_check_file_extension( file_name, "avs" ) < 0 )
243 return NULL;
244 /* Try to open the file as avisynth script. */
245 avs_handler_t *hp = lw_malloc_zero( sizeof(avs_handler_t) );
246 if( !hp )
247 return NULL;
248 AVS_Value res = initialize_avisynth( hp, file_name );
249 if( !avs_is_clip( res ) )
250 {
251 if( hp->library )
252 close_avisynth_dll( hp );
253 lw_free( hp );
254 return NULL;
255 }
256 hp->func.avs_release_value( res );
257 return hp;
258 }
259
get_video_track(lsmash_handler_t * h,video_option_t * opt)260 static int get_video_track( lsmash_handler_t *h, video_option_t *opt )
261 {
262 avs_handler_t *hp = (avs_handler_t *)h->video_private;
263 if( hp->vi->num_frames <= 0 || hp->vi->width <= 0 || hp->vi->height <= 0 )
264 return -1;
265 hp->av_frame = av_frame_alloc();
266 if( !hp->av_frame )
267 return -1;
268 hp->bit_depth = opt->avs.bit_depth;
269 return prepare_video_decoding( h, opt );
270 }
271
get_audio_track(lsmash_handler_t * h,audio_option_t * opt)272 static int get_audio_track( lsmash_handler_t *h, audio_option_t *opt )
273 {
274 avs_handler_t *hp = (avs_handler_t *)h->audio_private;
275 if( hp->vi->num_audio_samples <= 0 )
276 return -1;
277 return prepare_audio_decoding( h, opt );
278 }
279
read_video(lsmash_handler_t * h,int sample_number,void * buf)280 static int read_video( lsmash_handler_t *h, int sample_number, void *buf )
281 {
282 avs_handler_t *hp = (avs_handler_t *)h->video_private;
283 AVS_VideoFrame *as_frame = hp->func.avs_get_frame( hp->clip, sample_number );
284 if( hp->func.avs_clip_get_error( hp->clip ) )
285 return 0;
286 if( avs_is_interleaved( hp->vi ) )
287 {
288 uint8_t *read_ptr = (uint8_t *)avs_get_read_ptr( as_frame );
289 int pitch = avs_get_pitch( as_frame );
290 if( avs_is_rgb( hp->vi ) )
291 {
292 hp->av_frame->data [0] = read_ptr + pitch * (hp->vi->height - 1);
293 hp->av_frame->linesize[0] = -pitch;
294 }
295 else
296 {
297 hp->av_frame->data [0] = read_ptr;
298 hp->av_frame->linesize[0] = pitch;
299 }
300 }
301 else
302 for( int i = 0; i < 3; i++ )
303 {
304 static const int as_plane[3] = { AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V };
305 hp->av_frame->data [i] = (uint8_t *)avs_get_read_ptr_p( as_frame, as_plane[i] );
306 hp->av_frame->linesize[i] = avs_get_pitch_p( as_frame, as_plane[i] );
307 }
308 hp->av_frame->width = hp->vi->width;
309 hp->av_frame->height = hp->vi->height;
310 hp->av_frame->format = as_to_av_input_pixel_format( hp->vi->pixel_type, hp->bit_depth, &hp->av_frame->width );
311 hp->av_frame->color_range = AVCOL_RANGE_UNSPECIFIED;
312 hp->av_frame->colorspace = AVCOL_SPC_UNSPECIFIED;
313 /* Here, update_scaler_configuration_if_needed() is required to activate the scaler. */
314 if( update_scaler_configuration_if_needed( &hp->voh.scaler, NULL, hp->av_frame ) < 0 )
315 return 0;
316 int frame_size = convert_colorspace( &hp->voh, hp->av_frame, buf );
317 hp->func.avs_release_video_frame( as_frame );
318 return frame_size;
319 }
320
read_audio(lsmash_handler_t * h,int start,int wanted_length,void * buf)321 static int read_audio( lsmash_handler_t *h, int start, int wanted_length, void *buf )
322 {
323 avs_handler_t *hp = (avs_handler_t *)h->audio_private;
324 hp->func.avs_get_audio( hp->clip, buf, start, wanted_length );
325 return wanted_length;
326 }
327
delay_audio(lsmash_handler_t * h,int * start,int wanted_length,int audio_delay)328 static int delay_audio( lsmash_handler_t *h, int *start, int wanted_length, int audio_delay )
329 {
330 if( *start < audio_delay )
331 {
332 if( *start + wanted_length < audio_delay )
333 return 0;
334 *start = audio_delay - *start;
335 }
336 else
337 *start -= audio_delay;
338 return 1;
339 }
340
video_cleanup(lsmash_handler_t * h)341 static void video_cleanup
342 (
343 lsmash_handler_t *h
344 )
345 {
346 avs_handler_t *hp = (avs_handler_t *)h->video_private;
347 if( !hp )
348 return;
349 av_frame_free( &hp->av_frame );
350 lw_cleanup_video_output_handler( &hp->voh );
351 }
352
close_file(void * private_stuff)353 static void close_file( void *private_stuff )
354 {
355 avs_handler_t *hp = (avs_handler_t *)private_stuff;
356 if( !hp )
357 return;
358 if( hp->library )
359 close_avisynth_dll( hp );
360 lw_free( hp );
361 }
362
363 lsmash_reader_t avs_reader =
364 {
365 AVS_READER,
366 open_file,
367 get_video_track,
368 get_audio_track,
369 NULL,
370 read_video,
371 read_audio,
372 NULL,
373 delay_audio,
374 video_cleanup,
375 NULL,
376 close_file
377 };
378