示例#1
0
文件: sfmf.cpp 项目: sfpgmr/sfmf2
	audio_reader::audio_reader(std::wstring& source)
	{
		{
			IMFByteStreamPtr stream;
			CHK(MFCreateFile(MF_FILE_ACCESSMODE::MF_ACCESSMODE_READ, MF_FILE_OPENMODE::MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILE_FLAGS::MF_FILEFLAGS_NONE, source.c_str(), &stream));

			IMFAttributesPtr attr;
			CHK(MFCreateAttributes(&attr, 10));
			CHK(attr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true));
			IMFSourceReaderPtr reader;
			CHK(MFCreateSourceReaderFromByteStream(stream.Get(), attr.Get(), &reader));

			//      CHK(MFCreateSourceReaderFromURL(source.c_str(),attr.Get(), &reader));
			CHK(reader.As(&reader_));
			QWORD length;
			CHK(stream->GetLength(&length));
			fileSize_ = length;
		}

		//CHK(reader_->GetServiceForStream(0, MF_WRAPPED_OBJECT, __uuidof(IMFByteStream), &stream));

		CHK(reader_->GetNativeMediaType(0, 0, &native_media_type_));
		CHK(MFCreateMediaType(&current_media_type_));
		CHK(current_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
		CHK(current_media_type_->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM));
		CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE,
			MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample)
			)
			);
		CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND,
			MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_SAMPLES_PER_SECOND, samples_per_second)
			));
		CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS,
			MFGetAttributeUINT32(native_media_type_.Get(), MF_MT_AUDIO_NUM_CHANNELS, channel_count)
			));
		//DWORD blockAlign;
		//CHK(native_media_type_->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &blockAlign));
		//CHK(current_media_type_->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT,blockAlign ));
		CHK(reader_->SetCurrentMediaType(0, nullptr, current_media_type_.Get()));
		CHK(reader_->GetCurrentMediaType(0, current_media_type_.ReleaseAndGetAddressOf()));
		UINT32 blockAlign;
		CHK(current_media_type_->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &blockAlign));

		DOUT(boost::wformat(L"Block Align: %10d %10x") % blockAlign % blockAlign);

	}
示例#2
0
static int MediaFoundation_open(Sound_Sample *sample, const char *ext)
{
	MediaFoundationFileContainer* media_foundation_file_container;
	Sound_SampleInternal* internal = (Sound_SampleInternal*)sample->opaque;
	HRESULT hresult;
	IMFSourceReader* source_reader = NULL;
	// Since the byte stream stuff is so complicated, if you need to test without it, 
	// you can hard code loading a file and use MFCreateSourceReaderFromURL.
//	const WCHAR* source_file = L"C:\\Users\\username\\Documents\\crystal.wav";
//	const WCHAR* source_file = L"C:\\Users\\username\\Documents\\battle_hymn_of_the_republic.mp3";
//	const WCHAR* source_file = L"C:\\Users\\username\\Documents\\TheDeclarationOfIndependencePreambleJFK.m4a";
	

	IMFByteStreamRWops* byte_stream = new IMFByteStreamRWops(internal->rw, sample);
//	hresult = MFCreateSourceReaderFromURL(source_file, NULL, &source_reader);
	hresult = MFCreateSourceReaderFromByteStream(byte_stream, NULL, &source_reader);
	if (FAILED(hresult))
    {
		SNDERR("Error opening input file");
		return 0;
	}

	media_foundation_file_container = (MediaFoundationFileContainer*)calloc(1, sizeof(MediaFoundationFileContainer));
	BAIL_IF_MACRO(media_foundation_file_container == NULL, ERR_OUT_OF_MEMORY, 0);

	internal->decoder_private = media_foundation_file_container;
	media_foundation_file_container->sourceReader = source_reader;
	media_foundation_file_container->byteStreamRWops = byte_stream;

	{
		HRESULT hr = hresult;
		IMFMediaType *pUncompressedAudioType = NULL;
		IMFMediaType* audio_type = NULL;

		// Select the first audio stream, and deselect all other streams.
		hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false);

		if (SUCCEEDED(hr))
		{
			// select first stream
			hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
		}

		// Getting format data and debugging
		{
			// Not sure of the difference between GetNativeMediaType/GetNativeMediaType.
			// Search suggests GetCurrentMediaType gets the complete uncompressed format.
			// hr = source_reader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &audio_type);
			// The method returns a copy of the media type, so it is safe to modify the object received in the ppMediaType parameter.
			hr = source_reader->GetNativeMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM,
				0, // Index of the media type to retreive (don't really know what that means)
				&audio_type
			);
			if(FAILED(hr))
			{
				SNDERR("GetNativeMediaType failed");
				free(media_foundation_file_container);
				SafeRelease(&source_reader);		
				return 0;
    		}

			UINT32 all_samples_independent = 0;
			UINT32 fixed_size_samples = 0;
			UINT32 sample_size = 0;
			UINT32 bits_per_sample = 0;
			UINT32 block_alignment = 0;
			UINT32 num_channels = 0;
			UINT32 samples_per_second = 0;
			hr = audio_type->GetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, &all_samples_independent);
			hr = audio_type->GetUINT32(MF_MT_FIXED_SIZE_SAMPLES, &fixed_size_samples);
			hr = audio_type->GetUINT32(MF_MT_SAMPLE_SIZE, &sample_size);
			hr = audio_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
			hr = audio_type->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment);
			hr = audio_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &num_channels);
			hr = audio_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &samples_per_second);

			SNDDBG2("WindowsMediaFoundation: all_samples_independent == (%d).\n", all_samples_independent);
			SNDDBG2("WindowsMediaFoundation: fixed_size_samples == (%d).\n", fixed_size_samples);
			SNDDBG2("WindowsMediaFoundation: sample_size == (%d).\n", sample_size);
			SNDDBG2("WindowsMediaFoundation: bits_per_sample == (%d).\n", bits_per_sample);
			SNDDBG2("WindowsMediaFoundation: block_alignment == (%d).\n", block_alignment);
			SNDDBG2("WindowsMediaFoundation: num_channels == (%d).\n", num_channels);
			SNDDBG2("WindowsMediaFoundation: samples_per_second == (%d).\n", samples_per_second);


			// Get the total length of the stream 
			PROPVARIANT prop_variant;
			double duration_in_milliseconds = -1.0;
			// get the duration, which is a 64-bit integer of 100-nanosecond units
			hr = source_reader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop_variant);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to get duration");
				duration_in_milliseconds = -1.0;
			}
			else
			{
				LONGLONG file_duration = prop_variant.uhVal.QuadPart;
				//double durationInSeconds = (file_duration / static_cast<double>(10000 * 1000));
				duration_in_milliseconds = (file_duration / static_cast<double>(10000));
			}
			PropVariantClear(&prop_variant);


			sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
			sample->actual.rate = samples_per_second;
			sample->actual.channels = (UINT8)num_channels;
			internal->total_time = (INT32)(duration_in_milliseconds + 0.5);
			/*
			 * I want to use the native system to do conversion and decoding for performance reasons.
			 * This is particularly important on mobile devices like iOS.
			 * Taking from the Ogg Vorbis decode, I pretend the "actual" format is the same 
			 * as the desired format. 
			 */
			if(0 == sample->desired.format)
			{
				sample->actual.format = AUDIO_S16SYS;
			}
			else
			{
				sample->actual.format = sample->desired.format;				
			}

			SNDDBG2("WindowsMediaFoundation: total seconds of sample == (%d).\n", internal->total_time);


			// For compressed files, the bits per sample is undefined
			if(0 == bits_per_sample)
			{
				// hard code to 16
				media_foundation_file_container->bitsPerSample = 16;
			}
			else
			{
				media_foundation_file_container->bitsPerSample = bits_per_sample;
			}

			SafeRelease(&audio_type);		
			

		}


		{
			IMFMediaType* target_audio_type = NULL;
		

			// Create a partial media type that specifies uncompressed PCM audio.
			hr = MFCreateMediaType(&target_audio_type);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to create target MediaType\n");
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
			}

			hr = target_audio_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to set MFMediaType_Audio\n");
				SafeRelease(&target_audio_type);
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
				return 0;
			}
			// We want to decode to raw PCM
			hr = target_audio_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to set MFAudioFormat_PCM\n");
				SafeRelease(&target_audio_type);
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
				return 0;
			}

			// Set this type on the source reader. The source reader will
			// load the necessary decoder.
			hr = source_reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, target_audio_type);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n");
				SafeRelease(&target_audio_type);
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
				return 0;
			}

			// Don't need this any more
			SafeRelease(&target_audio_type);
		}

		// specify the output type (pcm)
		{
			IMFMediaType* uncompressed_audio_type = NULL;
			

			// Get the complete uncompressed format.
			hr = source_reader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &uncompressed_audio_type);
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n");
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
				return 0;
			}
			hr = source_reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
			// Ensure the stream is selected.
			if(FAILED(hr))
			{
				SNDERR("WindowsMediaFoundation: Failed to set SetCurrentMediaType\n");
				SafeRelease(&uncompressed_audio_type);
				SafeRelease(&source_reader);
				free(media_foundation_file_container);
				return 0;
			}

			// libaudiodecoder
			UINT32 leftover_buffer_size = 0;
			hr = uncompressed_audio_type->GetUINT32(MF_MT_SAMPLE_SIZE, &leftover_buffer_size);
			if(FAILED(hr))
			{
				// EW: MS docs say this will fail for varible length samples (proably aac, etc?)
				// So this could happen a lot.
				// So far, haven't noticed adverse effects.
				SNDDBG2("WindowsMediaFoundation: Failed to get leftover_buffer_size\n");
				leftover_buffer_size = 32;
			}



			media_foundation_file_container->leftoverBufferSize = leftover_buffer_size;
			media_foundation_file_container->leftoverBufferSize = leftover_buffer_size;
			media_foundation_file_container->leftoverBufferSize /= 2; // convert size in bytes to size in int16s
			media_foundation_file_container->leftoverBuffer = (short*)malloc(media_foundation_file_container->leftoverBufferSize * sizeof(short));

			media_foundation_file_container->uncompressedAudioType = uncompressed_audio_type;
			media_foundation_file_container->uncompressedAudioType->AddRef();
			SafeRelease(&uncompressed_audio_type);

		}

	}
		
	return(1);
} /* MediaFoundation_open */