/* TODO: Support offset > INT64_MAX */ int64_t lsmash_bs_read_seek( lsmash_bs_t *bs, int64_t offset, int whence ) { if( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END ) return LSMASH_ERR_FUNCTION_PARAM; if( whence == SEEK_CUR ) offset -= lsmash_bs_get_remaining_buffer_size( bs ); /* Check whether we can seek on the buffer. */ if( !bs->buffer.unseekable ) { assert( bs->offset >= bs->buffer.store ); uint64_t dst_offset = bs_estimate_seek_offset( bs, offset, whence ); uint64_t offset_s = bs->offset - bs->buffer.store; uint64_t offset_e = bs->offset; if( bs->unseekable || (dst_offset >= offset_s && dst_offset < offset_e) ) { /* OK, we can. So, seek on the buffer. */ bs->buffer.pos = dst_offset - offset_s; bs->eob = 0; return lsmash_bs_get_stream_pos( bs ); } } if( bs->unseekable ) return LSMASH_ERR_NAMELESS; /* Try to seek the stream. */ int64_t ret = bs->seek( bs->stream, offset, whence ); if( ret < 0 ) return ret; bs->offset = ret; bs->written = LSMASH_MAX( bs->written, bs->offset ); bs->eof = 0; bs->eob = 0; /* The data on the buffer is invalid. */ lsmash_bs_empty( bs ); return ret; }
static void bs_dispose_past_data( lsmash_bs_t *bs ) { /* Move remainder bytes. */ assert( bs->buffer.store >= bs->buffer.pos ); size_t remainder = lsmash_bs_get_remaining_buffer_size( bs ); if( bs->buffer.pos && remainder ) memmove( lsmash_bs_get_buffer_data_start( bs ), lsmash_bs_get_buffer_data( bs ), remainder ); bs->buffer.store = remainder; bs->buffer.pos = 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; }