int lsmash_set_tyrant_chapter( lsmash_root_t *root, char *file_name, int add_bom ) { /* This function should be called after updating of the latest movie duration. */ if( !root || !root->moov || !root->moov->mvhd || !root->moov->mvhd->timescale || !root->moov->mvhd->duration ) goto error_message; /* check each line format */ fn_get_chapter_data fnc = isom_check_chap_line( file_name ); if( !fnc ) goto error_message; FILE *chapter = fopen( file_name, "rb" ); if( !chapter ) { lsmash_log( LSMASH_LOG_ERROR, "failed to open the chapter file \"%s\".\n", file_name ); goto error_message; } if( isom_add_udta( root, 0 ) || isom_add_chpl( root->moov ) ) goto fail; isom_chapter_entry_t data = {0}; while( !fnc( chapter, &data ) ) { if( add_bom ) { char *chapter_name_with_bom = (char *)malloc( strlen( data.chapter_name ) + 1 + UTF8_BOM_LENGTH ); if( !chapter_name_with_bom ) goto fail2; sprintf( chapter_name_with_bom, "%s%s", UTF8_BOM, data.chapter_name ); free( data.chapter_name ); data.chapter_name = chapter_name_with_bom; } data.start_time = (data.start_time + 50) / 100; /* convert to 100ns unit */ if( data.start_time / 1e7 > (double)root->moov->mvhd->duration / root->moov->mvhd->timescale ) { lsmash_log( LSMASH_LOG_WARNING, "a chapter point exceeding the actual duration detected. This chapter point and the following ones (if any) will be cut off.\n" ); free( data.chapter_name ); break; } if( isom_add_chpl_entry( root->moov->udta->chpl, &data ) ) goto fail2; free( data.chapter_name ); data.chapter_name = NULL; } fclose( chapter ); return 0; fail2: if( data.chapter_name ) free( data.chapter_name ); fail: fclose( chapter ); error_message: lsmash_log( LSMASH_LOG_ERROR, "failed to set chapter list.\n" ); return -1; }
int lsmash_set_tyrant_chapter( lsmash_root_t *root, char *file_name, int add_bom ) { if( isom_check_initializer_present( root ) < 0 ) goto error_message; /* This function should be called after updating of the latest movie duration. */ lsmash_file_t *file = root->file; if( !file || !file->moov || !file->moov->mvhd || file->moov->mvhd->timescale == 0 || file->moov->mvhd->duration == 0 ) goto error_message; /* check each line format */ fn_get_chapter_data fnc = isom_check_chap_line( file_name ); if( !fnc ) goto error_message; FILE *chapter = lsmash_fopen( file_name, "rb" ); if( !chapter ) { lsmash_log( NULL, LSMASH_LOG_ERROR, "failed to open the chapter file \"%s\".\n", file_name ); goto error_message; } if( (!file->moov->udta && !isom_add_udta( file->moov )) || (!file->moov->udta->chpl && !isom_add_chpl( file->moov->udta )) ) goto fail; file->moov->udta->chpl->version = 1; /* version = 1 is popular. */ isom_chapter_entry_t data = { 0 }; while( !fnc( chapter, &data ) ) { if( add_bom ) { char *chapter_name_with_bom = (char *)lsmash_malloc( strlen( data.chapter_name ) + 1 + UTF8_BOM_LENGTH ); if( !chapter_name_with_bom ) goto fail2; sprintf( chapter_name_with_bom, "%s%s", UTF8_BOM, data.chapter_name ); lsmash_free( data.chapter_name ); data.chapter_name = chapter_name_with_bom; } data.start_time = (data.start_time + 50) / 100; /* convert to 100ns unit */ if( data.start_time / 1e7 > (double)file->moov->mvhd->duration / file->moov->mvhd->timescale ) { lsmash_log( NULL, LSMASH_LOG_WARNING, "a chapter point exceeding the actual duration detected." "This chapter point and the following ones (if any) will be cut off.\n" ); lsmash_free( data.chapter_name ); break; } if( isom_add_chpl_entry( file->moov->udta->chpl, &data ) < 0 ) goto fail2; lsmash_freep( &data.chapter_name ); } fclose( chapter ); return 0; fail2: lsmash_free( data.chapter_name ); fail: fclose( chapter ); error_message: lsmash_log( NULL, LSMASH_LOG_ERROR, "failed to set chapter list.\n" ); return LSMASH_ERR_NAMELESS; }