static int isom_read_minimum_chapter( FILE *chapter, isom_chapter_entry_t *data ) { char buff[CHAPTER_BUFSIZE]; if( isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) < 0 ) /* read newline */ return LSMASH_ERR_NAMELESS; char *p_buff = &buff[ !memcmp( buff, UTF8_BOM, UTF8_BOM_LENGTH ) ? UTF8_BOM_LENGTH : 0 ]; /* BOM detection */ if( isom_get_start_time( p_buff, data ) < 0 ) /* get start_time */ return LSMASH_ERR_INVALID_DATA; /* get chapter_name */ char *chapter_name = strchr( buff, ' ' ); /* find separator */ if( !chapter_name++ ) return LSMASH_ERR_INVALID_DATA; int len = LSMASH_MIN( 255, strlen( chapter_name ) ); /* We support length of chapter_name up to 255 */ data->chapter_name = (char *)lsmash_malloc( len + 1 ); if( !data->chapter_name ) return LSMASH_ERR_MEMORY_ALLOC; memcpy( data->chapter_name, chapter_name, len ); data->chapter_name[len] = '\0'; return 0; }
static int isom_read_minimum_chapter( FILE *chapter, isom_chapter_entry_t *data ) { char buff[CHAPTER_BUFSIZE]; int len; if( isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) ) /* read newline */ return -1; char *p_buff = !memcmp( buff, UTF8_BOM, UTF8_BOM_LENGTH ) ? &buff[UTF8_BOM_LENGTH] : &buff[0]; /* BOM detection */ if( isom_get_start_time( p_buff, data ) ) /* get start_time */ return -1; /* get chapter_name */ char *chapter_name = strchr( buff, ' ' ); /* find separator */ if( !chapter_name++ ) return -1; len = LSMASH_MIN( 255, strlen( chapter_name ) ); /* We support length of chapter_name up to 255 */ data->chapter_name = (char *)malloc( len + 1 ); if( !data->chapter_name ) return -1; memcpy( data->chapter_name, chapter_name, len ); data->chapter_name[len] = '\0'; return 0; }
static int isom_read_simple_chapter( FILE *chapter, isom_chapter_entry_t *data ) { char buff[CHAPTER_BUFSIZE]; /* get start_time */ if( isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) < 0 ) return LSMASH_ERR_NAMELESS; char *chapter_time = strchr( buff, '=' ); /* find separator */ if( !chapter_time++ ) return LSMASH_ERR_INVALID_DATA; if( isom_get_start_time( chapter_time, data ) < 0 ) return LSMASH_ERR_INVALID_DATA; if( isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) < 0 ) /* get chapter_name */ return LSMASH_ERR_NAMELESS; char *chapter_name = strchr( buff, '=' ); /* find separator */ if( !chapter_name++ ) return LSMASH_ERR_INVALID_DATA; int len = LSMASH_MIN( 255, strlen( chapter_name ) ); /* We support length of chapter_name up to 255 */ data->chapter_name = (char *)lsmash_malloc( len + 1 ); if( !data->chapter_name ) return LSMASH_ERR_MEMORY_ALLOC; memcpy( data->chapter_name, chapter_name, len ); data->chapter_name[len] = '\0'; return 0; }
static int isom_read_simple_chapter( FILE *chapter, isom_chapter_entry_t *data ) { char buff[CHAPTER_BUFSIZE]; int len; /* get start_time */ if( isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) ) return -1; char *chapter_time = strchr( buff, '=' ); /* find separator */ if( !chapter_time++ || isom_get_start_time( chapter_time, data ) || isom_lumber_line( buff, CHAPTER_BUFSIZE, chapter ) ) /* get chapter_name */ return -1; char *chapter_name = strchr( buff, '=' ); /* find separator */ if( !chapter_name++ ) return -1; len = LSMASH_MIN( 255, strlen( chapter_name ) ); /* We support length of chapter_name up to 255 */ data->chapter_name = (char *)malloc( len + 1 ); if( !data->chapter_name ) return -1; memcpy( data->chapter_name, chapter_name, len ); data->chapter_name[len] = '\0'; return 0; }
int isom_check_compatibility ( lsmash_file_t *file ) { if( !file ) return LSMASH_ERR_FUNCTION_PARAM; isom_clear_compat_flags( file ); /* Get the brand container. */ isom_ftyp_t *ftyp = file->ftyp ? file->ftyp : (isom_ftyp_t *)lsmash_get_entry_data( &file->styp_list, 1 ); /* Check brand to decide mandatory boxes. */ if( !ftyp ) { /* No brand declaration means this file is a MP4 version 1 or QuickTime file format. */ if( file->moov && file->moov->iods ) { file->mp4_version1 = 1; file->isom_compatible = 1; } else { file->qt_compatible = 1; file->undefined_64_ver = 1; } return 0; } for( uint32_t i = 0; i <= ftyp->brand_count; i++ ) { uint32_t brand = (i == ftyp->brand_count ? ftyp->major_brand : ftyp->compatible_brands[i]); switch( brand ) { case ISOM_BRAND_TYPE_QT : file->qt_compatible = 1; break; case ISOM_BRAND_TYPE_MP41 : file->mp4_version1 = 1; break; case ISOM_BRAND_TYPE_MP42 : file->mp4_version2 = 1; break; case ISOM_BRAND_TYPE_AVC1 : case ISOM_BRAND_TYPE_ISOM : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 1 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 1 ); break; case ISOM_BRAND_TYPE_ISO2 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 2 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 2 ); break; case ISOM_BRAND_TYPE_ISO3 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 3 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 3 ); break; case ISOM_BRAND_TYPE_ISO4 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 4 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 4 ); break; case ISOM_BRAND_TYPE_ISO5 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 5 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 5 ); break; case ISOM_BRAND_TYPE_ISO6 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 6 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 6 ); break; case ISOM_BRAND_TYPE_ISO7 : file->max_isom_version = LSMASH_MAX( file->max_isom_version, 7 ); file->min_isom_version = LSMASH_MIN( file->min_isom_version, 7 ); break; case ISOM_BRAND_TYPE_M4A : case ISOM_BRAND_TYPE_M4B : case ISOM_BRAND_TYPE_M4P : case ISOM_BRAND_TYPE_M4V : file->itunes_movie = 1; break; case ISOM_BRAND_TYPE_3GP4 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 4 ); break; case ISOM_BRAND_TYPE_3GP5 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 5 ); break; case ISOM_BRAND_TYPE_3GE6 : case ISOM_BRAND_TYPE_3GG6 : case ISOM_BRAND_TYPE_3GP6 : case ISOM_BRAND_TYPE_3GR6 : case ISOM_BRAND_TYPE_3GS6 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 6 ); break; case ISOM_BRAND_TYPE_3GP7 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 7 ); break; case ISOM_BRAND_TYPE_3GP8 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 8 ); break; case ISOM_BRAND_TYPE_3GE9 : case ISOM_BRAND_TYPE_3GF9 : case ISOM_BRAND_TYPE_3GG9 : case ISOM_BRAND_TYPE_3GH9 : case ISOM_BRAND_TYPE_3GM9 : case ISOM_BRAND_TYPE_3GP9 : case ISOM_BRAND_TYPE_3GR9 : case ISOM_BRAND_TYPE_3GS9 : case ISOM_BRAND_TYPE_3GT9 : file->max_3gpp_version = LSMASH_MAX( file->max_3gpp_version, 9 ); break; default : break; } switch( brand ) { case ISOM_BRAND_TYPE_AVC1 : case ISOM_BRAND_TYPE_ISO2 : case ISOM_BRAND_TYPE_ISO3 : case ISOM_BRAND_TYPE_ISO4 : case ISOM_BRAND_TYPE_ISO5 : case ISOM_BRAND_TYPE_ISO6 : file->avc_extensions = 1; break; case ISOM_BRAND_TYPE_3GP4 : case ISOM_BRAND_TYPE_3GP5 : case ISOM_BRAND_TYPE_3GP6 : case ISOM_BRAND_TYPE_3GP7 : case ISOM_BRAND_TYPE_3GP8 : case ISOM_BRAND_TYPE_3GP9 : file->forbid_tref = 1; break; case ISOM_BRAND_TYPE_3GH9 : case ISOM_BRAND_TYPE_3GM9 : case ISOM_BRAND_TYPE_DASH : case ISOM_BRAND_TYPE_DSMS : case ISOM_BRAND_TYPE_LMSG : case ISOM_BRAND_TYPE_MSDH : case ISOM_BRAND_TYPE_MSIX : case ISOM_BRAND_TYPE_SIMS : file->media_segment = 1; break; default : break; } } file->isom_compatible = !file->qt_compatible || file->mp4_version1 || file->mp4_version2 || file->itunes_movie || file->max_3gpp_version; file->undefined_64_ver = file->qt_compatible || file->itunes_movie; if( file->flags & LSMASH_FILE_MODE_WRITE ) { /* Media Segment is incompatible with ISO Base Media File Format version 4 or former must be compatible with * version 6 or later since it requires default-base-is-moof and Track Fragment Base Media Decode Time Box. */ if( file->media_segment && (file->min_isom_version < 5 || (file->max_isom_version && file->max_isom_version < 6)) ) return LSMASH_ERR_INVALID_DATA; file->allow_moof_base = (file->max_isom_version >= 5 && file->min_isom_version >= 5) || (file->max_isom_version == 0 && file->min_isom_version == UINT8_MAX && file->media_segment); } return 0; }
static int dts_importer_get_next_accessunit_internal( importer_t *importer ) { int au_completed = 0; dts_importer_t *dts_imp = (dts_importer_t *)importer->info; dts_info_t *info = &dts_imp->info; lsmash_bs_t *bs = info->bits->bs; while( !au_completed ) { /* Read data from the stream if needed. */ dts_imp->next_frame_pos += info->frame_size; lsmash_bs_read_seek( bs, dts_imp->next_frame_pos, SEEK_SET ); uint64_t remain_size = lsmash_bs_get_remaining_buffer_size( bs ); if( remain_size < DTS_MAX_EXSS_SIZE ) { int err = lsmash_bs_read( bs, bs->buffer.max_size ); if( err < 0 ) { lsmash_log( importer, LSMASH_LOG_ERROR, "failed to read data from the stream.\n" ); return err; } remain_size = lsmash_bs_get_remaining_buffer_size( bs ); } memcpy( dts_imp->buffer, lsmash_bs_get_buffer_data( bs ), LSMASH_MIN( remain_size, DTS_MAX_EXSS_SIZE ) ); /* Check the remainder length of the buffer. * If there is enough length, then parse the frame in it. * The length 10 is the required byte length to get frame size. */ if( bs->eob || (bs->eof && remain_size < 10) ) { /* Reached the end of stream. */ importer->status = IMPORTER_EOF; au_completed = !!dts_imp->incomplete_au_length; if( !au_completed ) { /* No more access units in the stream. */ if( lsmash_bs_get_remaining_buffer_size( bs ) ) { lsmash_log( importer, LSMASH_LOG_WARNING, "the stream is truncated at the end.\n" ); return LSMASH_ERR_INVALID_DATA; } return 0; } if( !info->ddts_param_initialized ) dts_update_specific_param( info ); } else { /* Parse substream frame. */ dts_substream_type prev_substream_type = info->substream_type; info->substream_type = dts_get_substream_type( info ); int err; int (*dts_parse_frame)( dts_info_t * ) = NULL; switch( info->substream_type ) { /* Decide substream frame parser and check if this frame and the previous frame belong to the same AU. */ case DTS_SUBSTREAM_TYPE_CORE : if( prev_substream_type != DTS_SUBSTREAM_TYPE_NONE ) au_completed = 1; dts_parse_frame = dts_parse_core_substream; break; case DTS_SUBSTREAM_TYPE_EXTENSION : { uint8_t prev_exss_index = info->exss_index; if( (err = dts_get_exss_index( info, &info->exss_index )) < 0 ) { lsmash_log( importer, LSMASH_LOG_ERROR, "failed to get the index of an extension substream.\n" ); return err; } if( prev_substream_type == DTS_SUBSTREAM_TYPE_EXTENSION && info->exss_index <= prev_exss_index ) au_completed = 1; dts_parse_frame = dts_parse_extension_substream; break; } default : lsmash_log( importer, LSMASH_LOG_ERROR, "unknown substream type is detected.\n" ); return LSMASH_ERR_NAMELESS; } if( !info->ddts_param_initialized && au_completed ) dts_update_specific_param( info ); info->frame_size = 0; if( (err = dts_parse_frame( info )) < 0 ) { lsmash_log( importer, LSMASH_LOG_ERROR, "failed to parse a frame.\n" ); return err; } } if( au_completed ) { memcpy( dts_imp->au, dts_imp->incomplete_au, dts_imp->incomplete_au_length ); dts_imp->au_length = dts_imp->incomplete_au_length; dts_imp->incomplete_au_length = 0; info->exss_count = (info->substream_type == DTS_SUBSTREAM_TYPE_EXTENSION); if( importer->status == IMPORTER_EOF ) break; } /* Increase buffer size to store AU if short. */ if( dts_imp->incomplete_au_length + info->frame_size > dts_imp->au_buffers->buffer_size ) { lsmash_multiple_buffers_t *temp = lsmash_resize_multiple_buffers( dts_imp->au_buffers, dts_imp->au_buffers->buffer_size + DTS_MAX_EXSS_SIZE ); if( !temp ) return LSMASH_ERR_MEMORY_ALLOC; dts_imp->au_buffers = temp; dts_imp->au = lsmash_withdraw_buffer( dts_imp->au_buffers, 1 ); dts_imp->incomplete_au = lsmash_withdraw_buffer( dts_imp->au_buffers, 2 ); } /* Append frame data. */ memcpy( dts_imp->incomplete_au + dts_imp->incomplete_au_length, dts_imp->buffer, info->frame_size ); dts_imp->incomplete_au_length += info->frame_size; } return bs->error ? LSMASH_ERR_NAMELESS : 0; }