📄 radeonproducer.cpp
字号:
return B_OK;}// set "offset" parameters of format if not set yetvoidCRadeonProducer::setFormatOffsets( media_format *format ){ if( format->u.raw_video.display.pixel_offset == media_raw_video_format::wildcard.display.pixel_offset ) format->u.raw_video.display.pixel_offset = 0; if( format->u.raw_video.display.line_offset == media_raw_video_format::wildcard.display.line_offset ) format->u.raw_video.display.line_offset = 0;}// verify "flags" parameter of formatstatus_tCRadeonProducer::verifyFormatFlags( media_format *format ){ if( format->u.raw_video.display.flags != media_raw_video_format::wildcard.display.flags && format->u.raw_video.display.flags != 0 ) { DPRINT(( "Requested display flags are not zero" )); return B_MEDIA_BAD_FORMAT; } return B_OK;}// set "flags" parameter of format if not set yetvoidCRadeonProducer::setFormatFlags( media_format *format ){ if( format->u.raw_video.display.flags == media_raw_video_format::wildcard.display.flags ) format->u.raw_video.display.flags = 0;}/* * Fill out all wildcards in a format descriptor. */status_tCRadeonProducer::finalizeFormat( media_format *format ){ if (format->type != B_MEDIA_RAW_VIDEO) return B_MEDIA_BAD_FORMAT; status_t res; res = verifySetMode( format ); if( res != B_OK ) return res; int32 mode = extractCaptureMode( format ); res = verifyActiveRange( format ); if( res != B_OK ) return res; setActiveRange( format ); res = verifyOrientation( format ); if( res != B_OK ) return res; res = verifySetPixelAspect( format ); if( res != B_OK ) return res; res = verifyPixelFormat( format ); if( res != B_OK ) return res; setPixelFormat( format); res = verifySetSize( format, mode, true ); if( res != B_OK ) return res; res = verifyFormatOffsets( format ); if( res != B_OK ) return res; setFormatOffsets( format ); res = verifyFormatFlags( format ); if( res != B_OK ) return res; setFormatFlags( format );}/* * Someone has no idea what format we usually provide and asks us. * * It's not really clear whether we are allowed to return wildcards. */status_t CRadeonProducer::FormatSuggestionRequested( media_type type, int32 quality, media_format *format){ DPRINT(("CRadeonProducer::FormatSuggestionRequested()\n")); if (type != B_MEDIA_RAW_VIDEO) return B_MEDIA_BAD_FORMAT; TOUCH(quality); format->type = B_MEDIA_RAW_VIDEO; format->u.raw_video = media_raw_video_format::wildcard; finalizeFormat( format ); return B_OK;}/* Initial format proposal as part of a connection establishment. First, the application defines a format with many wildcards in it; this format is passed to us, so we can restrict it if necessary; we should leave as many wildcards as possible, because in the next step the consumer is asked, and he will not be happy if he has to choise left .*/status_t CRadeonProducer::FormatProposal(const media_source &output, media_format *format){ char buffer[256]; DPRINT(("CRadeonProducer::FormatProposal()\n")); if( format == NULL ) return B_BAD_VALUE; if( output != fOutput.source ) return B_MEDIA_BAD_SOURCE; string_for_format(*format, buffer, sizeof(buffer)); DPRINT(("CRadeonProducer::FormatProposal() - in=%s\n", buffer)); if( format->type == B_MEDIA_NO_TYPE ) { // if there is not even a type, set raw video format->type = B_MEDIA_RAW_VIDEO; format->u.raw_video = media_raw_video_format::wildcard; } if (format->type != B_MEDIA_RAW_VIDEO) return B_MEDIA_BAD_FORMAT; status_t res; // first, choose capture mode, so we know the maximum video size res = verifySetMode( format ); if( res != B_OK ) return res; int32 mode = extractCaptureMode( format ); res = verifyActiveRange( format ); if( res != B_OK ) return res; res = verifyOrientation( format ); if( res != B_OK ) return res; setOrientation( format ); // simple aspect calculation: we always use 1:1, so setting this is easy res = verifySetPixelAspect( format ); if( res != B_OK ) return res; res = verifyPixelFormat( format ); if( res != B_OK ) return res; // if we don't set it, the consumer usually chooses a stupid format setPixelFormat( format ); // verify size and set if if undefined; // do that now, else the consumer will set it (making the defaults // set via preferences useless) // leave bytes_per_lines untouched, though // (we don't really care but the consumer may have some alignment restrictions) res = verifySetSize( format, mode, false ); if( res != B_OK ) return res; res = verifyFormatOffsets( format ); if( res != B_OK ) return res; res = verifyFormatFlags( format ); if( res != B_OK ) return res; string_for_format(*format, buffer, sizeof(buffer)); DPRINT(("CRadeonProducer::FormatProposal() - out=%s\n", buffer)); return B_OK;}status_t CRadeonProducer::FormatChangeRequested(const media_source &source, const media_destination &destination, media_format *io_format, int32 *_deprecated_){ DPRINT(("CRadeonProducer::FormatChangeRequested()\n")); TOUCH(destination); TOUCH(io_format); TOUCH(_deprecated_); if (source != fOutput.source) return B_MEDIA_BAD_SOURCE; return B_ERROR; }status_t CRadeonProducer::GetNextOutput(int32 *cookie, media_output *out_output){ DPRINT(("CRadeonProducer::GetNextOutput()\n")); if (!out_output) return B_BAD_VALUE; if ((*cookie) != 0) return B_BAD_INDEX; *out_output = fOutput; (*cookie)++; return B_OK;}status_t CRadeonProducer::DisposeOutputCookie(int32 cookie){ DPRINT(("CRadeonProducer::DisposeOutputCookie()\n")); TOUCH(cookie); return B_OK;}status_t CRadeonProducer::SetBufferGroup(const media_source &for_source, BBufferGroup *group){ DPRINT(("CRadeonProducer::SetBufferGroup()\n")); if( for_source != fOutput.source ) return B_MEDIA_BAD_SOURCE; if( group != NULL ) { delete fBufferGroup; fBufferGroup = group; } return B_OK;}status_t CRadeonProducer::VideoClippingChanged(const media_source &for_source, int16 num_shorts, int16 *clip_data, const media_video_display_info &display, int32 *_deprecated_){ DPRINT(("CRadeonProducer::VideoClippingChanged()\n")); TOUCH(for_source); TOUCH(num_shorts); TOUCH(clip_data); TOUCH(display); TOUCH(_deprecated_); return B_ERROR;}status_t CRadeonProducer::GetLatency(bigtime_t *out_latency){ DPRINT(("CRadeonProducer::GetLatency()\n")); // delay is one frame for capturing, a scheduling latency, the // DMA copying, the format conversion and the output nodes latency; // scheduling, DMA copying and format conversion is summed up in // fProcessingLatency bigtime_t capture_latency = (bigtime_t)(1000000.0 / fOutput.format.u.raw_video.field_rate); // HACK: (see HandleHardware()) // to be compatible to existing software, we write the ending time of // capture instead of the beginning time into buffers, thus we // have no capture delay capture_latency = 0; bigtime_t buffer_latency = fProcessingLatency; BBufferProducer::GetLatency( &buffer_latency ); *out_latency = SchedulingLatency() + capture_latency + fProcessingLatency + buffer_latency; DPRINT(("latency=%lld\n", *out_latency)); return B_OK;}status_t CRadeonProducer::PrepareToConnect(const media_source &source, const media_destination &destination, media_format *format, media_source *out_source, char *out_name){ DPRINT(("CRadeonProducer::PrepareToConnect()\n")); PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \ format->u.raw_video.display.line_width, \ format->u.raw_video.display.line_count)); if (source != fOutput.source) { DPRINT(("bad source\n")); return B_MEDIA_BAD_SOURCE; } if (fOutput.destination != media_destination::null) { DPRINT(("already connected\n")); return B_MEDIA_ALREADY_CONNECTED; } char buffer[256]; string_for_format(*format, buffer, sizeof(buffer)); DPRINT(("CRadeonProducer::PrepareToConnect() - in=%s\n", buffer)); status_t res = finalizeFormat( format ); if( res != B_OK ) return res; *out_source = fOutput.source; strcpy(out_name, fOutput.name); string_for_format(*format, buffer, sizeof(buffer)); DPRINT(("CRadeonProducer::PrepareToConnect() - out=%s\n", buffer)); // reserve connection fOutput.destination = destination; DPRINT(("finished\n")); return B_OK;}voidCRadeonProducer::setDefaultBufferGroup(){ DPRINT(("CRadeonProducer::setDefaultBufferGroup()\n")); /*delete fBufferGroup; fBufferGroup = NULL;*/ if( fBufferGroup != NULL ) { DPRINT(("Buffer already set\n")); return; } fBufferGroup = new BBufferGroup( fOutput.format.u.raw_video.display.bytes_per_row * fOutput.format.u.raw_video.display.line_count, 3, B_ANY_ADDRESS, B_FULL_LOCK ); if (fBufferGroup->InitCheck() < B_OK) { delete fBufferGroup; fBufferGroup = NULL; return; }}voidCRadeonProducer::startCapturing(){ if( RunState() != BMediaEventLooper::B_STARTED || fOutput.destination == media_destination::null ) return; fVideoIn.SetChannel(fTuner, C_VIDEO_IN_NTSC); fVideoIn.SetBrightness(fBrightness); fVideoIn.SetContrast(fContrast); fVideoIn.SetSaturation(fSaturation); fVideoIn.SetHue(fHue); fVideoIn.SetSharpness(fSharpness); fVideoIn.Start(video_in_source(fSource), BeToVideoInStandard( fStandard ), video_in_capture_mode(fCurMode), fOutput.format.u.raw_video.display.line_width, fOutput.format.u.raw_video.display.line_count); char *tmp_buffer; tmp_buffer = (char *)malloc( fOutput.format.u.raw_video.display.bytes_per_row * fOutput.format.u.raw_video.display.line_count ); int field_sequence; short field_number; bigtime_t capture_time; // do a real capturing to prime everything fVideoIn.Capture( tmp_buffer != NULL ? fOutput.format.u.raw_video.display.format : B_NO_COLOR_SPACE, tmp_buffer, fOutput.format.u.raw_video.display.bytes_per_row * fOutput.format.u.raw_video.display.line_count, fOutput.format.u.raw_video.display.bytes_per_row, &field_sequence, &field_number, &capture_time ); // capture some frames to be sure there are no pending buffers; // discard captured data to safe time (we want to catch up and not fall behind) for( int i = 0; i < 3; ++i ) { fVideoIn.Capture( B_NO_COLOR_SPACE, NULL, fOutput.format.u.raw_video.display.bytes_per_row * fOutput.format.u.raw_video.display.line_count, fOutput.format.u.raw_video.display.bytes_per_row, &field_sequence, &field_number, &capture_time ); DPRINT(("Captured: %lld, current: %lld\n", capture_time, system_time() )); } // do a real capturing to see how long it takes until the // buffer is ready, i.e. including DMA and colour conversion fVideoIn.Capture( tmp_buffer != NULL ? fOutput.format.u.raw_video.display.format : B_NO_COLOR_SPACE, tmp_buffer, fOutput.format.u.raw_video.display.bytes_per_row * fOutput.format.u.raw_video.display.line_count, fOutput.format.u.raw_video.display.bytes_per_row, &field_sequence, &field_number, &capture_time ); DPRINT(("Captured: %lld, current: %lld\n", capture_time, system_time() )); // now we know our internal latency fProcessingLatency = system_time() - capture_time; DPRINT(("Processing latency: %dµs\n", fProcessingLatency )); // store field sequence to start with zero // (capture-internal field sequence always counts up) fFieldSequenceBase = field_sequence; if( tmp_buffer != NULL ) free(tmp_buffer); // tell latence MediaEventLooper so it can schedule events properly ahead bigtime_t total_latency; GetLatency( &total_latency ); SetEventLatency( total_latency ); // Create the buffer group setDefaultBufferGroup(); //fUsedBufferGroup = fBufferGroup; // schedule a capture event after one field's time RealTimeQueue()->FlushEvents( 0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HARDWARE ); media_timed_event event( capture_time + 1000000 / fOutput.format.u.raw_video.field_rate, BTimedEventQueue::B_HARDWARE); RealTimeQueue()->AddEvent(event);}void CRadeonProducer::Connect(status_t error, const media_source &source, const media_destination &destination, const media_format &format, char *io_name){ // we even get called if consumer reported error in AcceptFormat; // in this case, we must release the source already reserved by // PrepareToConnect if( error != B_OK ) { DPRINT(( "Connect: Consumer returned error (%s) - releasing source", strerror( error ))); fOutput.destination = media_destination::null; return; } if( source != fOutput.source ) { DPRINT(( "Connect: Wrong source specified\n")); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -