void LSMASHVideoSource::get_video_track( const char *source, uint32_t track_number, int threads, IScriptEnvironment *env ) { uint32_t number_of_tracks = open_file( source, env ); if( track_number && track_number > number_of_tracks ) env->ThrowError( "LSMASHVideoSource: the number of tracks equals %I32u.", number_of_tracks ); /* L-SMASH */ uint32_t i; lsmash_media_parameters_t media_param; if( track_number == 0 ) { /* Get the first video track. */ for( i = 1; i <= number_of_tracks; i++ ) { vdh.track_ID = lsmash_get_track_ID( vdh.root, i ); if( vdh.track_ID == 0 ) env->ThrowError( "LSMASHVideoSource: failed to find video track." ); lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( vdh.root, vdh.track_ID, &media_param ) ) env->ThrowError( "LSMASHVideoSource: failed to get media parameters." ); if( media_param.handler_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK ) break; } if( i > number_of_tracks ) env->ThrowError( "LSMASHVideoSource: failed to find video track." ); } else { /* Get the desired video track. */ vdh.track_ID = lsmash_get_track_ID( vdh.root, track_number ); if( vdh.track_ID == 0 ) env->ThrowError( "LSMASHVideoSource: failed to find video track." ); lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( vdh.root, vdh.track_ID, &media_param ) ) env->ThrowError( "LSMASHVideoSource: failed to get media parameters." ); if( media_param.handler_type != ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK ) env->ThrowError( "LSMASHVideoSource: the track you specified is not a video track." ); } if( lsmash_construct_timeline( vdh.root, vdh.track_ID ) ) env->ThrowError( "LSMASHVideoSource: failed to get construct timeline." ); if( get_summaries( vdh.root, vdh.track_ID, &vdh.config ) ) env->ThrowError( "LSMASHVideoSource: failed to get summaries." ); vi.num_frames = lsmash_get_sample_count_in_media_timeline( vdh.root, vdh.track_ID ); setup_timestamp_info( &vdh, &vi, media_param.timescale, env ); /* libavformat */ for( i = 0; i < format_ctx->nb_streams && format_ctx->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO; i++ ); if( i == format_ctx->nb_streams ) env->ThrowError( "LSMASHVideoSource: failed to find stream by libavformat." ); /* libavcodec */ AVStream *stream = format_ctx->streams[i]; AVCodecContext *ctx = stream->codec; vdh.config.ctx = ctx; AVCodec *codec = avcodec_find_decoder( ctx->codec_id ); if( !codec ) env->ThrowError( "LSMASHVideoSource: failed to find %s decoder.", codec->name ); ctx->thread_count = threads; if( avcodec_open2( ctx, codec, NULL ) < 0 ) env->ThrowError( "LSMASHVideoSource: failed to avcodec_open2." ); }
static uint32_t libavsmash_video_fetch_media_timescale ( libavsmash_video_decode_handler_t *vdhp ) { if( !vdhp ) return 0; lsmash_media_parameters_t media_param; lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( vdhp->root, vdhp->track_id, &media_param ) < 0 ) return 0; vdhp->media_timescale = media_param.timescale; return vdhp->media_timescale; }
int main( int argc, char *argv[] ) { if ( argc < 2 ) { display_help(); return -1; } else if( !strcasecmp( argv[1], "-h" ) || !strcasecmp( argv[1], "--help" ) ) { display_help(); return 0; } else if( !strcasecmp( argv[1], "-v" ) || !strcasecmp( argv[1], "--version" ) ) { display_version(); return 0; } int dump_box = 1; int chapter = 0; char *filename; lsmash_get_mainargs( &argc, &argv ); if( argc > 2 ) { if( !strcasecmp( argv[1], "--box" ) ) DO_NOTHING; else if( !strcasecmp( argv[1], "--chapter" ) ) chapter = 1; else if( !strcasecmp( argv[1], "--timestamp" ) ) dump_box = 0; else { display_help(); return -1; } filename = argv[2]; } else { filename = argv[1]; } /* Open the input file. */ lsmash_root_t *root = lsmash_create_root(); if( !root ) { fprintf( stderr, "Failed to create a ROOT.\n" ); return -1; } lsmash_file_parameters_t file_param = { 0 }; if( lsmash_open_file( filename, 1, &file_param ) < 0 ) return BOXDUMPER_ERR( "Failed to open an input file.\n" ); if( dump_box ) file_param.mode |= LSMASH_FILE_MODE_DUMP; lsmash_file_t *file = lsmash_set_file( root, &file_param ); if( !file ) return BOXDUMPER_ERR( "Failed to add a file into a ROOT.\n" ); if( lsmash_read_file( file, &file_param ) < 0 ) return BOXDUMPER_ERR( "Failed to read a file\n" ); /* Dump the input file. */ if( chapter ) { if( lsmash_print_chapter_list( root ) ) return BOXDUMPER_ERR( "Failed to extract chapter.\n" ); } else if( dump_box ) { if( lsmash_print_movie( root, "-" ) ) return BOXDUMPER_ERR( "Failed to dump box structure.\n" ); } else { lsmash_movie_parameters_t movie_param; lsmash_initialize_movie_parameters( &movie_param ); lsmash_get_movie_parameters( root, &movie_param ); uint32_t num_tracks = movie_param.number_of_tracks; for( uint32_t track_number = 1; track_number <= num_tracks; track_number++ ) { uint32_t track_ID = lsmash_get_track_ID( root, track_number ); if( !track_ID ) return BOXDUMPER_ERR( "Failed to get track_ID.\n" ); lsmash_media_parameters_t media_param; lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( root, track_ID, &media_param ) ) return BOXDUMPER_ERR( "Failed to get media parameters.\n" ); if( lsmash_construct_timeline( root, track_ID ) ) return BOXDUMPER_ERR( "Failed to construct timeline.\n" ); uint32_t timeline_shift; if( lsmash_get_composition_to_decode_shift_from_media_timeline( root, track_ID, &timeline_shift ) ) return BOXDUMPER_ERR( "Failed to get timestamps.\n" ); lsmash_media_ts_list_t ts_list; if( lsmash_get_media_timestamps( root, track_ID, &ts_list ) ) return BOXDUMPER_ERR( "Failed to get timestamps.\n" ); fprintf( stdout, "track_ID: %"PRIu32"\n", track_ID ); fprintf( stdout, "Media timescale: %"PRIu32"\n", media_param.timescale ); lsmash_media_ts_t *ts_array = ts_list.timestamp; if( !ts_array ) { fprintf( stdout, "\n" ); continue; } for( uint32_t i = 0; i < ts_list.sample_count; i++ ) fprintf( stdout, "DTS = %"PRIu64", CTS = %"PRIu64"\n", ts_array[i].dts, ts_array[i].cts + timeline_shift ); lsmash_free( ts_array ); fprintf( stdout, "\n" ); } } lsmash_destroy_root( root ); return 0; }
static int wave_importer_probe( importer_t *importer ) { wave_importer_t *wave_imp = create_wave_importer( importer ); if( !wave_imp ) return LSMASH_ERR_MEMORY_ALLOC; int err = 0; uint32_t filesize; lsmash_bs_t *bs = importer->bs; if( lsmash_bs_get_be32( bs ) != LSMASH_4CC( 'R', 'I', 'F', 'F' ) || ((filesize = lsmash_bs_get_le32( bs ) + 8) < WAVE_MIN_FILESIZE && filesize > 8) || lsmash_bs_get_be32( bs ) != LSMASH_4CC( 'W', 'A', 'V', 'E' ) ) { err = LSMASH_ERR_INVALID_DATA; goto fail; } int fmt_chunk_present = 0; int data_chunk_present = 0; while( !bs->eob && !(fmt_chunk_present && data_chunk_present) ) { uint32_t ckID = lsmash_bs_get_be32( bs ); uint32_t ckSize = lsmash_bs_get_le32( bs ); lsmash_bs_reset_counter( bs ); switch( ckID ) { case LSMASH_4CC( 'f', 'm', 't', ' ' ) : if( ckSize < 16 ) { err = LSMASH_ERR_INVALID_DATA; goto fail; } if( (err = wave_parse_fmt_chunk( wave_imp, bs )) < 0 ) goto fail; fmt_chunk_present = 1; break; case LSMASH_4CC( 'd', 'a', 't', 'a' ) : if( !fmt_chunk_present ) { /* The 'fmt ' chunk must be present before the 'data' chunk. */ err = LSMASH_ERR_INVALID_DATA; goto fail; } wave_imp->chunk.data_offset = lsmash_bs_get_stream_pos( bs ); wave_imp->chunk.length = ckSize; wave_imp->chunk.number = 1; wave_imp->chunk.file = importer->file; wave_imp->number_of_samples = ckSize / wave_imp->fmt.wfx.nBlockAlign; data_chunk_present = 1; break; default : break; } if( !data_chunk_present ) { /* Skip the rest of this chunk. * Note that ckData is word-aligned even if ckSize is an odd number. */ uint32_t skip_size = ckSize; if( skip_size & 1 ) skip_size++; if( skip_size > lsmash_bs_count( bs ) ) { skip_size -= lsmash_bs_count( bs ); lsmash_bs_read_seek( bs, skip_size, SEEK_CUR ); } } } if( !(fmt_chunk_present && data_chunk_present) ) { err = LSMASH_ERR_INVALID_DATA; goto fail; } /* Make fake movie. * Treat WAVE file format as if it's QuickTime file format. */ uint32_t track_ID; lsmash_movie_parameters_t movie_param = { 0 }; lsmash_track_parameters_t track_param = { 0 }; lsmash_media_parameters_t media_param = { 0 }; importer->file->qt_compatible = 1; if( (err = lsmash_importer_make_fake_movie( importer )) < 0 || (err = lsmash_importer_make_fake_track( importer, ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK, &track_ID )) < 0 || (err = lsmash_get_movie_parameters( importer->root, &movie_param )) < 0 || (err = lsmash_get_track_parameters( importer->root, track_ID, &track_param )) < 0 || (err = lsmash_get_media_parameters( importer->root, track_ID, &media_param )) < 0 ) goto fail; movie_param.timescale = wave_imp->fmt.wfx.nSamplesPerSec; media_param.timescale = wave_imp->fmt.wfx.nSamplesPerSec; if( (err = lsmash_set_movie_parameters( importer->root, &movie_param )) < 0 || (err = lsmash_set_track_parameters( importer->root, track_ID, &track_param )) < 0 || (err = lsmash_set_media_parameters( importer->root, track_ID, &media_param )) < 0 ) goto fail; lsmash_audio_summary_t *summary = wave_create_summary( &wave_imp->fmt ); if( !summary || lsmash_add_sample_entry( importer->root, track_ID, summary ) != 1 ) { lsmash_cleanup_summary( (lsmash_summary_t *)summary ); err = LSMASH_ERR_NAMELESS; goto fail; } if( (err = lsmash_add_entry( importer->summaries, summary )) < 0 ) { lsmash_cleanup_summary( (lsmash_summary_t *)summary ); goto fail; } importer->info = wave_imp; importer->status = IMPORTER_OK; return 0; fail: lsmash_importer_break_fake_movie( importer ); remove_wave_importer( wave_imp ); importer->file->qt_compatible = 0; importer->info = NULL; return err; }
void LSMASHAudioSource::get_audio_track( const char *source, uint32_t track_number, bool skip_priming, IScriptEnvironment *env ) { uint32_t number_of_tracks = open_file( source, env ); if( track_number && track_number > number_of_tracks ) env->ThrowError( "LSMASHAudioSource: the number of tracks equals %I32u.", number_of_tracks ); /* L-SMASH */ uint32_t i; lsmash_media_parameters_t media_param; if( track_number == 0 ) { /* Get the first audio track. */ for( i = 1; i <= number_of_tracks; i++ ) { adh.track_ID = lsmash_get_track_ID( adh.root, i ); if( adh.track_ID == 0 ) env->ThrowError( "LSMASHAudioSource: failed to find audio track." ); lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( adh.root, adh.track_ID, &media_param ) ) env->ThrowError( "LSMASHAudioSource: failed to get media parameters." ); if( media_param.handler_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK ) break; } if( i > number_of_tracks ) env->ThrowError( "LSMASHAudioSource: failed to find audio track." ); } else { /* Get the desired audio track. */ adh.track_ID = lsmash_get_track_ID( adh.root, track_number ); if( adh.track_ID == 0 ) env->ThrowError( "LSMASHAudioSource: failed to find audio track." ); lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( adh.root, adh.track_ID, &media_param ) ) env->ThrowError( "LSMASHAudioSource: failed to get media parameters." ); if( media_param.handler_type != ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK ) env->ThrowError( "LSMASHAudioSource: the track you specified is not an audio track." ); } if( lsmash_construct_timeline( adh.root, adh.track_ID ) ) env->ThrowError( "LSMASHAudioSource: failed to get construct timeline." ); if( get_summaries( adh.root, adh.track_ID, &adh.config ) ) env->ThrowError( "LSMASHAudioSource: failed to get summaries." ); adh.frame_count = lsmash_get_sample_count_in_media_timeline( adh.root, adh.track_ID ); vi.num_audio_samples = lsmash_get_media_duration_from_media_timeline( adh.root, adh.track_ID ); if( skip_priming ) { uint32_t itunes_metadata_count = lsmash_count_itunes_metadata( adh.root ); for( i = 1; i <= itunes_metadata_count; i++ ) { lsmash_itunes_metadata_t metadata; if( lsmash_get_itunes_metadata( adh.root, i, &metadata ) < 0 ) continue; if( metadata.item != ITUNES_METADATA_ITEM_CUSTOM || (metadata.type != ITUNES_METADATA_TYPE_STRING && metadata.type != ITUNES_METADATA_TYPE_BINARY) || !metadata.meaning || !metadata.name || memcmp( "com.apple.iTunes", metadata.meaning, strlen( metadata.meaning ) ) || memcmp( "iTunSMPB", metadata.name, strlen( metadata.name ) ) ) { lsmash_cleanup_itunes_metadata( &metadata ); continue; } char *value = NULL; if( metadata.type == ITUNES_METADATA_TYPE_STRING ) { int length = strlen( metadata.value.string ); if( length >= 116 ) value = duplicate_as_string( metadata.value.string, length ); } else /* metadata.type == ITUNES_METADATA_TYPE_BINARY */ { if( metadata.value.binary.size >= 116 ) value = duplicate_as_string( metadata.value.binary.data, metadata.value.binary.size ); } lsmash_cleanup_itunes_metadata( &metadata ); if( !value ) continue; uint32_t dummy[9]; uint32_t priming_samples; uint32_t padding; uint64_t duration; if( 12 != sscanf( value, " %I32x %I32x %I32x %I64x %I32x %I32x %I32x %I32x %I32x %I32x %I32x %I32x", &dummy[0], &priming_samples, &padding, &duration, &dummy[1], &dummy[2], &dummy[3], &dummy[4], &dummy[5], &dummy[6], &dummy[7], &dummy[8] ) ) { delete [] value; continue; } delete [] value; adh.implicit_preroll = 1; aoh.skip_decoded_samples = priming_samples; vi.num_audio_samples = duration + priming_samples; break; } if( aoh.skip_decoded_samples == 0 ) { uint32_t ctd_shift; if( lsmash_get_composition_to_decode_shift_from_media_timeline( adh.root, adh.track_ID, &ctd_shift ) ) env->ThrowError( "LSMASHAudioSource: failed to get the timeline shift." ); aoh.skip_decoded_samples = ctd_shift + get_start_time( adh.root, adh.track_ID ); } } /* libavformat */ for( i = 0; i < format_ctx->nb_streams && format_ctx->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO; i++ ); if( i == format_ctx->nb_streams ) env->ThrowError( "LSMASHAudioSource: failed to find stream by libavformat." ); /* libavcodec */ AVStream *stream = format_ctx->streams[i]; AVCodecContext *ctx = stream->codec; adh.config.ctx = ctx; AVCodec *codec = avcodec_find_decoder( ctx->codec_id ); if( !codec ) env->ThrowError( "LSMASHAudioSource: failed to find %s decoder.", codec->name ); ctx->thread_count = 0; if( avcodec_open2( ctx, codec, NULL ) < 0 ) env->ThrowError( "LSMASHAudioSource: failed to avcodec_open2." ); }
int main( int argc, char *argv[] ) { if( argc < 2 ) return print_help( -1 ); int dump_box = 1; int chapter = 0; char *filename; if( argc > 2 ) { if( !strcasecmp( argv[1], "--box" ) ) DO_NOTHING; else if( !strcasecmp( argv[1], "--chapter" ) ) chapter = 1; else if( !strcasecmp( argv[1], "--timestamp" ) ) dump_box = 0; else return print_help( -1 ); filename = argv[2]; } else { if( !strcasecmp( argv[1], "-h" ) || !strcasecmp( argv[1], "--help" ) ) return print_help( 0 ); filename = argv[1]; } #ifdef _WIN32 _setmode( _fileno(stdin), _O_BINARY ); #endif lsmash_file_mode mode = LSMASH_FILE_MODE_READ; if( dump_box ) mode |= LSMASH_FILE_MODE_DUMP; lsmash_root_t *root = lsmash_open_movie( filename, mode ); if( !root ) { fprintf( stderr, "Failed to open input file.\n" ); return -1; } if( chapter ) { if( lsmash_print_chapter_list( root ) ) return BOXDUMPER_ERR( "Failed to extract chapter.\n" ); } else if( dump_box ) { if( lsmash_print_movie( root, "-" ) ) return BOXDUMPER_ERR( "Failed to dump box structure.\n" ); } else { lsmash_movie_parameters_t movie_param; lsmash_initialize_movie_parameters( &movie_param ); lsmash_get_movie_parameters( root, &movie_param ); uint32_t num_tracks = movie_param.number_of_tracks; for( uint32_t track_number = 1; track_number <= num_tracks; track_number++ ) { uint32_t track_ID = lsmash_get_track_ID( root, track_number ); if( !track_ID ) return BOXDUMPER_ERR( "Failed to get track_ID.\n" ); lsmash_media_parameters_t media_param; lsmash_initialize_media_parameters( &media_param ); if( lsmash_get_media_parameters( root, track_ID, &media_param ) ) return BOXDUMPER_ERR( "Failed to get media parameters.\n" ); if( lsmash_construct_timeline( root, track_ID ) ) return BOXDUMPER_ERR( "Failed to construct timeline.\n" ); uint32_t timeline_shift; if( lsmash_get_composition_to_decode_shift_from_media_timeline( root, track_ID, &timeline_shift ) ) return BOXDUMPER_ERR( "Failed to get timestamps.\n" ); lsmash_media_ts_list_t ts_list; if( lsmash_get_media_timestamps( root, track_ID, &ts_list ) ) return BOXDUMPER_ERR( "Failed to get timestamps.\n" ); fprintf( stdout, "track_ID: %"PRIu32"\n", track_ID ); fprintf( stdout, "Media timescale: %"PRIu32"\n", media_param.timescale ); lsmash_media_ts_t *ts_array = ts_list.timestamp; if( !ts_array ) { fprintf( stdout, "\n" ); continue; } for( uint32_t i = 0; i < ts_list.sample_count; i++ ) fprintf( stdout, "DTS = %"PRIu64", CTS = %"PRIu64"\n", ts_array[i].dts, ts_array[i].cts + timeline_shift ); free( ts_array ); fprintf( stdout, "\n" ); } } lsmash_destroy_root( root ); return 0; }