⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seekable_stream_decoder.c

📁 wince下著名的视频播放器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
}OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample){	FLAC__uint64 length;	FLAC__ASSERT(0 != decoder);	FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);	decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;	/* turn off md5 checking if a seek is attempted */	decoder->private_->do_md5_checking = false;	if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {		decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;		return false;	}	/* get the file length */	if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {		decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;		return false;	}	/* rewind */	if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {		decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;		return false;	}	if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {		decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;		return false;	}	if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {		decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;		return false;	}	return seek_to_absolute_sample_(decoder, length, sample);}/*********************************************************************** * * Private class methods * ***********************************************************************/void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder){	decoder->private_->read_callback = 0;	decoder->private_->seek_callback = 0;	decoder->private_->tell_callback = 0;	decoder->private_->length_callback = 0;	decoder->private_->eof_callback = 0;	decoder->private_->write_callback = 0;	decoder->private_->metadata_callback = 0;	decoder->private_->error_callback = 0;	decoder->private_->client_data = 0;	/* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */	decoder->private_->ignore_stream_info_block = false;	decoder->private_->ignore_seek_table_block = true;	decoder->protected_->md5_checking = false;}FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data){	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;	(void)decoder;	if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {		*bytes = 0;#if 0		/*@@@@@@ we used to do this: */		seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;		/* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */#endif		return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;	}	else if(*bytes > 0) {		if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {			seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;			return FLAC__STREAM_DECODER_READ_STATUS_ABORT;		}		if(*bytes == 0) {			if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {#if 0				/*@@@@@@ we used to do this: */				seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;				/* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */#endif				return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;			}			else				return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;		}		else {			return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;		}	}	else		return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */}FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data){	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;	(void)decoder;	if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {		FLAC__uint64 this_frame_sample = frame->header.number.sample_number;		FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;		FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;		FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);		seekable_stream_decoder->private_->got_a_frame = true;		seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */		if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */			unsigned delta = (unsigned)(target_sample - this_frame_sample);			/* kick out of seek mode */			seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;			/* shift out the samples before target_sample */			if(delta > 0) {				unsigned channel;				const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];				for(channel = 0; channel < frame->header.channels; channel++)					newbuffer[channel] = buffer[channel] + delta;				seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;				seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;				/* write the relevant samples */				return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);			}			else {				/* write the relevant samples */				return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);			}		}		else {			return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;		}	}	else {		if(seekable_stream_decoder->private_->do_md5_checking) {			if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))				return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;		}		return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);	}}void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data){	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;	(void)decoder;	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {		seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;		/* save the MD5 signature for comparison later */		memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);		if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))			seekable_stream_decoder->private_->do_md5_checking = false;	}	else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {		seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;	}	if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {		FLAC__bool ignore_block = false;		if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)			ignore_block = true;		else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)			ignore_block = true;		if(!ignore_block)			seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);	}}void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data){	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;	(void)decoder;	if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)		seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);}FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample){	FLAC__uint64 left_pos = 0, right_pos = stream_length;	FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;	FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */	FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */	FLAC__bool did_a_seek;	unsigned iteration = 0;	/* In the first iterations, we will calculate the target byte position 	 * by the distance from the target sample to left_sample and	 * right_sample (let's call it "proportional search").  After that, we	 * will switch to binary search.	 */	unsigned BINARY_SEARCH_AFTER_ITERATION = 2;	/* We will switch to a linear search once our current sample is less	 * that this number of samples ahead of the target sample	 */	static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;	/* If the total number of samples is unknown, use a large value and	 * increase 'iteration' to force binary search immediately.	 */	if(right_sample == 0) {		right_sample = (FLAC__uint64)(-1);		BINARY_SEARCH_AFTER_ITERATION = 0;	}	decoder->private_->target_sample = target_sample;	for( ; ; iteration++) {		if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {			if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {				pos = (right_pos + left_pos) / 2;			}			else {#ifndef FLAC__INTEGER_ONLY_LIBRARY#if defined _MSC_VER || defined __MINGW32__				/* with MSVC you have to spoon feed it the casting */				pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));#else				pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));#endif#else				/* a little less accurate: */				if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))					pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));				else /* @@@ WATCHOUT, ~2TB limit */					pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));#endif				/* @@@ TODO: might want to limit pos to some distance				 * before EOF, to make sure we land before the last frame,				 * thereby getting a this_fram_sample and so having a better				 * estimate.  this would also mostly (or totally if we could				 * be sure to land before the last frame) avoid the				 * end-of-stream case we have to check later.				 */			}			/* physical seek */			if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {				decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;				return false;			}			if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {				decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;				return false;			}			did_a_seek = true;		}		else			did_a_seek = false;		decoder->private_->got_a_frame = false;		if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {			decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;			return false;		}		if(!decoder->private_->got_a_frame) {			if(did_a_seek) {				/* this can happen if we seek to a point after the last frame; we drop				 * to binary search right away in this case to avoid any wasted				 * iterations of proportional search.				 */				right_pos = pos;				BINARY_SEARCH_AFTER_ITERATION = 0;			}			else {				/* this can probably only happen if total_samples is unknown and the				 * target_sample is past the end of the stream				 */				decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;				return false;			}		}		/* our write callback will change the state when it gets to the target frame */		else if(			decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&			decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM		) {			break;		}		else {			this_frame_sample = decoder->private_->last_frame.header.number.sample_number;			FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);			if (did_a_seek) {				if (this_frame_sample <= target_sample) {					/* The 'equal' case should not happen, since					 * OggFLAC__stream_decoder_process_single()					 * should recognize that it has hit the					 * target sample and we would exit through					 * the 'break' above.					 */					FLAC__ASSERT(this_frame_sample != target_sample);					left_sample = this_frame_sample;					/* sanity check to avoid infinite loop */					if (left_pos == pos) {						decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;						return false;					}					left_pos = pos;				}				else if(this_frame_sample > target_sample) {					right_sample = this_frame_sample;					/* sanity check to avoid infinite loop */					if (right_pos == pos) {						decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;						return false;					}					right_pos = pos;				}			}		}	}	return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -