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

📄 metadata_manip.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 5 页
字号:
	return true;
}

static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
{
	if(filename_based)
		return FLAC__metadata_chain_read(chain, flacfile_);
	else {
		FLAC__IOCallbacks callbacks;

		memset(&callbacks, 0, sizeof(callbacks));
		callbacks.read = (FLAC__IOCallback_Read)fread;
		callbacks.seek = chain_seek_cb_;
		callbacks.tell = chain_tell_cb_;

		{
			FLAC__bool ret;
			FILE *file = fopen(filename, "rb");
			if(0 == file)
				return false; /*@@@ chain status still says OK though */
			ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
			fclose(file);
			return ret;
		}
	}
}

/* function for comparing our metadata to a FLAC__Metadata_Chain */

static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
{
	unsigned i;
	FLAC__Metadata_Iterator *iterator;
	FLAC__StreamMetadata *block;
	FLAC__bool next_ok = true;

	FLAC__ASSERT(0 != chain);

	printf("\tcomparing chain... ");
	fflush(stdout);

	if(0 == (iterator = FLAC__metadata_iterator_new()))
		return die_("allocating memory for iterator");

	FLAC__metadata_iterator_init(iterator, chain);

	i = 0;
	do {
		printf("%u... ", i);
		fflush(stdout);

		if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
			FLAC__metadata_iterator_delete(iterator);
			return die_("getting block from iterator");
		}

		if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
			FLAC__metadata_iterator_delete(iterator);
			return die_("metadata block mismatch");
		}

		i++;
		next_ok = FLAC__metadata_iterator_next(iterator);
	} while(i < our_metadata_.num_blocks && next_ok);

	FLAC__metadata_iterator_delete(iterator);

	if(next_ok)
		return die_("chain has more blocks than expected");

	if(i < our_metadata_.num_blocks)
		return die_("short block count in chain");

	if(0 != current_block) {
		printf("CURRENT_POSITION... ");
		fflush(stdout);

		if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
			return die_("metadata block mismatch");
	}

	printf("PASSED\n");

	return true;
}

/* decoder callbacks for checking the file */

static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
	(void)decoder, (void)buffer, (void)client_data;

	if(
		(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
		(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
	) {
		printf("content... ");
		fflush(stdout);
	}

	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}

/* this version pays no attention to the metadata */
static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
	(void)decoder, (void)metadata, (void)client_data;

	printf("%d... ", mc_our_block_number_);
	fflush(stdout);

	mc_our_block_number_++;
}

/* this version is used when we want to compare to our metadata copy */
static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
	decoder_client_struct *dcd = (decoder_client_struct*)client_data;

	(void)decoder;

	/* don't bother checking if we've already hit an error */
	if(dcd->error_occurred)
		return;

	printf("%d... ", mc_our_block_number_);
	fflush(stdout);

	if(mc_our_block_number_ >= our_metadata_.num_blocks) {
		(void)die_("got more metadata blocks than expected");
		dcd->error_occurred = true;
	}
	else {
		if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
			(void)die_("metadata block mismatch");
			dcd->error_occurred = true;
		}
	}
	mc_our_block_number_++;
}

static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
	decoder_client_struct *dcd = (decoder_client_struct*)client_data;
	(void)decoder;

	dcd->error_occurred = true;
	printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
}

static FLAC__bool generate_file_()
{
	FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
	FLAC__StreamMetadata *metadata[1];

	printf("generating FLAC file for test\n");

	while(our_metadata_.num_blocks > 0)
		delete_from_our_metadata_(0);

	streaminfo.is_last = false;
	streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
	streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
	streaminfo.data.stream_info.min_blocksize = 576;
	streaminfo.data.stream_info.max_blocksize = 576;
	streaminfo.data.stream_info.min_framesize = 0;
	streaminfo.data.stream_info.max_framesize = 0;
	streaminfo.data.stream_info.sample_rate = 44100;
	streaminfo.data.stream_info.channels = 1;
	streaminfo.data.stream_info.bits_per_sample = 8;
	streaminfo.data.stream_info.total_samples = 0;
	memset(streaminfo.data.stream_info.md5sum, 0, 16);

	{
		const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
		vorbiscomment.is_last = false;
		vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
		vorbiscomment.length = (4 + vendor_string_length) + 4;
		vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
		vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
		memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
		vorbiscomment.data.vorbis_comment.num_comments = 0;
		vorbiscomment.data.vorbis_comment.comments = 0;
	}

	padding.is_last = true;
	padding.type = FLAC__METADATA_TYPE_PADDING;
	padding.length = 1234;

	metadata[0] = &padding;

	if(
		!insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
		!insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
		!insert_to_our_metadata_(&padding, 2, /*copy=*/true)
	)
		return die_("priming our metadata");

	if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
		return die_("creating the encoded file");

	free(vorbiscomment.data.vorbis_comment.vendor_string.entry);

	return true;
}

static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
{
	FLAC__FileDecoder *decoder;
	decoder_client_struct decoder_client_data;

	FLAC__ASSERT(0 != filename);
	FLAC__ASSERT(0 != metadata_callback);

	mc_our_block_number_ = 0;
	decoder_client_data.error_occurred = false;

	printf("\ttesting '%s'... ", filename);
	fflush(stdout);

	if(0 == (decoder = FLAC__file_decoder_new()))
		return die_("couldn't allocate decoder instance");

	FLAC__file_decoder_set_md5_checking(decoder, true);
	FLAC__file_decoder_set_filename(decoder, filename);
	FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
	FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
	FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
	FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
	FLAC__file_decoder_set_metadata_respond_all(decoder);
	if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
		FLAC__file_decoder_finish(decoder);
		FLAC__file_decoder_delete(decoder);
		return die_("initializing decoder\n");
	}
	if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
		FLAC__file_decoder_finish(decoder);
		FLAC__file_decoder_delete(decoder);
		return die_("decoding file\n");
	}

	FLAC__file_decoder_finish(decoder);
	FLAC__file_decoder_delete(decoder);

	if(decoder_client_data.error_occurred)
		return false;

	if(mc_our_block_number_ != our_metadata_.num_blocks)
		return die_("short metadata block count");

	printf("PASSED\n");
	return true;
}

static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
{
	if(!grabbag__file_change_stats(filename, read_only))
		return die_("during grabbag__file_change_stats()");

	return true;
}

static FLAC__bool remove_file_(const char *filename)
{
	while(our_metadata_.num_blocks > 0)
		delete_from_our_metadata_(0);

	if(!grabbag__file_remove_file(filename))
		return die_("removing file");

	return true;
}

static FLAC__bool test_level_0_()
{
	FLAC__StreamMetadata streaminfo;
	FLAC__StreamMetadata *tags = 0;

	printf("\n\n++++++ testing level 0 interface\n");

	if(!generate_file_())
		return false;

	if(!test_file_(flacfile_, decoder_metadata_callback_null_))
		return false;

	printf("testing FLAC__metadata_get_streaminfo()... ");

	if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
		return die_("during FLAC__metadata_get_streaminfo()");

	/* check to see if some basic data matches (c.f. generate_file_()) */
	if(streaminfo.data.stream_info.channels != 1)
		return die_("mismatch in streaminfo.data.stream_info.channels");
	if(streaminfo.data.stream_info.bits_per_sample != 8)
		return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
	if(streaminfo.data.stream_info.sample_rate != 44100)
		return die_("mismatch in streaminfo.data.stream_info.sample_rate");
	if(streaminfo.data.stream_info.min_blocksize != 576)
		return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
	if(streaminfo.data.stream_info.max_blocksize != 576)
		return die_("mismatch in streaminfo.data.stream_info.max_blocksize");

	printf("OK\n");

	printf("testing FLAC__metadata_get_tags()... ");

	if(!FLAC__metadata_get_tags(flacfile_, &tags))
		return die_("during FLAC__metadata_get_tags()");

	/* check to see if some basic data matches (c.f. generate_file_()) */
	if(tags->data.vorbis_comment.num_comments != 0)
		return die_("mismatch in tags->data.vorbis_comment.num_comments");

	printf("OK\n");

	FLAC__metadata_object_delete(tags);

	if(!remove_file_(flacfile_))
		return false;

	return true;
}

static FLAC__bool test_level_1_()
{
	FLAC__Metadata_SimpleIterator *iterator;
	FLAC__StreamMetadata *block, *app, *padding;
	FLAC__byte data[1000];
	unsigned our_current_position = 0;

⌨️ 快捷键说明

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