Example #1
0
bool
BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to)
{
	_plugin_manager.DestroyDecoder(fRawDecoder);
	fRawDecoder = NULL;

#ifdef TRACE_MEDIA_TRACK
	char s[200];
	string_for_format(from, s, sizeof(s));
	printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s);
#endif

	status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from);
	if (res != B_OK) {
		ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n");
		return false;
	}

	// XXX video?
	int buffer_size = from.u.raw_audio.buffer_size;
	int frame_size = (from.u.raw_audio.format & 15)
		* from.u.raw_audio.channel_count;
	media_format notconstFrom = from;

	ChunkProvider *chunkProvider
		= new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size,
			frame_size);
	if (!chunkProvider) {
		ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk "
			"provider\n");
		goto error;
	}
	fRawDecoder->SetChunkProvider(chunkProvider);

	res = fRawDecoder->Setup(&notconstFrom, 0, 0);
	if (res != B_OK) {
		ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n");
		goto error;
	}

#ifdef TRACE_MEDIA_TRACK
	string_for_format(*to, s, sizeof(s));
	printf("BMediaTrack::SetupFormatTranslation:   to: %s\n", s);
#endif

	res = fRawDecoder->NegotiateOutputFormat(to);
	if (res != B_OK) {
		ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat "
			"failed\n");
		goto error;
	}

#ifdef TRACE_MEDIA_TRACK
	string_for_format(*to, s, sizeof(s));
	printf("BMediaTrack::SetupFormatTranslation:  res: %s\n", s);
#endif

	return true;

error:
	_plugin_manager.DestroyDecoder(fRawDecoder);
	fRawDecoder = NULL;
	return false;
}
Example #2
0
status_t
BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags)
{
	CALLED();
	if (!inout_format)
		return B_BAD_VALUE;
	if (!fExtractor || !fDecoder)
		return B_NO_INIT;

	_plugin_manager.DestroyDecoder(fRawDecoder);
	fRawDecoder = NULL;

#ifdef TRACE_MEDIA_TRACK
	char s[200];
	string_for_format(*inout_format, s, sizeof(s));
	printf("BMediaTrack::DecodedFormat: req1: %s\n", s);
#endif

	if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && inout_format->type == B_MEDIA_ENCODED_AUDIO)) {
		inout_format->type = B_MEDIA_RAW_AUDIO;
		inout_format->u.raw_audio = media_multi_audio_format::wildcard;
	}
	if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && inout_format->type == B_MEDIA_ENCODED_VIDEO)) {
		inout_format->type = B_MEDIA_RAW_VIDEO;
		inout_format->u.raw_video = media_raw_video_format::wildcard;
	}
	if (inout_format->type == B_MEDIA_RAW_AUDIO) {
		if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN)
			inout_format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
		if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)
			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
		if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT)
			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
		if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT)
			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
	}

#ifdef TRACE_MEDIA_TRACK
	string_for_format(*inout_format, s, sizeof(s));
	printf("BMediaTrack::DecodedFormat: req2: %s\n", s);
#endif

	fFormat = *inout_format;

	status_t res;

	res = fDecoder->NegotiateOutputFormat(inout_format);

#ifdef TRACE_MEDIA_TRACK
	string_for_format(*inout_format, s, sizeof(s));
	printf("BMediaTrack::DecodedFormat: nego: %s\n", s);
#endif

	if (inout_format->type == 0)
		debugger("Decoder didn't set output format type");
	if (inout_format->type == B_MEDIA_RAW_AUDIO) {
		if (inout_format->u.raw_audio.byte_order == 0)
			debugger("Decoder didn't set raw audio output byte order");
		if (inout_format->u.raw_audio.format == 0)
			debugger("Decoder didn't set raw audio output sample format");
		if (inout_format->u.raw_audio.buffer_size <= 0)
			debugger("Decoder didn't set raw audio output buffer size");
	}
	if (inout_format->type == B_MEDIA_RAW_VIDEO) {
		if (inout_format->u.raw_video.display.format == 0)
			debugger("Decoder didn't set raw video output color space");
		if (inout_format->u.raw_video.display.line_width == 0)
			debugger("Decoder didn't set raw video output line_width");
		if (inout_format->u.raw_video.display.line_count == 0)
			debugger("Decoder didn't set raw video output line_count");
		if (inout_format->u.raw_video.display.bytes_per_row == 0)
			debugger("Decoder didn't set raw video output bytes_per_row");
	}

	if (0 == (flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION)) {
		if (fFormat.type == B_MEDIA_RAW_AUDIO
			&& inout_format->type == B_MEDIA_RAW_AUDIO
			&& fFormat.u.raw_audio.format != 0
			&& fFormat.u.raw_audio.format != inout_format->u.raw_audio.format) {
				if (SetupFormatTranslation(*inout_format, &fFormat)) {
					*inout_format = fFormat;
				}
		}
	}

	fFormat = *inout_format;

//	string_for_format(*inout_format, s, sizeof(s));
//	printf("BMediaTrack::DecodedFormat: res: %s\n", s);

	return res;
}
Example #3
0
status_t FlangerNode::validateProposedFormat(
	const media_format& preferredFormat,
	media_format& ioProposedFormat) {

	char formatStr[256];
	PRINT(("FlangerNode::validateProposedFormat()\n"));

	ASSERT(preferredFormat.type == B_MEDIA_RAW_AUDIO);

	string_for_format(preferredFormat, formatStr, 255);
	PRINT(("\ttemplate format: %s\n", formatStr));

	string_for_format(ioProposedFormat, formatStr, 255);
	PRINT(("\tproposed format: %s\n", formatStr));

	status_t err = B_OK;

	if(ioProposedFormat.type != B_MEDIA_RAW_AUDIO) {
		// out of the ballpark
		ioProposedFormat = preferredFormat;
		return B_MEDIA_BAD_FORMAT;
	}

	// wildcard format
	media_raw_audio_format& wild = media_raw_audio_format::wildcard;
	// proposed format
	media_raw_audio_format& f = ioProposedFormat.u.raw_audio;
	// template format
	const media_raw_audio_format& pref = preferredFormat.u.raw_audio;

	if(pref.frame_rate != wild.frame_rate) {
		if(f.frame_rate != pref.frame_rate) {
			if(f.frame_rate != wild.frame_rate)
				err = B_MEDIA_BAD_FORMAT;
			f.frame_rate = pref.frame_rate;
		}
	}

	if(pref.channel_count != wild.channel_count) {
		if(f.channel_count != pref.channel_count) {
			if(f.channel_count != wild.channel_count)
				err = B_MEDIA_BAD_FORMAT;
			f.channel_count = pref.channel_count;
		}
	}

	if(pref.format != wild.format) {
		if(f.format != pref.format) {
			if(f.format != wild.format)
				err = B_MEDIA_BAD_FORMAT;
			f.format = pref.format;
		}
	}

	if(pref.byte_order != wild.byte_order) {
		if(f.byte_order != pref.byte_order) {
			if(f.byte_order != wild.byte_order)
				err = B_MEDIA_BAD_FORMAT;
			f.byte_order = pref.byte_order;
		}
	}

	if(pref.buffer_size != wild.buffer_size) {
		if(f.buffer_size != pref.buffer_size) {
			if(f.buffer_size != wild.buffer_size)
				err = B_MEDIA_BAD_FORMAT;
			f.buffer_size = pref.buffer_size;
		}
	}

	if(err != B_OK) {
		string_for_format(ioProposedFormat, formatStr, 255);
		PRINT((
			"\tformat conflict; suggesting:\n\tformat %s\n", formatStr));
	}

	return err;
}
Example #4
0
status_t
RawDecoder::NegotiateAudioOutputFormat(media_format *ioDecodedFormat)
{
	char s[1024];

	TRACE("RawDecoder::NegotiateAudioOutputFormat enter:\n");

	ioDecodedFormat->type = B_MEDIA_RAW_AUDIO;
	switch (ioDecodedFormat->u.raw_audio.format) {
		case media_raw_audio_format::B_AUDIO_FLOAT:
		case media_raw_audio_format::B_AUDIO_SHORT:
		case media_raw_audio_format::B_AUDIO_UCHAR:
		case media_raw_audio_format::B_AUDIO_CHAR:
			ioDecodedFormat->u.raw_audio.valid_bits = 0;
			break; // we can produce this on request

		case media_raw_audio_format::B_AUDIO_INT:
			ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits;
			break; // we can produce this on request

		default:
			switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
				case media_raw_audio_format::B_AUDIO_SHORT:
				case media_raw_audio_format::B_AUDIO_UCHAR:
				case media_raw_audio_format::B_AUDIO_CHAR:
					ioDecodedFormat->u.raw_audio.format = fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK;
					ioDecodedFormat->u.raw_audio.valid_bits = 0;
					break;

				case media_raw_audio_format::B_AUDIO_INT:
				case B_AUDIO_FORMAT_INT24:
					ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
					ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits;
					break;

				case media_raw_audio_format::B_AUDIO_FLOAT:
				case B_AUDIO_FORMAT_FLOAT64:
				default:
					ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
					ioDecodedFormat->u.raw_audio.valid_bits = 0;
					break;
			}
			break;
	}

	ioDecodedFormat->u.raw_audio.frame_rate = fInputFormat.u.raw_audio.frame_rate;
	ioDecodedFormat->u.raw_audio.channel_count = fInputFormat.u.raw_audio.channel_count;

	fFrameRate = (int32) ioDecodedFormat->u.raw_audio.frame_rate;

	fOutputSampleSize = (ioDecodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK);
	fOutputFrameSize = fOutputSampleSize * ioDecodedFormat->u.raw_audio.channel_count;

	if (ioDecodedFormat->u.raw_audio.byte_order == 0)
		ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;

	ioDecodedFormat->u.raw_audio.channel_mask = 0;
	ioDecodedFormat->u.raw_audio.matrix_mask = 0;

	ioDecodedFormat->u.raw_audio.buffer_size = fInputFormat.u.raw_audio.buffer_size;

// I don't believe we can negotiate the buffer size with the reader
// the decoder might use a different buffer for output but it must read all bytes given.
//	if (ioDecodedFormat->u.raw_audio.buffer_size < 128 || ioDecodedFormat->u.raw_audio.buffer_size > 65536) {
//		ioDecodedFormat->u.raw_audio.buffer_size = AudioBufferSize(
//														ioDecodedFormat->u.raw_audio.channel_count,
//														ioDecodedFormat->u.raw_audio.format,
//														ioDecodedFormat->u.raw_audio.frame_rate);
//	} else {
		// round down to exact multiple of output frame size
//		ioDecodedFormat->u.raw_audio.buffer_size = (ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize) * fOutputFrameSize;
//	}

	fOutputBufferFrameCount = ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize;

	// setup input swapping function
	if (fInputFormat.u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) {
		fSwapInput = 0;
	} else {
		switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
			case B_AUDIO_FORMAT_INT16:
				fSwapInput = &swap_int16;
				break;
			case B_AUDIO_FORMAT_INT24:
				fSwapInput = &swap_int24;
				break;
			case B_AUDIO_FORMAT_INT32:
				fSwapInput = &swap_int32;
				break;
			case B_AUDIO_FORMAT_FLOAT32:
				fSwapInput = &swap_float32;
				break;
			case B_AUDIO_FORMAT_FLOAT64:
				fSwapInput = &swap_float64;
				break;
			case B_AUDIO_FORMAT_UINT8:
			case B_AUDIO_FORMAT_INT8:
				fSwapInput = 0;
				break;
			default:
				debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n");
				break;
		}
	}

	// setup output swapping function
	if (ioDecodedFormat->u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) {
		fSwapOutput = 0;
	} else {
		switch (ioDecodedFormat->u.raw_audio.format) {
			case B_AUDIO_FORMAT_INT16:
				fSwapOutput = &swap_int16;
				break;
			case B_AUDIO_FORMAT_INT32:
				fSwapOutput = &swap_int32;
				break;
			case B_AUDIO_FORMAT_FLOAT32:
				fSwapOutput = &swap_float32;
				break;
			case B_AUDIO_FORMAT_UINT8:
			case B_AUDIO_FORMAT_INT8:
				fSwapOutput = 0;
				break;
			default:
				debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
				break;
		}
	}

	// setup sample conversation function
	switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
		case B_AUDIO_FORMAT_UINT8:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &uint8_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &uint8_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &uint8_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &uint8_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &uint8_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_INT8:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &int8_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &int8_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &int8_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &int8_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &int8_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_INT16:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &int16_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &int16_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &int16_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &int16_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &int16_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_INT24:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &int24_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &int24_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &int24_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &int24_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &int24_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_INT32:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &int32_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &int32_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &int32_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &int32_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &int32_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_FLOAT32:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &float32_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &float32_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &float32_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &float32_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &float32_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		case B_AUDIO_FORMAT_FLOAT64:
			switch (ioDecodedFormat->u.raw_audio.format) {
				case B_AUDIO_FORMAT_UINT8:
					fConvert = &float64_to_uint8;
					break;
				case B_AUDIO_FORMAT_INT8:
					fConvert = &float64_to_int8;
					break;
				case B_AUDIO_FORMAT_INT16:
					fConvert = &float64_to_int16;
					break;
				case B_AUDIO_FORMAT_INT32:
					fConvert = &float64_to_int32;
					break;
				case B_AUDIO_FORMAT_FLOAT32:
					fConvert = &float64_to_float32;
					break;
				default:
					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
					break;
			}
			break;

		default:
			debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n");
			break;
	}

	fChunkBuffer = 0;
	fChunkSize = 0;
	fStartTime = 0;

	string_for_format(*ioDecodedFormat, s, sizeof(s));
	TRACE("RawDecoder::NegotiateAudioOutputFormat leave: %s\n", s);

	if (ioDecodedFormat->type == 0)
		debugger("RawDecoder::NegotiateAudioOutputFormat ioDecodedFormat->type == 0");
/*
	TRACE("fFrameRate              %ld\n", fFrameRate);
	TRACE("fInputFrameSize         %ld\n", fInputFrameSize);
	TRACE("fOutputFrameSize        %ld\n", fOutputFrameSize);
	TRACE("fInputSampleSize        %ld\n", fInputSampleSize);
	TRACE("fOutputSampleSize       %ld\n", fOutputSampleSize);
	TRACE("fOutputBufferFrameCount %ld\n", fOutputBufferFrameCount);
	TRACE("fSwapInput              %p\n", fSwapInput);
	TRACE("fConvert                %p\n", fConvert);
	TRACE("fSwapOutput             %p\n", fSwapOutput);
*/
	return B_OK;
}
Example #5
0
status_t
AVFormatReader::Stream::Init(int32 virtualIndex)
{
	TRACE("AVFormatReader::Stream::Init(%ld)\n", virtualIndex);

	status_t ret = StreamBase::Init(virtualIndex);
	if (ret != B_OK)
		return ret;

	// Get a pointer to the AVCodecContext for the stream at streamIndex.
	AVCodecContext* codecContext = fStream->codec;

#if 0
// stippi: Here I was experimenting with the question if some fields of the
// AVCodecContext change (or get filled out at all), if the AVCodec is opened.
	class CodecOpener {
	public:
		CodecOpener(AVCodecContext* context)
		{
			fCodecContext = context;
			AVCodec* codec = avcodec_find_decoder(context->codec_id);
			fCodecOpen = avcodec_open(context, codec) >= 0;
			if (!fCodecOpen)
				TRACE("  failed to open the codec!\n");
		}
		~CodecOpener()
		{
			if (fCodecOpen)
				avcodec_close(fCodecContext);
		}
	private:
		AVCodecContext*		fCodecContext;
		bool				fCodecOpen;
	} codecOpener(codecContext);
#endif

	// initialize the media_format for this stream
	media_format* format = &fFormat;
	memset(format, 0, sizeof(media_format));

	media_format_description description;

	// Set format family and type depending on codec_type of the stream.
	switch (codecContext->codec_type) {
		case AVMEDIA_TYPE_AUDIO:
			if ((codecContext->codec_id >= CODEC_ID_PCM_S16LE)
				&& (codecContext->codec_id <= CODEC_ID_PCM_U8)) {
				TRACE("  raw audio\n");
				format->type = B_MEDIA_RAW_AUDIO;
				description.family = B_ANY_FORMAT_FAMILY;
				// This will then apparently be handled by the (built into
				// BMediaTrack) RawDecoder.
			} else {
				TRACE("  encoded audio\n");
				format->type = B_MEDIA_ENCODED_AUDIO;
				description.family = B_MISC_FORMAT_FAMILY;
				description.u.misc.file_format = 'ffmp';
			}
			break;
		case AVMEDIA_TYPE_VIDEO:
			TRACE("  encoded video\n");
			format->type = B_MEDIA_ENCODED_VIDEO;
			description.family = B_MISC_FORMAT_FAMILY;
			description.u.misc.file_format = 'ffmp';
			break;
		default:
			TRACE("  unknown type\n");
			format->type = B_MEDIA_UNKNOWN_TYPE;
			return B_ERROR;
			break;
	}

	if (format->type == B_MEDIA_RAW_AUDIO) {
		// We cannot describe all raw-audio formats, some are unsupported.
		switch (codecContext->codec_id) {
			case CODEC_ID_PCM_S16LE:
				format->u.raw_audio.format
					= media_raw_audio_format::B_AUDIO_SHORT;
				format->u.raw_audio.byte_order
					= B_MEDIA_LITTLE_ENDIAN;
				break;
			case CODEC_ID_PCM_S16BE:
				format->u.raw_audio.format
					= media_raw_audio_format::B_AUDIO_SHORT;
				format->u.raw_audio.byte_order
					= B_MEDIA_BIG_ENDIAN;
				break;
			case CODEC_ID_PCM_U16LE:
//				format->u.raw_audio.format
//					= media_raw_audio_format::B_AUDIO_USHORT;
//				format->u.raw_audio.byte_order
//					= B_MEDIA_LITTLE_ENDIAN;
				return B_NOT_SUPPORTED;
				break;
			case CODEC_ID_PCM_U16BE:
//				format->u.raw_audio.format
//					= media_raw_audio_format::B_AUDIO_USHORT;
//				format->u.raw_audio.byte_order
//					= B_MEDIA_BIG_ENDIAN;
				return B_NOT_SUPPORTED;
				break;
			case CODEC_ID_PCM_S8:
				format->u.raw_audio.format
					= media_raw_audio_format::B_AUDIO_CHAR;
				break;
			case CODEC_ID_PCM_U8:
				format->u.raw_audio.format
					= media_raw_audio_format::B_AUDIO_UCHAR;
				break;
			default:
				return B_NOT_SUPPORTED;
				break;
		}
	} else {
		if (description.family == B_MISC_FORMAT_FAMILY)
			description.u.misc.codec = codecContext->codec_id;

		BMediaFormats formats;
		status_t status = formats.GetFormatFor(description, format);
		if (status < B_OK)
			TRACE("  formats.GetFormatFor() error: %s\n", strerror(status));

		format->user_data_type = B_CODEC_TYPE_INFO;
		*(uint32*)format->user_data = codecContext->codec_tag;
		format->user_data[4] = 0;
	}

	format->require_flags = 0;
	format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;

	switch (format->type) {
		case B_MEDIA_RAW_AUDIO:
			format->u.raw_audio.frame_rate = (float)codecContext->sample_rate;
			format->u.raw_audio.channel_count = codecContext->channels;
			format->u.raw_audio.channel_mask = codecContext->channel_layout;
			format->u.raw_audio.byte_order
				= avformat_to_beos_byte_order(codecContext->sample_fmt);
			format->u.raw_audio.format
				= avformat_to_beos_format(codecContext->sample_fmt);
			format->u.raw_audio.buffer_size = 0;

			// Read one packet and mark it for later re-use. (So our first
			// GetNextChunk() call does not read another packet.)
			if (_NextPacket(true) == B_OK) {
				TRACE("  successfully determined audio buffer size: %d\n",
					fPacket.size);
				format->u.raw_audio.buffer_size = fPacket.size;
			}
			break;

		case B_MEDIA_ENCODED_AUDIO:
			format->u.encoded_audio.bit_rate = codecContext->bit_rate;
			format->u.encoded_audio.frame_size = codecContext->frame_size;
			// Fill in some info about possible output format
			format->u.encoded_audio.output
				= media_multi_audio_format::wildcard;
			format->u.encoded_audio.output.frame_rate
				= (float)codecContext->sample_rate;
			// Channel layout bits match in Be API and FFmpeg.
			format->u.encoded_audio.output.channel_count
				= codecContext->channels;
			format->u.encoded_audio.multi_info.channel_mask
				= codecContext->channel_layout;
			format->u.encoded_audio.output.byte_order
				= avformat_to_beos_byte_order(codecContext->sample_fmt);
			format->u.encoded_audio.output.format
				= avformat_to_beos_format(codecContext->sample_fmt);
			if (codecContext->block_align > 0) {
				format->u.encoded_audio.output.buffer_size
					= codecContext->block_align;
			} else {
				format->u.encoded_audio.output.buffer_size
					= codecContext->frame_size * codecContext->channels
						* (format->u.encoded_audio.output.format
							& media_raw_audio_format::B_AUDIO_SIZE_MASK);
			}
			break;

		case B_MEDIA_ENCODED_VIDEO:
// TODO: Specifying any of these seems to throw off the format matching
// later on.
//			format->u.encoded_video.avg_bit_rate = codecContext->bit_rate;
//			format->u.encoded_video.max_bit_rate = codecContext->bit_rate
//				+ codecContext->bit_rate_tolerance;

//			format->u.encoded_video.encoding
//				= media_encoded_video_format::B_ANY;

//			format->u.encoded_video.frame_size = 1;
//			format->u.encoded_video.forward_history = 0;
//			format->u.encoded_video.backward_history = 0;

			format->u.encoded_video.output.field_rate = FrameRate();
			format->u.encoded_video.output.interlace = 1;

			format->u.encoded_video.output.first_active = 0;
			format->u.encoded_video.output.last_active
				= codecContext->height - 1;
				// TODO: Maybe libavformat actually provides that info
				// somewhere...
			format->u.encoded_video.output.orientation
				= B_VIDEO_TOP_LEFT_RIGHT;

			// Calculate the display aspect ratio
			AVRational displayAspectRatio;
		    if (codecContext->sample_aspect_ratio.num != 0) {
				av_reduce(&displayAspectRatio.num, &displayAspectRatio.den,
					codecContext->width
						* codecContext->sample_aspect_ratio.num,
					codecContext->height
						* codecContext->sample_aspect_ratio.den,
					1024 * 1024);
				TRACE("  pixel aspect ratio: %d/%d, "
					"display aspect ratio: %d/%d\n",
					codecContext->sample_aspect_ratio.num,
					codecContext->sample_aspect_ratio.den,
					displayAspectRatio.num, displayAspectRatio.den);
		    } else {
				av_reduce(&displayAspectRatio.num, &displayAspectRatio.den,
					codecContext->width, codecContext->height, 1024 * 1024);
				TRACE("  no display aspect ratio (%d/%d)\n",
					displayAspectRatio.num, displayAspectRatio.den);
		    }
			format->u.encoded_video.output.pixel_width_aspect
				= displayAspectRatio.num;
			format->u.encoded_video.output.pixel_height_aspect
				= displayAspectRatio.den;

			format->u.encoded_video.output.display.format
				= pixfmt_to_colorspace(codecContext->pix_fmt);
			format->u.encoded_video.output.display.line_width
				= codecContext->width;
			format->u.encoded_video.output.display.line_count
				= codecContext->height;
			TRACE("  width/height: %d/%d\n", codecContext->width,
				codecContext->height);
			format->u.encoded_video.output.display.bytes_per_row = 0;
			format->u.encoded_video.output.display.pixel_offset = 0;
			format->u.encoded_video.output.display.line_offset = 0;
			format->u.encoded_video.output.display.flags = 0; // TODO

			break;

		default:
			// This is an unknown format to us.
			break;
	}

	// Add the meta data, if any
	if (codecContext->extradata_size > 0) {
		format->SetMetaData(codecContext->extradata,
			codecContext->extradata_size);
		TRACE("  extradata: %p\n", format->MetaData());
	}

	TRACE("  extradata_size: %d\n", codecContext->extradata_size);
//	TRACE("  intra_matrix: %p\n", codecContext->intra_matrix);
//	TRACE("  inter_matrix: %p\n", codecContext->inter_matrix);
//	TRACE("  get_buffer(): %p\n", codecContext->get_buffer);
//	TRACE("  release_buffer(): %p\n", codecContext->release_buffer);

#ifdef TRACE_AVFORMAT_READER
	char formatString[512];
	if (string_for_format(*format, formatString, sizeof(formatString)))
		TRACE("  format: %s\n", formatString);

	uint32 encoding = format->Encoding();
	TRACE("  encoding '%.4s'\n", (char*)&encoding);
#endif

	return B_OK;
}
Example #6
0
status_t
AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
	size_t infoSize)
{
	if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO
		&& ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO)
		return B_ERROR;

	fIsAudio = (ioEncodedFormat->type == B_MEDIA_ENCODED_AUDIO);
	TRACE("[%c] AVCodecDecoder::Setup()\n", fIsAudio?('a'):('v'));

#ifdef TRACE_AV_CODEC
	char buffer[1024];
	string_for_format(*ioEncodedFormat, buffer, sizeof(buffer));
	TRACE("[%c]   input_format = %s\n", fIsAudio?('a'):('v'), buffer);
	TRACE("[%c]   infoSize = %ld\n", fIsAudio?('a'):('v'), infoSize);
	TRACE("[%c]   user_data_type = %08lx\n", fIsAudio?('a'):('v'),
		ioEncodedFormat->user_data_type);
	TRACE("[%c]   meta_data_size = %ld\n", fIsAudio?('a'):('v'),
		ioEncodedFormat->MetaDataSize());
#endif

	media_format_description description;
	if (BMediaFormats().GetCodeFor(*ioEncodedFormat,
			B_MISC_FORMAT_FAMILY, &description) == B_OK) {
		if (description.u.misc.file_format != 'ffmp')
			return B_NOT_SUPPORTED;
		fCodec = avcodec_find_decoder(static_cast<CodecID>(
			description.u.misc.codec));
		if (fCodec == NULL) {
			TRACE("  unable to find the correct FFmpeg "
				"decoder (id = %lu)\n", description.u.misc.codec);
			return B_ERROR;
		}
		TRACE("  found decoder %s\n", fCodec->name);

		const void* extraData = infoBuffer;
		fExtraDataSize = infoSize;
		if (description.family == B_WAV_FORMAT_FAMILY
				&& infoSize >= sizeof(wave_format_ex)) {
			TRACE("  trying to use wave_format_ex\n");
			// Special case extra data in B_WAV_FORMAT_FAMILY
			const wave_format_ex* waveFormatData
				= (const wave_format_ex*)infoBuffer;

			size_t waveFormatSize = infoSize;
			if (waveFormatData != NULL && waveFormatSize > 0) {
				fBlockAlign = waveFormatData->block_align;
				TRACE("  found block align: %d\n", fBlockAlign);
				fExtraDataSize = waveFormatData->extra_size;
				// skip the wave_format_ex from the extra data.
				extraData = waveFormatData + 1;
			}
		} else {
			if (fIsAudio) {
				fBlockAlign
					= ioEncodedFormat->u.encoded_audio.output
						.buffer_size;
				TRACE("  using buffer_size as block align: %d\n",
					fBlockAlign);
			}
		}
		if (extraData != NULL && fExtraDataSize > 0) {
			TRACE("AVCodecDecoder: extra data size %ld\n", infoSize);
			delete[] fExtraData;
			fExtraData = new(std::nothrow) char[fExtraDataSize];
			if (fExtraData != NULL)
				memcpy(fExtraData, infoBuffer, fExtraDataSize);
			else
				fExtraDataSize = 0;
		}

		fInputFormat = *ioEncodedFormat;
		return B_OK;
	} else {
		TRACE("AVCodecDecoder: BMediaFormats().GetCodeFor() failed.\n");
	}

	printf("AVCodecDecoder::Setup failed!\n");
	return B_ERROR;
}