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; }
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; }