- Compile fix/Added missing files

- Implemented missing functionality
- Added debug.h from other media addons for nicer debug.
- Instead of using the MediaNode inside the View, the node should control the view and the window in the case it is instantiated from an addon.
- During the connection process the VideoNode tried to allocate overlay buffers. This can fail for multiple reasons like there is already someone using overlay or it is not supported at all due to driver limitations. In that case try to get non overlay buffers. If this fails, the Connect() can still return an error.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24273 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Maurice Kalinowski 2008-03-06 17:43:41 +00:00
parent 9fb2c0f239
commit 72ac59d172
11 changed files with 313 additions and 90 deletions

View File

@ -14,4 +14,5 @@ SubInclude HAIKU_TOP src add-ons media media-add-ons tone_producer_demo ;
SubInclude HAIKU_TOP src add-ons media media-add-ons usb_vision ;
SubInclude HAIKU_TOP src add-ons media media-add-ons usb_webcam ;
SubInclude HAIKU_TOP src add-ons media media-add-ons video_producer_demo ;
SubInclude HAIKU_TOP src add-ons media media-add-ons videowindow ;

View File

@ -0,0 +1,9 @@
SubDir HAIKU_TOP src add-ons media media-add-ons videowindow ;
Addon video_window_demo.media_addon :
VideoAddOn.cpp
VideoNode.cpp
VideoView.cpp
VideoWindow.cpp
: be media
;

View File

@ -1,6 +1,102 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2006-2008 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "VideoAddOn.h"
#include "VideoNode.h"
#include "VideoView.h"
#include "debug.h"
#include <stdio.h>
#include <string.h>
VideoWindowAddOn::VideoWindowAddOn(image_id id)
: BMediaAddOn(id)
{
CALLED();
fInfo.internal_id = 0;
fInfo.name = strdup("VideoWindow Consumer");
fInfo.info = strdup("This node displays a simple video window");
fInfo.kinds = B_BUFFER_CONSUMER;
fInfo.flavor_flags = 0;
fInfo.possible_count = 0;
fInfo.in_format_count = 1;
media_format *inFormat = new media_format;
inFormat->type = B_MEDIA_RAW_VIDEO;
inFormat->u.raw_video = media_raw_video_format::wildcard;
fInfo.in_formats = inFormat;
}
VideoWindowAddOn::~VideoWindowAddOn()
{
}
bool
VideoWindowAddOn::WantsAutoStart()
{
CALLED();
return false;
}
int32
VideoWindowAddOn::CountFlavors()
{
CALLED();
return 1;
}
status_t
VideoWindowAddOn::GetFlavorAt(int32 cookie, const flavor_info **flavorInfo)
{
CALLED();
if (cookie != 0)
return B_BAD_INDEX;
if (!flavorInfo || !*flavorInfo)
return B_ERROR;
*flavorInfo = &fInfo;
return B_OK;
}
BMediaNode*
VideoWindowAddOn::InstantiateNodeFor(const flavor_info *info, BMessage*, status_t *outError)
{
CALLED();
if (!outError)
return NULL;
if (info->in_formats[0].type != B_MEDIA_RAW_VIDEO) {
*outError = B_MEDIA_BAD_FORMAT;
return NULL;
}
BRect size;
if (info->in_formats[0].u.raw_video.display.line_width != 0)
size.right = info->in_formats[0].u.raw_video.display.line_width;
else
size.right = 320;
if (info->in_formats[0].u.raw_video.display.line_count != 0)
size.bottom = info->in_formats[0].u.raw_video.display.line_count;
else
size.bottom = 240;
VideoNode* node = new VideoNode("Video Node", this, info->internal_id);
return node;
}
extern "C" BMediaAddOn *make_media_addon(image_id id)
{
return new VideoWindowAddOn(id);
}

View File

@ -1,18 +1,29 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2006-2008 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef __VIDEO_ADD_ON_H
#define __VIDEO_ADD_ON_H
#include <MediaAddOn.h>
class MediaAddOn : public BMediaAddOn
class VideoWindowAddOn : public BMediaAddOn
{
public:
VideoWindowAddOn(image_id);
~VideoWindowAddOn();
bool WantsAutoStart();
int32 CountFlavors();
status_t GetFlavorAt(int32, const flavor_info**);
BMediaNode* InstantiateNodeFor(const flavor_info*, BMessage*, status_t*);
private:
flavor_info fInfo;
};
extern "C" BMediaAddOn *make_media_addon(image_id id);

View File

@ -1,51 +1,78 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#include <string.h>
#include <Window.h>
#include <TimeSource.h>
#include <MediaRoster.h>
#include <BufferGroup.h>
#include <Buffer.h>
#include <Bitmap.h>
#include <Locker.h>
#include <Debug.h>
#include "VideoNode.h"
#include "VideoView.h"
#include "VideoWindow.h"
VideoNode::VideoNode(const char *name, VideoView *view)
#include <Bitmap.h>
#include <Buffer.h>
#include <BufferGroup.h>
#include <Debug.h>
#include <MediaRoster.h>
#include <Locker.h>
#include <TimeSource.h>
#include <Window.h>
#include <stdio.h>
#include <string.h>
VideoNode::VideoNode(const char *name)
: BMediaNode(name)
, BMediaEventLooper()
, BBufferConsumer(B_MEDIA_RAW_VIDEO)
, fVideoView(view)
, fWindow(0)
, fVideoView(0)
, fInput()
, fOverlayEnabled(true)
, fOverlayActive(false)
, fDirectOverlayBuffer(false)
, fBitmap(0)
, fBitmapLocker(new BLocker("Video Node Locker"))
, fAddOn(0)
, fInternalFlavorId(0)
{
_InitDisplay();
}
VideoNode::VideoNode(const char *name, BMediaAddOn* addon, int32 id)
: BMediaNode(name)
, BMediaEventLooper()
, BBufferConsumer(B_MEDIA_RAW_VIDEO)
, fWindow(0)
, fVideoView(0)
, fInput()
, fOverlayEnabled(true)
, fOverlayActive(false)
, fDirectOverlayBuffer(false)
, fBitmap(0)
, fBitmapLocker(new BLocker("Video Node Locker"))
, fAddOn(addon)
, fInternalFlavorId(id)
{
_InitDisplay();
}
VideoNode::~VideoNode()
{
Quit();
DeleteBuffers();
delete fBitmapLocker;
if (fWindow)
fWindow->Quit();
}
BMediaAddOn *
VideoNode::AddOn(int32 *internal_id) const
{
*internal_id = 0;
return NULL;
*internal_id = fInternalFlavorId;
return fAddOn;
}
@ -127,7 +154,7 @@ VideoNode::HandleEvent(const media_timed_event *event,
HandleBuffer((BBuffer *)event->pointer);
break;
default:
printf("VideoNode::HandleEvent unknown event");
fprintf(stderr, "VideoNode::HandleEvent unknown event");
break;
}
}
@ -149,12 +176,13 @@ VideoNode::GetLatencyFor(const media_destination &dst,
{
if (dst != fInput.destination)
return B_MEDIA_BAD_DESTINATION;
*out_latency = 10000;
*out_id = TimeSource()->ID();
return B_OK;
}
status_t
VideoNode::AcceptFormat(const media_destination &dst,
media_format *format)
@ -166,17 +194,15 @@ VideoNode::AcceptFormat(const media_destination &dst,
* BBufferConsumer::Connected
* BBufferProducer::Connect
*/
if (dst != fInput.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)
return B_MEDIA_BAD_FORMAT;
return B_OK;
}
@ -210,15 +236,19 @@ VideoNode::Connected(const media_source &src,
DeleteBuffers();
err = CreateBuffers(frame, colorspace, fOverlayEnabled);
if (err && fOverlayEnabled) {
SetOverlayEnabled(false);
err = CreateBuffers(frame, colorspace, fOverlayEnabled);
}
if (err) {
printf("VideoNode::Connected failed, fOverlayEnabled = %d\n", fOverlayEnabled);
fprintf(stderr, "VideoNode::Connected failed, fOverlayEnabled = %d\n", fOverlayEnabled);
return err;
}
*out_input = fInput;
return B_OK;
}
@ -244,7 +274,6 @@ VideoNode::FormatChanged(const media_source &src,
int32 from_change_count,
const media_format &format)
{
printf("VideoNode::FormatChanged enter\n");
if (src != fInput.source)
return B_MEDIA_BAD_SOURCE;
if (dst != fInput.destination)
@ -259,20 +288,20 @@ VideoNode::FormatChanged(const media_source &src,
fVideoView->RemoveOverlay();
err = CreateBuffers(frame, colorspace, true); // try overlay
if (err) {
printf("VideoNode::FormatChanged creating overlay buffer failed\n");
fprintf(stderr, "VideoNode::FormatChanged creating overlay buffer failed\n");
err = CreateBuffers(frame, colorspace, false); // no overlay
}
} else {
err = CreateBuffers(frame, colorspace, false); // no overlay
}
if (err) {
printf("VideoNode::FormatChanged failed (lost buffer group!)\n");
fprintf(stderr, "VideoNode::FormatChanged failed (lost buffer group!)\n");
return B_MEDIA_BAD_FORMAT;
}
fInput.format = format;
printf("VideoNode::FormatChanged leave\n");
return B_OK;
}
@ -280,10 +309,8 @@ VideoNode::FormatChanged(const media_source &src,
void
VideoNode::HandleBuffer(BBuffer *buffer)
{
// printf("VideoNode::HandleBuffer\n");
LockBitmap();
if (fBitmap) {
if (fBitmap && fWindow && fVideoView) {
// bigtime_t start = system_time();
if (fOverlayActive) {
if (B_OK == fBitmap->LockBits()) {
@ -341,8 +368,8 @@ VideoNode::IsOverlayActive()
status_t
VideoNode::CreateBuffers(BRect frame, color_space cspace, bool overlay)
{
printf("VideoNode::CreateBuffers: frame %d,%d,%d,%d colorspace 0x%08x, overlay %d\n",
int(frame.left), int(frame.top), int(frame.right), int(frame.bottom), int(cspace), overlay);
//printf("VideoNode::CreateBuffers: frame %d,%d,%d,%d colorspace 0x%08x, overlay %d\n",
// int(frame.left), int(frame.top), int(frame.right), int(frame.bottom), int(cspace), overlay);
LockBitmap();
ASSERT(fBitmap == 0);
@ -353,12 +380,12 @@ VideoNode::CreateBuffers(BRect frame, color_space cspace, bool overlay)
fBitmap = 0;
fOverlayActive = false;
UnlockBitmap();
printf("VideoNode::CreateBuffers failed\n");
fprintf(stderr, "VideoNode::CreateBuffers failed\n");
return B_ERROR;
}
fOverlayActive = overlay;
UnlockBitmap();
printf("VideoNode::CreateBuffers success\n");
return B_OK;
}
@ -371,3 +398,16 @@ VideoNode::DeleteBuffers()
fBitmap = NULL;
UnlockBitmap();
}
void
VideoNode::_InitDisplay()
{
// TODO: Get rid of hardcoded values
BRect size(0,0,320,240);
fVideoView = new VideoView(size, "Video View", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE, this);
size.OffsetBy(40.f, 40.f);
fWindow = new VideoWindow(size, fVideoView);
fWindow->Show();
}

View File

@ -1,25 +1,34 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef __VIDEO_NODE_H_
#define __VIDEO_NODE_H_
#include <BufferConsumer.h>
#include <MediaEventLooper.h>
class BBitmap;
class BLocker;
class BWindow;
class VideoView;
class VideoWindow;
class VideoNode : public BMediaEventLooper, public BBufferConsumer
{
public:
VideoNode(const char *name, VideoView *view);
VideoNode(const char *name);
VideoNode(const char *name, BMediaAddOn* addon, int32 id);
~VideoNode();
void SetOverlayEnabled(bool yesno);
bool IsOverlayActive();
void LockBitmap();
BBitmap * Bitmap();
void UnlockBitmap();
@ -52,7 +61,7 @@ protected:
const media_destination &dst,
int32 status,
bigtime_t at_media_time);
status_t GetLatencyFor(
const media_destination &dst,
bigtime_t *out_latency,
@ -74,12 +83,13 @@ protected:
int32 from_change_count,
const media_format &format);
protected:
void HandleBuffer(BBuffer *buffer);
status_t CreateBuffers(BRect frame, color_space cspace, bool overlay);
void DeleteBuffers();
protected:
private:
void _InitDisplay();
VideoWindow * fWindow;
VideoView * fVideoView;
media_input fInput;
bool fOverlayEnabled;
@ -87,6 +97,8 @@ protected:
bool fDirectOverlayBuffer; // If the overlay memory is directly written by the producer node.
BBitmap * fBitmap;
BLocker * fBitmapLocker;
BMediaAddOn* fAddOn;
int32 fInternalFlavorId;
};
#endif

View File

@ -3,39 +3,32 @@
*
* Distributed under the terms of the MIT License.
*/
#include <Bitmap.h>
#include <MediaRoster.h>
#include "VideoView.h"
#include "VideoNode.h"
#include "VideoView.h"
#include "debug.h"
#include <Bitmap.h>
#include <Locker.h>
#include <MediaRoster.h>
#include <Message.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
VideoView::VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags)
VideoView::VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags, VideoNode *node)
: BView(frame, name, resizeMask, flags)
, fVideoNode(0)
, fVideoNode(node)
, fOverlayActive(false)
{
SetViewColor(B_TRANSPARENT_COLOR);
status_t err = B_OK;
BMediaRoster *mroster = BMediaRoster::Roster(&err);
if (!mroster || err) {
printf("VideoView::VideoView: media_server is dead\n");
exit(1);
} else {
fVideoNode = new VideoNode("video in", this);
err = mroster->RegisterNode(fVideoNode);
}
}
VideoView::~VideoView()
{
if (fVideoNode) {
BMediaRoster::Roster()->UnregisterNode(fVideoNode);
delete fVideoNode;
}
}
@ -55,14 +48,14 @@ VideoView::Node()
void
VideoView::OverlayLockAcquire()
{
printf("VideoView::OverlayLockAcquire\n");
CALLED();
}
void
VideoView::OverlayLockRelease()
{
printf("VideoView::OverlayLockRelease\n");
CALLED();
// overlaybitmap->UnlockBits
}
@ -70,7 +63,7 @@ VideoView::OverlayLockRelease()
void
VideoView::OverlayScreenshotPrepare()
{
printf("OverlayScreenshotPrepare enter\n");
CALLED();
/*
fVideoNode->LockBitmap();
if (fOverlayActive) {
@ -88,14 +81,13 @@ VideoView::OverlayScreenshotPrepare()
}
fVideoNode->UnlockBitmap();
*/
printf("OverlayScreenshotPrepare leave\n");
}
void
VideoView::OverlayScreenshotCleanup()
{
printf("OverlayScreenshotCleanup enter\n");
CALLED();
/*
snooze(50000); // give app server some time to take the screenshot
fVideoNode->LockBitmap();
@ -110,15 +102,14 @@ VideoView::OverlayScreenshotCleanup()
}
fVideoNode->UnlockBitmap();
*/
printf("OverlayScreenshotCleanup leave\n");
}
void
VideoView::RemoveVideoDisplay()
{
printf("VideoView::RemoveVideoDisplay\n");
CALLED();
if (fOverlayActive) {
ClearViewOverlay();
fOverlayActive = false;
@ -130,7 +121,7 @@ VideoView::RemoveVideoDisplay()
void
VideoView::RemoveOverlay()
{
printf("VideoView::RemoveOverlay\n");
CALLED();
if (LockLooperWithTimeout(50000) == B_OK) {
ClearViewOverlay();
fOverlayActive = false;
@ -148,7 +139,10 @@ VideoView::Draw(BRect updateRect)
} else {
fVideoNode->LockBitmap();
BBitmap *bmp = fVideoNode->Bitmap();
if (bmp)
if (!bmp) {
SetHighColor(0, 0, 0, 0);
FillRect(updateRect);
} else
DrawBitmap(bmp, Bounds());
fVideoNode->UnlockBitmap();
}
@ -158,8 +152,8 @@ VideoView::Draw(BRect updateRect)
void
VideoView::DrawFrame()
{
// printf("VideoView::DrawFrame\n");
//CALLED();
bool want_overlay = fVideoNode->IsOverlayActive();
if (!want_overlay && fOverlayActive) {
@ -168,9 +162,10 @@ VideoView::DrawFrame()
UnlockLooper();
fOverlayActive = false;
} else {
printf("can't ClearViewOverlay, as LockLooperWithTimeout failed\n");
fprintf(stderr, "VideoView::DrawFrame: cannot ClearViewOverlay, as LockLooperWithTimeout failed\n");
}
}
if (want_overlay && !fOverlayActive) {
fVideoNode->LockBitmap();
BBitmap *bmp = fVideoNode->Bitmap();
@ -247,4 +242,3 @@ VideoView::IsOverlaySupported()
}
return supported;
}

View File

@ -6,19 +6,23 @@
#ifndef __VIDEO_VIEW_H
#define __VIDEO_VIEW_H
#include <View.h>
class BMediaAddOn;
class VideoNode;
class VideoView : public BView
{
public:
VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags);
VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags, VideoNode *node);
~VideoView();
void RemoveVideoDisplay();
void RemoveOverlay();
VideoNode * Node();
bool IsOverlaySupported();
@ -28,14 +32,14 @@ public:
void OverlayScreenshotPrepare();
void OverlayScreenshotCleanup();
void DrawFrame();
private:
void AttachedToWindow();
void MessageReceived(BMessage *msg);
void Draw(BRect updateRect);
private:
VideoNode * fVideoNode;
bool fOverlayActive;

View File

@ -1,11 +1,30 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2006-2008 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "VideoView.h"
#include "VideoNode.h"
#include "VideoWindow.h"
#include "VideoView.h"
#include <stdio.h>
#include <string.h>
VideoWindow::VideoWindow(BRect size, VideoView* view)
: BWindow(size, "Video Window", B_TITLED_WINDOW, 0)
, fVideoView(view)
{
if (fVideoView)
AddChild(fVideoView);
}
VideoWindow::~VideoWindow()
{
}
void
VideoWindow::MessageReceived(BMessage *msg)
{
if (msg)
BWindow::MessageReceived(msg);
}

View File

@ -1,24 +1,27 @@
/*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2006-2008 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
* Copyright (C) 2008 Maurice Kalinowski <haiku@kaldience.com>. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef __VIDEO_WINDOW_H
#define __VIDEO_WINDOW_H
#include <Window.h>
class VideoNode;
class VideoView;
class VideoWindow : public BWindow
{
public:
VideoWindow(BRect size, VideoView* view);
~VideoWindow();
void MessageReceived(BMessage *msg);
private:
private:
VideoNode * fVideoNode;
VideoView * fVideoView;
};

View File

@ -0,0 +1,34 @@
#include <stdio.h>
#ifndef NDEBUG
#ifndef DEBUG
#define DEBUG 2
#endif
#if DEBUG >= 1
#define UNIMPLEMENTED() printf("UNIMPLEMENTED %s\n",__PRETTY_FUNCTION__)
#else
#define UNIMPLEMENTED() ((void)0)
#endif
#if DEBUG >= 2
#define BROKEN() printf("BROKEN %s\n",__PRETTY_FUNCTION__)
#else
#define BROKEN() ((void)0)
#endif
#if DEBUG >= 3
#define CALLED() printf("CALLED %s\n",__PRETTY_FUNCTION__)
#else
#define CALLED() ((void)0)
#endif
#else
#define UNIMPLEMENTED() ((void)0)
#define BROKEN() ((void)0)
#define CALLED() ((void)0)
#endif