lwlibav_audio_output_handler_t *lwlibav_audio_alloc_output_handler ( void ) { return (lwlibav_audio_output_handler_t *)lw_malloc_zero( sizeof(lwlibav_audio_output_handler_t) ); }
libavsmash_video_output_handler_t *libavsmash_video_alloc_output_handler ( void ) { return (libavsmash_video_output_handler_t *)lw_malloc_zero( sizeof(libavsmash_video_output_handler_t) ); }
LSMASHVideoSource::LSMASHVideoSource ( const char *source, uint32_t track_number, int threads, int seek_mode, uint32_t forward_seek_threshold, int direct_rendering, int stacked_format, enum AVPixelFormat pixel_format, IScriptEnvironment *env ) { memset( &vi, 0, sizeof(VideoInfo) ); memset( &vdh, 0, sizeof(libavsmash_video_decode_handler_t) ); memset( &voh, 0, sizeof(libavsmash_video_output_handler_t) ); format_ctx = NULL; vdh.seek_mode = seek_mode; vdh.forward_seek_threshold = forward_seek_threshold; as_video_output_handler_t *as_vohp = (as_video_output_handler_t *)lw_malloc_zero( sizeof(as_video_output_handler_t) ); if( !as_vohp ) env->ThrowError( "LSMASHVideoSource: failed to allocate the AviSynth video output handler." ); as_vohp->vi = &vi; as_vohp->env = env; voh.private_handler = as_vohp; voh.free_private_handler = as_free_video_output_handler; get_video_track( source, track_number, threads, env ); lsmash_discard_boxes( vdh.root ); prepare_video_decoding( direct_rendering, stacked_format, pixel_format, env ); }
static int get_first_video_track( lsmash_handler_t *h, video_option_t *opt ) { if( h->audio_pcm_sample_count == 0 || h->audio_format.Format.nSamplesPerSec == 0 ) return -1; /* Only available if audio stream is present. */ if( opt->dummy.framerate_den == 0 ) return -1; h->framerate_num = opt->dummy.framerate_num; h->framerate_den = opt->dummy.framerate_den; h->video_sample_count = ((uint64_t)h->framerate_num * h->audio_pcm_sample_count - 1) / ((uint64_t)h->framerate_den * h->audio_format.Format.nSamplesPerSec) + 1; static const struct { int pixel_size; output_colorspace_tag compression; } colorspace_table[3] = { { YUY2_SIZE, OUTPUT_TAG_YUY2 }, { RGB24_SIZE, OUTPUT_TAG_RGB }, { YC48_SIZE, OUTPUT_TAG_YC48 } }; int linesize = MAKE_AVIUTL_PITCH( opt->dummy.width * (colorspace_table[ opt->dummy.colorspace ].pixel_size << 3) ); dummy_handler_t *hp = (dummy_handler_t *)h->video_private; hp->dummy_size = linesize * opt->dummy.height; if( hp->dummy_size <= 0 ) return -1; hp->dummy_data = lw_malloc_zero( hp->dummy_size ); if( !hp->dummy_data ) return -1; uint8_t *pic = hp->dummy_data; switch( colorspace_table[ opt->dummy.colorspace ].compression ) { case OUTPUT_TAG_YC48 : case OUTPUT_TAG_RGB : break; case OUTPUT_TAG_YUY2 : for( int i = 0; i < opt->dummy.height; i++ ) { for( int j = 0; j < linesize; j += 2 ) { pic[j ] = 0; pic[j + 1] = 128; } pic += linesize; } break; default : lw_freep( &hp->dummy_data ); return -1; } /* BITMAPINFOHEADER */ h->video_format.biSize = sizeof( BITMAPINFOHEADER ); h->video_format.biWidth = opt->dummy.width; h->video_format.biHeight = opt->dummy.height; h->video_format.biBitCount = colorspace_table[ opt->dummy.colorspace ].pixel_size << 3; h->video_format.biCompression = colorspace_table[ opt->dummy.colorspace ].compression; return 0; }
vs_video_output_handler_t *vs_allocate_video_output_handler ( lw_video_output_handler_t *vohp ) { vs_video_output_handler_t *vs_vohp = lw_malloc_zero( sizeof(vs_video_output_handler_t) ); if( !vs_vohp ) return NULL; vohp->private_handler = vs_vohp; vohp->free_private_handler = vs_free_video_output_handler; return vs_vohp; }
/***************************************************************************** * Allocators / Deallocators *****************************************************************************/ libavsmash_video_decode_handler_t *libavsmash_video_alloc_decode_handler ( void ) { libavsmash_video_decode_handler_t *vdhp = (libavsmash_video_decode_handler_t *)lw_malloc_zero( sizeof(libavsmash_video_decode_handler_t) ); if( !vdhp ) return NULL; vdhp->frame_buffer = av_frame_alloc(); if( !vdhp->frame_buffer ) { libavsmash_video_free_decode_handler( vdhp ); return NULL; } return vdhp; }
/***************************************************************************** * Allocators / Deallocators *****************************************************************************/ lwlibav_audio_decode_handler_t *lwlibav_audio_alloc_decode_handler ( void ) { lwlibav_audio_decode_handler_t *adhp = (lwlibav_audio_decode_handler_t *)lw_malloc_zero( sizeof(lwlibav_audio_decode_handler_t) ); if( !adhp ) return NULL; adhp->frame_buffer = av_frame_alloc(); if( !adhp->frame_buffer ) { lwlibav_audio_free_decode_handler( adhp ); return NULL; } return adhp; }
/* Allocate the handler of this plugin. */ static lwlibav_handler_t *alloc_handler ( void ) { lwlibav_handler_t *hp = lw_malloc_zero( sizeof(lwlibav_handler_t) ); if( !hp ) return NULL; if( !(hp->vdhp = lwlibav_video_alloc_decode_handler()) || !(hp->vohp = lwlibav_video_alloc_output_handler()) || !(hp->adhp = lwlibav_audio_alloc_decode_handler()) || !(hp->aohp = lwlibav_audio_alloc_output_handler()) ) { free_handler( &hp ); return NULL; } return hp; }
static void *open_file( char *file_name, reader_option_t *opt ) { /* Check file extension. */ if( lw_check_file_extension( file_name, "avs" ) < 0 ) return NULL; /* Try to open the file as avisynth script. */ avs_handler_t *hp = lw_malloc_zero( sizeof(avs_handler_t) ); if( !hp ) return NULL; AVS_Value res = initialize_avisynth( hp, file_name ); if( !avs_is_clip( res ) ) { if( hp->library ) close_avisynth_dll( hp ); lw_free( hp ); return NULL; } hp->func.avs_release_value( res ); return hp; }
int libavsmash_video_create_keyframe_list ( libavsmash_video_decode_handler_t *vdhp ) { vdhp->keyframe_list = (uint8_t *)lw_malloc_zero( (vdhp->sample_count + 1) * sizeof(uint8_t) ); if( !vdhp->keyframe_list ) return -1; for( uint32_t composition_sample_number = 1; composition_sample_number <= vdhp->sample_count; composition_sample_number++ ) { uint32_t decoding_sample_number = get_decoding_sample_number( vdhp->order_converter, composition_sample_number ); uint32_t rap_number; if( lsmash_get_closest_random_accessible_point_from_media_timeline( vdhp->root, vdhp->track_id, decoding_sample_number, &rap_number ) < 0 ) continue; if( decoding_sample_number == rap_number ) vdhp->keyframe_list[composition_sample_number] = 1; } return 0; }
/* Allocate the handler of this plugin. */ static lsmas_handler_t *alloc_handler ( void ) { lsmas_handler_t *hp = lw_malloc_zero( sizeof(lsmas_handler_t) ); if( !hp ) return NULL; hp->vdhp = libavsmash_video_alloc_decode_handler(); if( !hp->vdhp ) { free_handler( &hp ); return NULL; } hp->vohp = libavsmash_video_alloc_output_handler(); if( !hp->vohp ) { free_handler( &hp ); return NULL; } return hp; }
static void *open_file( char *file_path, reader_option_t *opt ) { libav_handler_t *hp = lw_malloc_zero( sizeof(libav_handler_t) ); if( !hp ) return NULL; /* Set up error handler. */ lw_log_handler_t lh = { 0 }; lh.level = LW_LOG_FATAL; lh.priv = &hp->uType; lh.show_log = NULL; hp->uType = MB_ICONERROR | MB_OK; /* Set options. */ lwlibav_option_t lwlibav_opt; lwlibav_opt.file_path = file_path; lwlibav_opt.threads = opt->threads; lwlibav_opt.av_sync = opt->av_sync; lwlibav_opt.no_create_index = opt->no_create_index; lwlibav_opt.force_video = opt->force_video; lwlibav_opt.force_video_index = opt->force_video_index; lwlibav_opt.force_audio = opt->force_audio; lwlibav_opt.force_audio_index = opt->force_audio_index; lwlibav_opt.apply_repeat_flag = opt->video_opt.apply_repeat_flag; lwlibav_opt.field_dominance = opt->video_opt.field_dominance; /* Set up progress indicator. */ progress_indicator_t indicator; indicator.open = open_indicator; indicator.update = update_indicator; indicator.close = close_indicator; progress_handler_t ph = { { 0 } }; ph.module_name = "lwinput.aui"; ph.template_id = IDD_PROGRESS_ABORTABLE; /* Construct index. */ if( lwlibav_construct_index( &hp->lwh, &hp->vdh, &hp->voh, &hp->adh, &hp->aoh, &lh, &lwlibav_opt, &indicator, &ph ) < 0 ) { free( hp ); return NULL; } return hp; }
static void *open_file ( char *file_name, reader_option_t *opt ) { /* Check file extension. */ if( lw_check_file_extension( file_name, "vpy" ) < 0 ) return NULL; /* Try to open the file as VapourSynth script. */ vpy_handler_t *hp = lw_malloc_zero( sizeof(vpy_handler_t) ); if( !hp ) return NULL; if( load_vsscript_dll( hp ) < 0 ) { free( hp ); return NULL; } if( hp->vsscript.func.init() == 0 ) goto fail; hp->vsapi = hp->vsscript.func.getVSApi(); if( !hp->vsapi || hp->vsscript.func.evaluateFile( &hp->vsscript.handle, file_name, efSetWorkingDir ) ) goto fail; hp->node = hp->vsscript.func.getOutput( hp->vsscript.handle, 0 ); if( !hp->node ) goto fail; hp->vi = hp->vsapi->getVideoInfo( hp->node ); /* */ hp->ctx = avcodec_alloc_context3( NULL ); if( !hp->ctx ) goto fail; return hp; fail: if( hp->library ) close_vsscript_dll( hp ); free( hp ); return NULL; }
static void *open_file( char *file_name, reader_option_t *opt ) { /* Check file extension. */ int file_name_length = strlen( file_name ); if( file_name_length < 5 ) return NULL; char *ext = &file_name[file_name_length - 4]; if( ext[0] != '.' || ext[1] != 'a' || ext[2] != 'v' || ext[3] != 's' ) return NULL; /* Try to open the file as avisynth script. */ avs_handler_t *hp = lw_malloc_zero( sizeof(avs_handler_t) ); if( !hp ) return NULL; AVS_Value res = initialize_avisynth( hp, file_name ); if( !avs_is_clip( res ) ) { if( hp->library ) close_avisynth_dll( hp ); free( hp ); return NULL; } hp->func.avs_release_value( res ); return hp; }
int libavsmash_video_setup_timestamp_info ( libavsmash_video_decode_handler_t *vdhp, libavsmash_video_output_handler_t *vohp, int64_t *framerate_num, int64_t *framerate_den ) { int err = -1; uint64_t media_timescale = lsmash_get_media_timescale( vdhp->root, vdhp->track_id ); uint64_t media_duration = lsmash_get_media_duration_from_media_timeline( vdhp->root, vdhp->track_id ); if( media_duration == 0 ) media_duration = INT32_MAX; if( vdhp->sample_count == 1 ) { /* Calculate average framerate. */ reduce_fraction( &media_timescale, &media_duration ); *framerate_num = (int64_t)media_timescale; *framerate_den = (int64_t)media_duration; err = 0; goto setup_finish; } lw_log_handler_t *lhp = &vdhp->config.lh; lsmash_media_ts_list_t ts_list; if( lsmash_get_media_timestamps( vdhp->root, vdhp->track_id, &ts_list ) < 0 ) { lw_log_show( lhp, LW_LOG_ERROR, "Failed to get timestamps." ); goto setup_finish; } if( ts_list.sample_count != vdhp->sample_count ) { lw_log_show( lhp, LW_LOG_ERROR, "Failed to count number of video samples." ); goto setup_finish; } uint32_t composition_sample_delay; if( lsmash_get_max_sample_delay( &ts_list, &composition_sample_delay ) < 0 ) { lsmash_delete_media_timestamps( &ts_list ); lw_log_show( lhp, LW_LOG_ERROR, "Failed to get composition delay." ); goto setup_finish; } if( composition_sample_delay ) { /* Consider composition order for keyframe detection. * Note: sample number for L-SMASH is 1-origin. */ vdhp->order_converter = (order_converter_t *)lw_malloc_zero( (ts_list.sample_count + 1) * sizeof(order_converter_t) ); if( !vdhp->order_converter ) { lsmash_delete_media_timestamps( &ts_list ); lw_log_show( lhp, LW_LOG_ERROR, "Failed to allocate memory." ); goto setup_finish; } for( uint32_t i = 0; i < ts_list.sample_count; i++ ) ts_list.timestamp[i].dts = i + 1; lsmash_sort_timestamps_composition_order( &ts_list ); for( uint32_t i = 0; i < ts_list.sample_count; i++ ) vdhp->order_converter[i + 1].composition_to_decoding = (uint32_t)ts_list.timestamp[i].dts; } /* Calculate average framerate. */ uint64_t largest_cts = ts_list.timestamp[0].cts; uint64_t second_largest_cts = 0; uint64_t first_duration = ts_list.timestamp[1].cts - ts_list.timestamp[0].cts; uint64_t composition_timebase = first_duration; int strict_cfr = 1; for( uint32_t i = 1; i < ts_list.sample_count; i++ ) { uint64_t duration = ts_list.timestamp[i].cts - ts_list.timestamp[i - 1].cts; if( duration == 0 ) { lsmash_delete_media_timestamps( &ts_list ); lw_log_show( lhp, LW_LOG_WARNING, "Detected CTS duplication at frame %" PRIu32, i ); err = 0; goto setup_finish; } if( strict_cfr && duration != first_duration ) strict_cfr = 0; composition_timebase = get_gcd( composition_timebase, duration ); second_largest_cts = largest_cts; largest_cts = ts_list.timestamp[i].cts; } uint64_t reduce = reduce_fraction( &media_timescale, &composition_timebase ); uint64_t composition_duration = ((largest_cts - ts_list.timestamp[0].cts) + (largest_cts - second_largest_cts)) / reduce; lsmash_delete_media_timestamps( &ts_list ); double avg_frame_rate = (vdhp->sample_count * ((double)media_timescale / composition_duration)); if( strict_cfr || !lw_try_rational_framerate( avg_frame_rate, framerate_num, framerate_den, composition_timebase ) ) { uint64_t num = (uint64_t)(avg_frame_rate * composition_timebase + 0.5); uint64_t den = composition_timebase; if( num && den ) reduce_fraction( &num, &den ); else { num = 1; den = 1; } *framerate_num = (int64_t)num; *framerate_den = (int64_t)den; } err = 0; setup_finish:; if( vohp->vfr2cfr ) { /* Override average framerate by specified output constant framerate. */ *framerate_num = (int64_t)vohp->cfr_num; *framerate_den = (int64_t)vohp->cfr_den; vohp->frame_count = ((double)vohp->cfr_num / vohp->cfr_den) * ((double)media_duration / media_timescale) + 0.5; } else vohp->frame_count = libavsmash_video_get_sample_count( vdhp ); uint32_t min_cts_sample_number = get_decoding_sample_number( vdhp->order_converter, 1 ); vdhp->config.error = lsmash_get_cts_from_media_timeline( vdhp->root, vdhp->track_id, min_cts_sample_number, &vdhp->min_cts ); return err; }
INPUT_HANDLE func_open( LPSTR file ) { lsmash_handler_t *hp = (lsmash_handler_t *)lw_malloc_zero( sizeof(lsmash_handler_t) ); if( !hp ) return NULL; hp->video_reader = READER_NONE; hp->audio_reader = READER_NONE; get_settings(); if( reader_opt.threads <= 0 ) reader_opt.threads = get_auto_threads(); extern lsmash_reader_t libavsmash_reader; extern lsmash_reader_t avs_reader; extern lsmash_reader_t vpy_reader; extern lsmash_reader_t libav_reader; extern lsmash_reader_t dummy_reader; static lsmash_reader_t *lsmash_reader_table[] = { &libavsmash_reader, &avs_reader, &vpy_reader, &libav_reader, &dummy_reader, NULL }; for( int i = 0; lsmash_reader_table[i]; i++ ) { if( reader_disabled[lsmash_reader_table[i]->type - 1] ) continue; int video_none = 1; int audio_none = 1; lsmash_reader_t reader = *lsmash_reader_table[i]; void *private_stuff = reader.open_file( file, &reader_opt ); if( private_stuff ) { if( !hp->video_private ) { hp->video_private = private_stuff; if( reader.get_video_track && reader.get_video_track( hp ) == 0 ) { hp->video_reader = reader.type; hp->read_video = reader.read_video; hp->is_keyframe = reader.is_keyframe; hp->video_cleanup = reader.video_cleanup; hp->close_video_file = reader.close_file; video_none = 0; } else hp->video_private = NULL; } if( !hp->audio_private ) { hp->audio_private = private_stuff; if( reader.get_audio_track && reader.get_audio_track( hp ) == 0 ) { hp->audio_reader = reader.type; hp->read_audio = reader.read_audio; hp->delay_audio = reader.delay_audio; hp->audio_cleanup = reader.audio_cleanup; hp->close_audio_file = reader.close_file; audio_none = 0; } else hp->audio_private = NULL; } } if( video_none && audio_none ) { if( reader.close_file ) reader.close_file( private_stuff ); } else { if( reader.destroy_disposable ) reader.destroy_disposable( private_stuff ); if( !video_none && reader.prepare_video_decoding && reader.prepare_video_decoding( hp, video_opt ) ) { if( hp->video_cleanup ) { hp->video_cleanup( hp ); hp->video_cleanup = NULL; } hp->video_private = NULL; hp->video_reader = READER_NONE; video_none = 1; } if( !audio_none && reader.prepare_audio_decoding && reader.prepare_audio_decoding( hp, audio_opt ) ) { if( hp->audio_cleanup ) { hp->audio_cleanup( hp ); hp->audio_cleanup = NULL; } hp->audio_private = NULL; hp->audio_reader = READER_NONE; audio_none = 1; } if( video_none && audio_none && reader.close_file ) reader.close_file( private_stuff ); } /* Found both video and audio reader. */ if( hp->video_reader != READER_NONE && hp->audio_reader != READER_NONE ) break; } if( hp->video_reader == hp->audio_reader ) { hp->global_private = hp->video_private; hp->close_file = hp->close_video_file; hp->close_video_file = NULL; hp->close_audio_file = NULL; } if( hp->video_reader == READER_NONE && hp->audio_reader == READER_NONE ) { DEBUG_MESSAGE_BOX_DESKTOP( MB_OK, "No readable video and/or audio stream" ); func_close( hp ); return NULL; } return hp; }
static void *open_file( char *file_name, reader_option_t *opt ) { return lw_malloc_zero( sizeof(dummy_handler_t) ); }