status_t
VideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
{
	FUNCTION("VideoConsumer::AcceptFormat\n");
	
	if (dest != fIn.destination) {
		ERROR("VideoConsumer::AcceptFormat - BAD DESTINATION\n");
		return B_MEDIA_BAD_DESTINATION;	
	}
	
	if (format->type == B_MEDIA_NO_TYPE)
		format->type = B_MEDIA_RAW_VIDEO;
	
	if (format->type != B_MEDIA_RAW_VIDEO) {
		ERROR("VideoConsumer::AcceptFormat - BAD FORMAT\n");
		return B_MEDIA_BAD_FORMAT;
	}

	if (format->u.raw_video.display.format
			!= media_raw_video_format::wildcard.display.format) {
		uint32 flags = 0;
		bool supported = bitmaps_support_space(
			format->u.raw_video.display.format, &flags);
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
		// GRRR! BeOS implementation claims not
		// to support these formats, while they work just fine.
		switch (format->u.raw_video.display.format) {
			case B_YCbCr422:
			case B_YCbCr411:
			case B_YCbCr444:
			case B_YCbCr420:
				supported = true;
				break;
			default:
				break;
		}
#endif
		if (!supported) {
			// cannot create bitmaps with such a color space
			ERROR("AcceptFormat - unsupported color space for BBitmaps "
				"(%s)!\n",
				color_space_to_string(format->u.raw_video.display.format));
			return B_MEDIA_BAD_FORMAT;
		}
		if (!fTryOverlay && (flags & B_VIEWS_SUPPORT_DRAW_BITMAP) == 0) {
			// BViews do not support drawing such a bitmap
			ERROR("AcceptFormat - BViews cannot draw bitmaps in given "
				"colorspace (%s)!\n",
				color_space_to_string(format->u.raw_video.display.format));
			return B_MEDIA_BAD_FORMAT;
		}
	}

	#ifdef TRACE_VIDEO_CONSUMER
		char string[256];
		string[0] = 0;
		string_for_format(*format, string, 256);
		FUNCTION("VideoConsumer::AcceptFormat: %s\n", string);
	#endif

	return B_OK;
}
Пример #2
0
status_t
NodeManager::_SetUpVideoNodes(color_space preferredVideoFormat,
	bool useOverlays)
{
	// create the video producer node
	fVideoProducer = new VideoProducer(NULL, "MediaPlayer video out", 0,
		this, fVideoSupplier);

	// register the producer node
	fStatus = fMediaRoster->RegisterNode(fVideoProducer);
	if (fStatus != B_OK) {
		print_error("Can't register the video producer", fStatus);
		return fStatus;
	}

	// make sure the Media Roster knows that we're using the node
//	fMediaRoster->GetNodeFor(fVideoProducer->Node().node,
//		&fVideoConnection.producer);
	fVideoConnection.producer = fVideoProducer->Node();

	// create the video consumer node
	fVideoConsumer = new VideoConsumer("MediaPlayer video in", NULL, 0, this,
		fVideoTarget);

	// register the consumer node
	fStatus = fMediaRoster->RegisterNode(fVideoConsumer);
	if (fStatus != B_OK) {
		print_error("Can't register the video consumer", fStatus);
		return fStatus;
	}

	// make sure the Media Roster knows that we're using the node
//	fMediaRoster->GetNodeFor(fVideoConsumer->Node().node,
//		&fVideoConnection.consumer);
	fVideoConnection.consumer = fVideoConsumer->Node();

	// find free producer output
	media_input videoInput;
	media_output videoOutput;
	int32 count = 1;
	fStatus = fMediaRoster->GetFreeOutputsFor(fVideoConnection.producer,
		&videoOutput, 1, &count, B_MEDIA_RAW_VIDEO);
	if (fStatus != B_OK || count < 1) {
		fStatus = B_RESOURCE_UNAVAILABLE;
		print_error("Can't find an available video stream", fStatus);
		return fStatus;
	}

	// find free consumer input
	count = 1;
	fStatus = fMediaRoster->GetFreeInputsFor(fVideoConnection.consumer,
		&videoInput, 1, &count, B_MEDIA_RAW_VIDEO);
	if (fStatus != B_OK || count < 1) {
		fStatus = B_RESOURCE_UNAVAILABLE;
		print_error("Can't find an available connection to the video window",
			fStatus);
		return fStatus;
	}

	// connect the nodes
	media_format format;
	format.type = B_MEDIA_RAW_VIDEO;
	media_raw_video_format videoFormat = {
		FramesPerSecond(), 1, 0,
		(uint32)fVideoBounds.IntegerWidth(),
		B_VIDEO_TOP_LEFT_RIGHT, 1, 1,
		{
			preferredVideoFormat,
			(uint32)(fVideoBounds.IntegerWidth() + 1),
			(uint32)(fVideoBounds.IntegerHeight() + 1),
			0, 0, 0
		}
	};
	format.u.raw_video = videoFormat;

	// connect video producer to consumer (hopefully using overlays)
	fVideoConsumer->SetTryOverlay(useOverlays);
	fStatus = fMediaRoster->Connect(videoOutput.source, videoInput.destination,
		&format, &videoOutput, &videoInput);

	if (fStatus != B_OK) {
		print_error("Can't connect the video source to the video window... "
			"trying without overlays", fStatus);

		uint32 flags = 0;
		bool supported = bitmaps_support_space(
			format.u.raw_video.display.format, &flags);
		if (!supported || (flags & B_VIEWS_SUPPORT_DRAW_BITMAP) == 0) {
			// cannot create bitmaps with such a color space
			// or BViews don't support drawing it, fallback to B_RGB32
			format.u.raw_video.display.format = B_RGB32;
			printf("NodeManager::_SetupVideoNodes() - falling back to "
				"B_RGB32\n");
		}

		fVideoConsumer->SetTryOverlay(false);
		// connect video producer to consumer (not using overlays and using
		// a colorspace that BViews support drawing)
		fStatus = fMediaRoster->Connect(videoOutput.source,
			videoInput.destination, &format, &videoOutput, &videoInput);
	}
	// bail if second attempt failed too
	if (fStatus != B_OK) {
		print_error("Can't connect the video source to the video window",
			fStatus);
		return fStatus;
	}

	// the inputs and outputs might have been reassigned during the
	// nodes' negotiation of the Connect().  That's why we wait until
	// after Connect() finishes to save their contents.
	fVideoConnection.format = format;
	fVideoConnection.source = videoOutput.source;
	fVideoConnection.destination = videoInput.destination;
	fVideoConnection.connected = true;

	// set time sources
	fStatus = fMediaRoster->SetTimeSourceFor(fVideoConnection.producer.node,
		fTimeSource.node);
	if (fStatus != B_OK) {
		print_error("Can't set the timesource for the video source", fStatus);
		return fStatus;
	}

	fStatus = fMediaRoster->SetTimeSourceFor(fVideoConsumer->ID(),
		fTimeSource.node);
	if (fStatus != B_OK) {
		print_error("Can't set the timesource for the video window", fStatus);
		return fStatus;
	}

	return fStatus;
}