📄 video4beos.cxx
字号:
/*
* video4beos.cxx
*
* Classes to support streaming video input (grabbing) and output.
*
* Portable Windows Library
*
* Copyright (c) 1993-2000 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): Yuri Kiryanov, ykiryanov at users.sourceforge.net
* Jac Goudsmit <jac@be.com>.
*
* $Log: video4beos.cxx,v $
* Revision 1.1 2006/06/29 04:18:41 joegenbaclor
* *** empty log message ***
*
* Revision 1.6 2005/08/09 09:08:13 rjongbloed
* Merged new video code from branch back to the trunk.
*
* Revision 1.5.6.1 2005/07/17 09:27:08 rjongbloed
* Major revisions of the PWLib video subsystem including:
* removal of F suffix on colour formats for vertical flipping, all done with existing bool
* working through use of RGB and BGR formats so now consistent
* cleaning up the plug in system to use virtuals instead of pointers to functions.
* rewrite of SDL to be a plug in compatible video output device.
* extensive enhancement of video test program
*
* Revision 1.5 2004/06/16 01:55:47 ykiryanov
* Made video capture working
*
* Revision 1.4 2004/01/02 23:30:18 rjongbloed
* Removed extraneous static function for getting input device names that has been deprecated during the plug ins addition.
*
* Revision 1.3 2002/04/10 08:40:36 rogerh
* Simplify the SetVideoChannelFormat() code. Use the implementation in the
* ancestor class.
*
* Revision 1.2 2002/04/05 21:54:58 rogerh
* Add SetVideoChannelFormat - Reminded by Yuri
*
* Revision 1.1 2001/07/09 06:16:15 yurik
* Jac Goudsmit's BeOS changes of July,6th. Cleaning up media subsystem etc.
*
*
*/
#include <ptlib.h>
#include <ptlib/unix/ptlib/bevideo.h>
#include <stdio.h>
#include <fcntl.h>
#include <Buffer.h>
#include <unistd.h>
#include <string.h>
#include <NodeInfo.h>
#include <scheduler.h>
#include <TimeSource.h>
#include <MediaRoster.h>
#include <Application.h>
#include <BufferGroup.h>
#include <Bitmap.h>
#include <MediaNode.h>
#include <BufferConsumer.h>
#include <TimedEventQueue.h>
#include <MediaEventLooper.h>
// Define default trace level
#define TL 7
///////////////////////////////////////////////////////////////////////////////
// VideoConsumer
class VideoConsumer :
public BMediaEventLooper,
public BBufferConsumer
{
public:
VideoConsumer(
const char * name,
BMediaAddOn *addon,
const uint32 internal_id,
int XSize,
int YSize);
~VideoConsumer();
// BMediaNode
public:
virtual BMediaAddOn *AddOn(long *cookie) const;
protected:
virtual void Start(bigtime_t performance_time);
virtual void Stop(bigtime_t performance_time, bool immediate);
virtual void Seek(bigtime_t media_time, bigtime_t performance_time);
virtual void TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time);
virtual void NodeRegistered();
virtual status_t RequestCompleted(
const media_request_info & info);
virtual status_t DeleteHook(BMediaNode * node);
// BMediaEventLooper
protected:
virtual void HandleEvent(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent);
// BBufferConsumer
public:
virtual status_t AcceptFormat(
const media_destination &dest,
media_format * format);
virtual status_t GetNextInput(
int32 * cookie,
media_input * out_input);
virtual void DisposeInputCookie(
int32 cookie);
protected:
virtual void BufferReceived(
BBuffer * buffer);
private:
virtual void ProducerDataStatus(
const media_destination &for_whom,
int32 status,
bigtime_t at_media_time);
virtual status_t GetLatencyFor(
const media_destination &for_whom,
bigtime_t * out_latency,
media_node_id * out_id);
virtual status_t Connected(
const media_source &producer,
const media_destination &where,
const media_format & with_format,
media_input * out_input);
virtual void Disconnected(
const media_source &producer,
const media_destination &where);
virtual status_t FormatChanged(
const media_source & producer,
const media_destination & consumer,
int32 from_change_count,
const media_format & format);
// implementation
public:
status_t CreateBuffers(
const media_format & with_format);
void DeleteBuffers();
PMutex mFrameMutex;
void GetFrame(BYTE* buffer, PINDEX* bytesReturned,
PColourConverter* converter);
private:
uint32 mInternalID;
BMediaAddOn* mAddOn;
media_input mIn;
media_destination mDestination;
bigtime_t mMyLatency;
BBitmap* mFrames[3];
bool mOurBuffers;
BBufferGroup* mBuffers;
uint32 mBufferMap[3];
int mXSize;
int mYSize;
};
const media_raw_video_format vid_format =
{ 29.97,1,0,175, // YK
B_VIDEO_TOP_LEFT_RIGHT,1,1,
{B_RGB32,
176,144,176*4, // YK
0,0}};
VideoConsumer::VideoConsumer(
const char * name,
BMediaAddOn *addon,
const uint32 internal_id,
int XSize,
int YSize
) :
BMediaNode(name),
BMediaEventLooper(),
BBufferConsumer(B_MEDIA_RAW_VIDEO),
mInternalID(internal_id),
mAddOn(addon),
mMyLatency(20000),
mOurBuffers(false),
mBuffers(NULL),
mXSize(XSize),
mYSize(YSize)
{
PTRACE(TL, "VideoConsumer::VideoConsumer");
AddNodeKind(B_PHYSICAL_OUTPUT);
SetEventLatency(0);
for (uint32 j = 0; j < 3; j++)
{
mFrames[j] = NULL;
mBufferMap[j] = 0;
}
SetPriority(B_LOW_PRIORITY);
}
VideoConsumer::~VideoConsumer()
{
PTRACE(TL, "VideoConsumer::~VideoConsumer");
Quit();
DeleteBuffers();
}
// From BMediaNode
BMediaAddOn *
VideoConsumer::AddOn(long *cookie) const
{
PTRACE(3, "VideoConsumer::AddOn");
// do the right thing if we're ever used with an add-on
*cookie = mInternalID;
return mAddOn;
}
void
VideoConsumer::Start(bigtime_t performance_time)
{
BMediaEventLooper::Start(performance_time);
}
void
VideoConsumer::Stop(bigtime_t performance_time, bool immediate)
{
BMediaEventLooper::Stop(performance_time, immediate);
}
void
VideoConsumer::Seek(bigtime_t media_time, bigtime_t performance_time)
{
BMediaEventLooper::Seek(media_time, performance_time);
}
void
VideoConsumer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
{
BMediaEventLooper::TimeWarp(at_real_time, to_performance_time);
}
status_t
VideoConsumer::DeleteHook(BMediaNode *node)
{
return BMediaEventLooper::DeleteHook(node);
}
void
VideoConsumer::NodeRegistered()
{
PTRACE(TL, "VideoConsumer::NodeRegistered");
mIn.destination.port = ControlPort();
mIn.destination.id = 0;
mIn.source = media_source::null;
mIn.format.type = B_MEDIA_RAW_VIDEO;
mIn.format.u.raw_video = vid_format;
mIn.format.u.raw_video.display.line_width = mXSize;
mIn.format.u.raw_video.display.line_count = mYSize;
mIn.format.u.raw_video.display.bytes_per_row = mXSize * 4; // RGB32 only
Run();
}
status_t
VideoConsumer::RequestCompleted(const media_request_info & info)
{
PTRACE(TL, "VideoConsumer::RequestCompleted");
switch(info.what)
{
case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
{
if (info.status != B_OK)
PTRACE(1, "VideoConsumer::RequestCompleted: Not using our buffers!");
}
break;
case media_request_info::B_SET_VIDEO_CLIPPING_FOR:
case media_request_info::B_REQUEST_FORMAT_CHANGE:
case media_request_info::B_SET_OUTPUT_ENABLED:
case media_request_info::B_FORMAT_CHANGED:
default:
break;
}
return B_OK;
}
void
VideoConsumer::BufferReceived(BBuffer * buffer)
{
PTRACE(TL, "VideoConsumer::Buffer " << buffer->ID() << " received");
if (RunState() == B_STOPPED)
{
buffer->Recycle();
return;
}
media_timed_event event(buffer->Header()->start_time,
BTimedEventQueue::B_HANDLE_BUFFER,
buffer,
BTimedEventQueue::B_RECYCLE_BUFFER);
EventQueue()->AddEvent(event);
}
void
VideoConsumer::ProducerDataStatus(
const media_destination &for_whom,
int32 status,
bigtime_t at_media_time)
{
PTRACE(TL, "VideoConsumer::ProducerDataStatus");
if (for_whom != mIn.destination)
return;
}
status_t
VideoConsumer::CreateBuffers(
const media_format & with_format)
{
PTRACE(TL, "VideoConsumer::CreateBuffers");
// delete any old buffers
DeleteBuffers();
status_t status = B_OK;
// create a buffer group
mBuffers = new BBufferGroup();
status = mBuffers->InitCheck();
if (B_OK != status)
{
PTRACE(TL, "VideoConsumer::CreateBuffers - error while creating buffer group");
return status;
}
uint32 XSize = with_format.u.raw_video.display.line_width;
uint32 YSize = with_format.u.raw_video.display.line_count;
color_space mColorspace = with_format.u.raw_video.display.format;
PTRACE(TL, "VideoConsumer::CreateBuffers - Colorspace = " << (unsigned) mColorspace);
// and attach the bitmaps to the buffer group
for (uint32 j=0; j < 3; j++)
{
mFrames[j] = new BBitmap(BRect(0, 0, (XSize-1), (YSize - 1)), mColorspace, false, true);
if (mFrames[j]->IsValid())
{
buffer_clone_info info;
if ((info.area = area_for(mFrames[j]->Bits())) == B_ERROR)
PTRACE(1, "VideoConsumer::CreateBuffers - error in area");
info.offset = 0;
info.size = (size_t) mFrames[j]->BitsLength();
info.flags = j;
info.buffer = 0;
if ((status = mBuffers->AddBuffer(info)) != B_OK)
{
PTRACE(1, "VideoConsumer::CreateBuffers - error adding buffer to group");
return status;
} // if status
else
{
PTRACE(1, "VideoConsumer::CreateBuffers - successfully added buffer to group");
}
} // if bitmap is valid
else
{
PTRACE(1,
"VideoConsumer::CreateBuffers - error creating ring buffer, status " << status);
return B_ERROR;
} // bitmap is not valid
} // for loop
BBuffer ** buffList = new BBuffer * [3];
for (int j = 0; j < 3; j++) buffList[j] = 0;
if ((status = mBuffers->GetBufferList(3, buffList)) == B_OK)
{
for (int j = 0; j < 3; j++)
{
if (buffList[j] != NULL)
{
mBufferMap[j] = (uint32) buffList[j];
PTRACE(TL, " j = " << j << " buffer = " << mBufferMap[j]);
}
else
{
PTRACE(1, "VideoConsumer::CreateBuffers - error mapping ring buffer");
return B_ERROR;
} // else buflist
} // end for
} // if status
else
PTRACE(1, "VideoConsumer::CreateBuffers - error in get buffer list");
PTRACE(TL, "VideoConsumer::CreateBuffers - exit");
return status;
}
void
VideoConsumer::DeleteBuffers()
{
PTRACE(TL, "VideoConsumer::DeleteBuffers");
if (mBuffers)
{
delete mBuffers;
mBuffers = NULL;
for (uint32 j = 0; j < 3; j++)
{
if (mFrames[j]->IsValid())
{
delete mFrames[j];
mFrames[j] = NULL;
} // if bitmap
} // for
} // if buffers
PTRACE(TL, "VideoConsumer::DeleteBuffers - exit");
}
status_t
VideoConsumer::Connected(
const media_source & producer,
const media_destination & where,
const media_format & with_format,
media_input * out_input)
{
PTRACE(TL, "VideoConsumer::Connected");
mIn.source = producer;
mIn.format = with_format;
mIn.node = Node();
sprintf(mIn.name, "PWLV");
*out_input = mIn;
uint32 user_data = 0;
int32 change_tag = 1;
if (CreateBuffers(with_format) == B_OK)
{
BBufferConsumer::SetOutputBuffersFor(producer, mDestination,
mBuffers, (void *)&user_data, &change_tag, true);
}
else
{
PTRACE(1, "VideoConsumer::Connected - can't create buffers");
return B_ERROR;
}
PTRACE(TL, "VideoConsumer::Connected - exit");
return B_OK;
}
void
VideoConsumer::Disconnected(
const media_source & producer,
const media_destination & where)
{
PTRACE(TL, "VideoConsumer::Disconnected");
if (where == mIn.destination && producer == mIn.source)
{
// disconnect the connection
mIn.source = media_source::null;
}
}
//---------------------------------------------------------------
status_t
VideoConsumer::AcceptFormat(
const media_destination & dest,
media_format * format)
{
PTRACE(TL, "VideoConsumer::AcceptFormat") ;
if (dest != mIn.destination)
{
PTRACE(1, "VideoConsumer::AcceptFormat - bad destination");
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)
{
PTRACE(1, "VideoConsumer::AcceptFormat - bad format");
return B_MEDIA_BAD_FORMAT;
}
if (format->u.raw_video.display.format != B_RGB32 &&
format->u.raw_video.display.format != media_raw_video_format::wildcard.display.format)
{
PTRACE(1, "AcceptFormat - not a RGB32 format!");
return B_MEDIA_BAD_FORMAT;
}
if (format->u.raw_video.display.format == media_raw_video_format::wildcard.display.format)
{
format->u.raw_video.display.format = B_RGB32;
}
char format_string[256];
string_for_format(*format, format_string, 256);
PTRACE(TL, "VideoConsumer::AcceptFormat: " << format_string);
return B_OK;
}
status_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -