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