📄 radeonproducer.cpp
字号:
/******************************************************************************// File: RadeonProducer.cpp// Description: ATI Radeon Video Producer media node.// Copyright 2001, Carlos Hasan/*******************************************************************************/#include <fcntl.h>#include <malloc.h>#include <math.h>#include <stdio.h>#include <string.h>#include <sys/uio.h>#include <unistd.h>#include <scheduler.h>#include <media/Buffer.h>#include <media/BufferGroup.h>#include <media/ParameterWeb.h>#include <media/TimeSource.h>#include <support/Autolock.h>#include <support/Debug.h>#include <app/Message.h>#include "RadeonAddOn.h"#define DPRINT(args) { PRINT(("\x1b[0;30;35m")); PRINT(args); PRINT(("\x1b[0;30;47m")); }#define TOUCH(x) ((void)(x))#define PRINTF(a,b) \ do { \ if (a < 2) { \ printf("CRadeonProducer::"); \ printf b; \ } \ } while (0)#include "RadeonProducer.h"// convert Be video standard to video-in standard;// Be forgot some standards and define code 7 and 8 to be MPEG1/2, i.e.// didn't leave any space for enhancements, so I chose to use 101 and up;// this way, we get a scattered list of video standards, needing special// functions to convert to scattered Be-code to the compact video-in-codevideo_in_standard BeToVideoInStandard( int32 be_standard ){ switch( be_standard ) { case 1: return C_VIDEO_IN_NTSC; case 2: return C_VIDEO_IN_NTSC_JAPAN; case 3: return C_VIDEO_IN_PAL_BDGHI; case 4: return C_VIDEO_IN_PAL_M; case 5: return C_VIDEO_IN_PAL_N; case 6: return C_VIDEO_IN_SECAM; case 101: return C_VIDEO_IN_NTSC_443; case 102: return C_VIDEO_IN_PAL_60; case 103: return C_VIDEO_IN_PAL_NC; default: return C_VIDEO_IN_NTSC; }}int32 VideoInStandardToBe( video_in_standard standard ){ int32 be_standard[] = { 1, 2, 101, 4, 3, 5, 102, 103, 6 }; if( (uint)standard < sizeof( be_standard ) / sizeof( be_standard[0] ) ) return be_standard[(int)standard]; else return 1;}status_t CRadeonProducer::FindInt32( BMessage *config, EOptions option, int32 min_value, int32 max_value, int32 default_value, int32 *value ){ char name[5]; status_t res; *value = default_value; *(int32 *)name = option; name[4] = 0; res = config->FindInt32( name, value ); if( res == B_NAME_NOT_FOUND ) return B_OK; if( res != B_OK ) return res; *value = MAX( *value, min_value ); *value = MIN( *value, max_value ); return B_OK;}CRadeonProducer::CRadeonProducer( CRadeonAddOn *addon, const char *name, const char *device_name, int32 internal_id, BMessage *config ) : BMediaNode(name), BMediaEventLooper(), BBufferProducer(B_MEDIA_RAW_VIDEO), BControllable(), fVideoIn( device_name ){ DPRINT(("CRadeonProducer::CRadeonProducer()\n")); fInitStatus = B_NO_INIT; fInternalID = internal_id; fAddOn = addon; fBufferGroup = NULL; //fUsedBufferGroup = NULL; fProcessingLatency = 0LL; //fConnected = false; fEnabled = true; AddNodeKind(B_PHYSICAL_INPUT); if( fVideoIn.InitCheck() == B_OK ) fInitStatus = B_OK; fSource = ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) != 0 ? C_VIDEO_IN_TUNER : C_VIDEO_IN_COMPOSITE); fStandard = 1; fMode = C_VIDEO_IN_WEAVE; fFormat = B_RGB32; fResolution = 4; fTuner = 25; fBrightness = 0; fContrast = 0; fSaturation = 0; fHue = 0; fSharpness = 0; if( config != NULL ) { status_t res; int32 standard; if( (res = FindInt32( config, P_SOURCE, 0, C_VIDEO_IN_SOURCE_MAX, (fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) != 0 ? C_VIDEO_IN_TUNER : C_VIDEO_IN_COMPOSITE, &fSource )) != B_OK || (res = FindInt32( config, P_STANDARD, 0, C_VIDEO_IN_STANDARD_MAX, C_VIDEO_IN_NTSC, &standard )) != B_OK || (res = FindInt32( config, P_MODE, 0, C_VIDEO_IN_CAPTURE_MODE_MAX, C_VIDEO_IN_FIELD, &fMode )) != B_OK || (res = FindInt32( config, P_FORMAT, -2147483647L-1, 2147483647L, B_RGB16, &fFormat )) != B_OK || (res = FindInt32( config, P_RESOLUTION, 0, C_RESOLUTION_MAX, 4, &fResolution )) != B_OK || (res = FindInt32( config, P_TUNER, 0, C_CHANNEL_MAX, 25, &fTuner )) != B_OK || (res = FindInt32( config, P_BRIGHTNESS, -100, +100, 0, &fBrightness )) != B_OK || (res = FindInt32( config, P_CONTRAST, 0, 100, 0, &fContrast )) != B_OK || (res = FindInt32( config, P_SATURATION, -100, +100, 0, &fSaturation )) != B_OK || (res = FindInt32( config, P_HUE, -90, +90, 0, &fHue )) != B_OK || (res = FindInt32( config, P_SHARPNESS, 0, 15, 0, &fSharpness )) != B_OK ) { DPRINT(("Corrupted settings (%s)\n", strerror( res ))); } // standard is stored as internal code (which has no "holes" in its numbering); // time to convert it fStandard = VideoInStandardToBe( (video_in_standard)standard ); // if there is no tuner, force composite input if( (fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) == 0 ) fSource = C_VIDEO_IN_COMPOSITE; // format ids are scattered, so we must verify them manually switch( fFormat ) { case B_YCbCr422: case B_GRAY8: case B_RGB15: case B_RGB16: case B_RGB32: break; default: fFormat = B_RGB16; } } fSourceLastChange = fStandardLastChange = fModeLastChange = fFormatLastChange = fResolutionLastChange = fTunerLastChange = fBrightnessLastChange = fContrastLastChange = fSaturationLastChange = fHueLastChange = fSharpnessLastChange = system_time(); fOutput.destination = media_destination::null; strcpy(fOutput.name, Name()); // we provide interlaced raw video in any format fOutput.format.type = B_MEDIA_RAW_VIDEO; fOutput.format.u.raw_video = media_raw_video_format::wildcard;}void CRadeonProducer::setupWeb(){ /////////// /* Set up the parameter web */ // in "kind" value of parameters is "stampTV-compatible", i.e. // if not defined, we use the name used in stampTV BParameterWeb *web = new BParameterWeb(); BParameterGroup *controls = web->MakeGroup("Controls"); BParameterGroup *options = web->MakeGroup("Video"); /*BParameterGroup *audio = web->MakeGroup("Audio");*/ BParameterGroup *controls1 = controls->MakeGroup("Controls1"); BParameterGroup *controls2 = controls->MakeGroup("Controls2"); BParameterGroup *controls3 = controls->MakeGroup("Controls3"); BParameterGroup *options1 = options->MakeGroup("Options1"); BParameterGroup *options2 = options->MakeGroup("Options2"); /*BParameterGroup *audio1 = audio->MakeGroup("Audio1"); BParameterGroup *audio2 = audio->MakeGroup("Audio2");*/ // Controls if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) != 0) { // Controls.Channel BDiscreteParameter *tuner = controls1->MakeDiscreteParameter( P_TUNER, B_MEDIA_NO_TYPE, "Channel:", B_TUNER_CHANNEL); for (int channel = 0; channel <= 125; channel++) { char buffer[32]; sprintf(buffer, "%d", channel); tuner->AddItem(channel, buffer); } } // Controls.Source BDiscreteParameter *source = controls1->MakeDiscreteParameter( P_SOURCE, B_MEDIA_RAW_VIDEO, "Video Input:", "Video Input:"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) != 0) source->AddItem(C_VIDEO_IN_TUNER, "Tuner"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_COMPOSITE) != 0) source->AddItem(C_VIDEO_IN_COMPOSITE, "Composite"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_SVIDEO) != 0) source->AddItem(C_VIDEO_IN_SVIDEO, "SVideo"); // TODO: BDiscreteParameter *source2 = controls1->MakeDiscreteParameter( P_AUDIO_SOURCE, B_MEDIA_RAW_VIDEO, "Audio Input:", "Audio Input:"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_TUNER) != 0) source2->AddItem(C_VIDEO_IN_TUNER, "Tuner"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_COMPOSITE) != 0) source2->AddItem(C_VIDEO_IN_COMPOSITE, "Composite"); if ((fVideoIn.Capabilities() & C_VIDEO_IN_HAS_SVIDEO) != 0) source2->AddItem(C_VIDEO_IN_SVIDEO, "SVideo"); // Controls.Brightness/Contrast/Saturation/Hue controls2->MakeContinuousParameter(P_BRIGHTNESS, B_MEDIA_RAW_VIDEO,"Brightness", "BRIGHTNESS", "", -100, 100, 1); controls2->MakeContinuousParameter(P_CONTRAST, B_MEDIA_RAW_VIDEO, "Contrast", "CONTRAST", "", 0, 100, 1); controls2->MakeContinuousParameter(P_SHARPNESS, B_MEDIA_RAW_VIDEO, "Sharpness", B_LEVEL, "dB", 0, 15, 1); controls3->MakeContinuousParameter(P_SATURATION, B_MEDIA_RAW_VIDEO, "Saturation", "SATURATION", "", -100, 100, 1); controls3->MakeContinuousParameter(P_HUE, B_MEDIA_RAW_VIDEO, "Hue", B_LEVEL, "°", -90, 90, 1); // Options.Resolution BDiscreteParameter *resolution = options1->MakeDiscreteParameter( P_RESOLUTION, B_MEDIA_RAW_VIDEO, "Default Image Size:", B_RESOLUTION); resolution->AddItem(6, "768x576"); resolution->AddItem(5, "720x576"); resolution->AddItem(4, "720x480"); resolution->AddItem(0, "640x480"); resolution->AddItem(3, "480x360"); resolution->AddItem(1, "320x240"); resolution->AddItem(2, "160x120"); // Options.Format BDiscreteParameter *format = options1->MakeDiscreteParameter( P_FORMAT, B_MEDIA_RAW_VIDEO, "Default Colors:", B_COLOR_SPACE); format->AddItem(B_YCbCr422, "YCbCr422 (fastest)"); format->AddItem(B_GRAY8, "8 Bits/Pixel (gray)"); format->AddItem(B_RGB15, "15 Bits/Pixel"); format->AddItem(B_RGB16, "16 Bits/Pixel"); format->AddItem(B_RGB32, "32 Bits/Pixel"); // Options.Standard BDiscreteParameter *standard = options2->MakeDiscreteParameter( P_STANDARD, B_MEDIA_RAW_VIDEO, "Video Format:", B_VIDEO_FORMAT); standard->AddItem(1, "NTSC"); standard->AddItem(2, "NTSC Japan"); standard->AddItem(101, "NTSC 443"); standard->AddItem(4, "PAL M"); standard->AddItem(3, "PAL BDGHI"); standard->AddItem(5, "PAL N"); standard->AddItem(102, "PAL 60"); standard->AddItem(103, "PAL NC"); standard->AddItem(6, "SECAM"); // Options.Mode BDiscreteParameter *mode = options2->MakeDiscreteParameter( P_MODE, B_MEDIA_RAW_VIDEO, "Video Interlace:", B_GENERIC); mode->AddItem(C_VIDEO_IN_FIELD, "Field"); mode->AddItem(C_VIDEO_IN_BOB, "Bob"); mode->AddItem(C_VIDEO_IN_WEAVE, "Weave"); // TODO: /* BDiscreteParameter *standard2 = audio1->MakeDiscreteParameter( P_AUDIO_FORMAT, B_MEDIA_RAW_VIDEO, "Audio Format:", B_VIDEO_FORMAT); standard2->AddItem(0, "Stereo"); standard2->AddItem(1, "Mono"); standard2->AddItem(2, "NICAM"); BDiscreteParameter *audioSource = audio1->MakeDiscreteParameter( P_AUDIO_FORMAT, B_MEDIA_RAW_VIDEO, "Audio Source:", B_VIDEO_FORMAT); audioSource->AddItem(0, "FM"); audioSource->AddItem(1, "Stereo"); audioSource->AddItem(2, "SCART"); audioSource->AddItem(3, "Language A"); audioSource->AddItem(4, "Language B"); BDiscreteParameter *matrix= audio2->MakeDiscreteParameter( P_AUDIO_FORMAT, B_MEDIA_RAW_VIDEO, "Audio Matrix:", B_VIDEO_FORMAT); matrix->AddItem(0, "Sound A"); matrix->AddItem(1, "Sound B"); matrix->AddItem(2, "Stereo"); matrix->AddItem(3, "Mono");*/ /* After this call, the BControllable owns the BParameterWeb object and * will delete it for you */ SetParameterWeb(web); /////////}CRadeonProducer::~CRadeonProducer(){ DPRINT(("CRadeonProducer::~CRadeonProducer()\n")); if (fInitStatus == B_OK) { /* Clean up after ourselves, in case the application didn't make us * do so. */ /*if (fConnected) Disconnect(fOutput.source, fOutput.destination);*/ HandleStop(); } delete fBufferGroup; fBufferGroup = NULL; BMessage settings; GetConfiguration( &settings ); fAddOn->UnregisterNode( this, &settings ); Quit();}/* BMediaNode */port_idCRadeonProducer::ControlPort() const{ return BMediaNode::ControlPort();}BMediaAddOn *CRadeonProducer::AddOn(int32 *internal_id) const{ if (internal_id) *internal_id = fInternalID; return fAddOn;}status_t CRadeonProducer::HandleMessage(int32 message, const void *data, size_t size){ //DPRINT(("CRadeonProducer::HandleMessage()\n")); switch( message ) { case C_GET_CONFIGURATION: { const configuration_msg *request = (const configuration_msg *)data; BMessage msg; configuration_msg_reply *reply; size_t reply_size, config_size; status_t res; if( size < sizeof( configuration_msg )) return B_ERROR; res = GetConfiguration( &msg ); config_size = msg.FlattenedSize(); reply_size = sizeof( *reply ) + config_size; reply = (configuration_msg_reply *)malloc( reply_size ); if( reply == NULL ) return B_NO_MEMORY; reply->res = res; reply->config_size = config_size; msg.Flatten( &reply->config, config_size ); write_port_etc( request->reply_port, C_GET_CONFIGURATION_REPLY, reply, reply_size, B_TIMEOUT, 0 ); free( reply ); return B_OK; } default: return B_ERROR; // return BControllable::HandleMessage(message, data, size); }}void CRadeonProducer::Preroll(){ /* This hook may be called before the node is started to give the hardware * a chance to start. */ DPRINT(("CRadeonProducer::Preroll()\n"));}voidCRadeonProducer::SetTimeSource(BTimeSource *time_source){ DPRINT(("CRadeonProducer::SetTimeSource()\n")); /* Tell frame generation thread to recalculate delay value */ //release_sem(fFrameSync);}status_tCRadeonProducer::RequestCompleted(const media_request_info &info){ DPRINT(("CRadeonProducer::RequestCompleted()\n")); return BMediaNode::RequestCompleted(info);}/* BMediaEventLooper */void CRadeonProducer::NodeRegistered(){ DPRINT(("CRadeonProducer::NodeRegistered()\n")); if (fInitStatus != B_OK) { ReportError(B_NODE_IN_DISTRESS); return; } setupWeb();//!!// fOutput.node = Node(); fOutput.source.port = ControlPort(); fOutput.source.id = 0; /* Tailor these for the output of your device */ /******** fOutput.format.type = B_MEDIA_RAW_VIDEO; fOutput.format.u.raw_video = media_raw_video_format::wildcard;// fOutput.format.u.raw_video.interlace = 1; fOutput.format.u.raw_video.display.format = B_RGB32; ********/ // up to 60 frames (NTSC); jitter less then half a frame; processing time // depends on whether colour space conversion is required, let's say half // a frame in worst case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -