📄 video4beos.cxx
字号:
VideoConsumer::GetNextInput(
int32 * cookie,
media_input * out_input)
{
PTRACE(TL, "VideoConsumer::GetNextInput");
// custom build a destination for this connection
// put connection number in id
if (*cookie < 1)
{
mIn.node = Node();
mIn.destination.id = *cookie;
sprintf(mIn.name, "PWLV");
*out_input = mIn;
(*cookie)++;
return B_OK;
}
else
{
PTRACE(1, "VideoConsumer::GetNextInput - bad index");
return B_MEDIA_BAD_DESTINATION;
}
}
void
VideoConsumer::DisposeInputCookie(int32 /*cookie*/)
{
}
status_t
VideoConsumer::GetLatencyFor(
const media_destination &for_whom,
bigtime_t * out_latency,
media_node_id * out_timesource)
{
PTRACE(TL, "VideoConsumer::GetLatencyFor");
if (for_whom != mIn.destination)
return B_MEDIA_BAD_DESTINATION;
*out_latency = mMyLatency;
*out_timesource = TimeSource()->ID();
return B_OK;
}
status_t
VideoConsumer::FormatChanged(
const media_source & producer,
const media_destination & consumer,
int32 from_change_count,
const media_format &format)
{
PTRACE(TL, "VideoConsumer::FormatChanged");
if (consumer != mIn.destination)
return B_MEDIA_BAD_DESTINATION;
if (producer != mIn.source)
return B_MEDIA_BAD_SOURCE;
mIn.format = format;
return CreateBuffers(format);
}
void
VideoConsumer::HandleEvent(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent)
{
PTRACE(TL, "VideoConsumer::HandleEvent");
BBuffer *buffer;
switch (event->type)
{
case BTimedEventQueue::B_START:
PTRACE(TL, "VideoConsumer::HandleEvent - start");
break;
case BTimedEventQueue::B_STOP:
PTRACE(TL, "VideoConsumer::HandleEvent - stop");
EventQueue()->FlushEvents(event->event_time,
BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
break;
case BTimedEventQueue::B_HANDLE_BUFFER:
PTRACE(TL, "VideoConsumer::HandleEvent - handle buffer");
buffer = (BBuffer *) event->pointer;
if (RunState() == B_STARTED)
{
// see if this is one of our buffers
uint32 index = 0;
mOurBuffers = true;
while(index < 3)
if ((uint32)buffer == mBufferMap[index])
break;
else
index++;
if (index == 3)
{
// no, buffers belong to consumer
mOurBuffers = false;
index = 0;
}
PWaitAndSignal ws(mFrameMutex);
memcpy(mFrames[index]->Bits(), buffer->Data(), mFrames[index]->BitsLength());
}
else
buffer->Recycle();
break;
default:
PTRACE(1, "VideoConsumer::HandleEvent - bad event");
break;
}
}
void VideoConsumer::GetFrame(BYTE* buffer,
PINDEX* bytesReturned,
PColourConverter* converter)
{
PAssertNULL(bytesReturned);
PWaitAndSignal ws(mFrameMutex);
{
const BYTE* frame = (const BYTE*) mFrames[0]->Bits();
if (converter != NULL)
{
converter->Convert(frame, buffer, bytesReturned);
}
else
{
memcpy(buffer, frame, *bytesReturned);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// PVideoDevice
PVideoInputDevice_BeOSVideo::PVideoInputDevice_BeOSVideo()
: captureThread(NULL)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo");
captureThread = NULL;
isCapturingNow = FALSE;
}
BOOL PVideoInputDevice_BeOSVideo::Open(const PString & devName, BOOL startImmediate)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::Open");
Close();
frameWidth = CIFWidth;
frameHeight = CIFHeight;
colourFormat = "RGB32";
deviceName = devName;
if (startImmediate)
return Start();
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::IsOpen()
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::IsOpen");
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::Close()
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::Close");
if (!IsOpen())
return FALSE;
Stop();
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::Start()
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::Start");
if (IsCapturing())
return TRUE;
StartNodes();
isCapturingNow = TRUE;
return isCapturingNow;
}
BOOL PVideoInputDevice_BeOSVideo::Stop()
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::Stop");
if (!IsCapturing())
return FALSE;
StopNodes();
::snooze(100000);
isCapturingNow = FALSE;
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::IsCapturing()
{
return isCapturingNow;
}
BOOL PVideoInputDevice_BeOSVideo::TestAllFormats()
{
BOOL running = IsCapturing();
if (running)
Stop();
if (running)
return Start();
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::SetFrameRate(unsigned rate)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::SetFrameRate");
if (!PVideoDevice::SetFrameRate(rate))
return FALSE;
BOOL running = IsCapturing();
if (running)
Stop();
if (running)
return Start();
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::SetFrameSize(unsigned width, unsigned height)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::SetFrameSize, width " << width << " height " << height);
BOOL running = IsCapturing();
if (running)
Stop();
if (!PVideoDevice::SetFrameSize(width, height))
return FALSE;
if (running)
return Start();
return TRUE;
}
BOOL PVideoInputDevice_BeOSVideo::SetColourFormat(const PString & colourFmt)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::SetColourFormat, format" << colourFmt);
BOOL running = IsCapturing();
if (running)
Stop();
if (!PVideoDevice::SetColourFormat(colourFmt)) {
return FALSE;
}
converter = PColourConverter::Create("RGB32", colourFormat, frameWidth, frameHeight);
if (converter == NULL) {
PTRACE(1, "Failed to make a converter.");
return FALSE;
}
// if (converter->SetSrcFrameSize(width,height) == FALSE) {
// PTRACE(1, "Failed to set source frame size of a converter.");
// return FALSE;
// }
// if (converter->SetDstFrameSize(desiredFrameWidth, desiredFrameHeight, FALSE) == FALSE) {
// PTRACE(1, "Failed to set destination frame size (+scaling) of a converter.");
// return FALSE;
// }
if (running)
return Start();
return TRUE;
}
PStringList PVideoInputDevice_BeOSVideo::GetInputDeviceNames()
{
PStringList list;
list.AppendString("MediaKit");
return list;
}
PINDEX PVideoInputDevice_BeOSVideo::GetMaxFrameBytes()
{
if (!IsOpen())
return 0;
return GetMaxFrameBytesConverted(frameWidth * frameHeight *4); // RGB32 only
}
BOOL PVideoInputDevice_BeOSVideo::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
{
return GetFrameDataNoDelay(buffer, bytesReturned);
}
BOOL PVideoInputDevice_BeOSVideo::GetFrameDataNoDelay(BYTE * buffer, PINDEX * bytesReturned)
{
PTRACE(TL, "PVideoInputDevice_BeOSVideo::GetFrameDataNoDelay");
if (!IsCapturing())
return FALSE;
*bytesReturned = GetMaxFrameBytes();
fVideoConsumer->GetFrame(buffer, bytesReturned, converter);
return TRUE;
}
status_t PVideoInputDevice_BeOSVideo::StartNodes()
{
PTRACE(TL, "StartNodes!");
status_t status = B_OK;
// find the media roster
fMediaRoster = BMediaRoster::Roster(&status);
if (status != B_OK)
{
PTRACE(3, "Can't find the media roster, status " << status);
return status;
}
// find the time source
status = fMediaRoster->GetTimeSource(&fTimeSourceNode);
if (status != B_OK)
{
PTRACE(3, "Can't get a time source, status " << status);
return status;
}
// find a video producer node
PTRACE(3, "PVideoInputDevice_BeOSVideo acquiring video input node");
status = fMediaRoster->GetVideoInput(&fProducerNode);
if (status != B_OK)
{
PTRACE(3, "Can't find a video input!, status " << status);
return status;
}
// create the video consumer node
fVideoConsumer = new VideoConsumer("PWLV", NULL, 0, frameWidth, frameHeight);
if (!fVideoConsumer)
{
PTRACE(3, "Can't create a video consumer");
return B_ERROR;
}
// register the node
status = fMediaRoster->RegisterNode(fVideoConsumer);
if (status != B_OK)
{
PTRACE(3, "Can't register the video consumer, status " << status);
return status;
}
fPort = fVideoConsumer->ControlPort();
// find free producer output
int32 cnt = 0;
status = fMediaRoster->GetFreeOutputsFor(fProducerNode,
&fProducerOut, 1, &cnt, B_MEDIA_RAW_VIDEO);
if (status != B_OK || cnt < 1)
{
status = B_RESOURCE_UNAVAILABLE;
PTRACE(3, "Can't find an available video stream, status " << status);
return status;
}
// find free consumer input
cnt = 0;
status = fMediaRoster->GetFreeInputsFor(fVideoConsumer->Node(),
&fConsumerIn, 1, &cnt, B_MEDIA_RAW_VIDEO);
if (status != B_OK || cnt < 1)
{
status = B_RESOURCE_UNAVAILABLE;
PTRACE(3,
"Can't find an available connection to the video consumer, status " << status);
return status;
}
// Connect The Nodes!!!
media_format format;
format.type = B_MEDIA_RAW_VIDEO;
media_raw_video_format vid_format =
{ 0, 1, 0, 175, // YK
B_VIDEO_TOP_LEFT_RIGHT, 1, 1,
{B_RGB32, 0, 0, 0, 0, 0}};
vid_format.display.line_width = frameWidth;
vid_format.display.line_count = frameHeight;
vid_format.display.bytes_per_row = frameWidth * 4; // RGB32 only
format.u.raw_video = vid_format;
// connect producer to consumer
status = fMediaRoster->Connect(fProducerOut.source, fConsumerIn.destination,
&format, &fProducerOut, &fConsumerIn);
if (status != B_OK)
{
PTRACE(3, "Can't connect the video source to the video consumer, status " << status);
return status;
}
// set time sources
status = fMediaRoster->SetTimeSourceFor(fProducerNode.node, fTimeSourceNode.node);
if (status != B_OK)
{
PTRACE(3, "Can't set the timesource for the video source, status " << status);
return status;
}
status = fMediaRoster->SetTimeSourceFor(fVideoConsumer->ID(), fTimeSourceNode.node);
if (status != B_OK)
{
PTRACE(3, "Can't set the timesource for the video consumer, status " << status);
return status;
}
// figure out what recording delay to use
bigtime_t latency = 0;
status = fMediaRoster->GetLatencyFor(fProducerNode, &latency);
status = fMediaRoster->SetProducerRunModeDelay(fProducerNode, latency);
// start the nodes
bigtime_t initLatency = 0;
status = fMediaRoster->GetInitialLatencyFor(fProducerNode, &initLatency);
if (status < B_OK)
{
PTRACE(3, "error getting initial latency for fCaptureNode, status " << status);
}
initLatency += estimate_max_scheduling_latency();
BTimeSource *timeSource = fMediaRoster->MakeTimeSourceFor(fProducerNode);
bool running = timeSource->IsRunning();
// workaround for people without sound cards
// because the system time source won't be running
bigtime_t real = BTimeSource::RealTime();
if (!running)
{
status = fMediaRoster->StartTimeSource(fTimeSourceNode, real);
if (status != B_OK)
{
timeSource->Release();
PTRACE(3, "Cannot start time source!, status" << status);
return status;
}
status = fMediaRoster->SeekTimeSource(fTimeSourceNode, 0, real);
if (status != B_OK)
{
timeSource->Release();
PTRACE(3, "Cannot seek time source!, status " << status);
return status;
}
}
bigtime_t perf = timeSource->PerformanceTimeFor(real + latency + initLatency);
timeSource->Release();
// start the nodes
status = fMediaRoster->StartNode(fProducerNode, perf);
if (status != B_OK)
{
PTRACE(3, "Can't start the video source, status " << status);
return status;
}
status = fMediaRoster->StartNode(fVideoConsumer->Node(), perf);
if (status != B_OK)
{
PTRACE(3, "Can't start the video consumer, status " << status);
return status;
}
return status;
}
void PVideoInputDevice_BeOSVideo::StopNodes()
{
PTRACE(TL, "StopNodes");
if (!fMediaRoster)
return;
if (fVideoConsumer)
{
// stop
PTRACE(TL, "Stopping nodes!");
fMediaRoster->StopNode(fProducerNode, 0, true);
fMediaRoster->StopNode(fVideoConsumer->Node(), 0, true);
// disconnect
fMediaRoster->Disconnect(
fProducerOut.node.node, fProducerOut.source,
fConsumerIn.node.node, fConsumerIn.destination);
if(fProducerNode != media_node::null)
{
PTRACE(TL, "Releasing fProducerNode");
fMediaRoster->ReleaseNode(fProducerNode);
fProducerNode = media_node::null;
}
fMediaRoster->ReleaseNode(fVideoConsumer->Node());
fVideoConsumer = NULL;
} // if video consumer
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -