📄 xaosproducer.cpp
字号:
/*******************************************************************************// File: XaoSProducer.cpp// Description: Produce XaoS animation to pass along to some video-consuming Node./*******************************************************************************/#include <Mime.h>#include <TimeSource.h>#include <BufferGroup.h>#include <Buffer.h>#include <Autolock.h>#include <Debug.h>#include <MediaNode.h>#include <BufferProducer.h>#include <scheduler.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include "be_checkfile.h"#include "XaoSProducer.h"#define us_to_s(i) ((i)/1000000.0)#undef NDEBUG#define DEBUG 1#if !NDEBUG#define FPRINTF fprintf#else#define FPRINTF#endifenum { MSG_QUIT_NOW = 0x60000000L};// Comment out the FPRINTF part of these lines to reduce verbiage.#define WARNING FPRINTF#define LATE FPRINTF#define TRANSPORT FPRINTF#define NODE FPRINTF#define TIMING FPRINTF#define FORMAT FPRINTF#define PREFFERED_FIELD_RATE 90 #define PREFFERED_WIDTH 320#define PREFFERED_HEIGHT 200// is there a reason for higher framereate? We are handling real framerate// by dropping frames anyway// These constants set a reasonable default format for us to use.#define PREFFERED_COLOR_SPACE B_RGB32static const bigtime_t HUGE_TIMEOUT = 6000000LL;static const struct media_file_format fileformat={ media_file_format::B_READABLE | /*media_file_format::B_IMPERFECTLY_SEEKABLE | */ media_file_format::B_KNOWS_VIDEO, {}, "video/x-xaos-animation"};XaoSProducer::XaoSProducer(const char * name, BMediaAddOn *add): BMediaNode(name ? name : "XaoS"), BBufferProducer(B_MEDIA_RAW_VIDEO), BFileInterface(), addon(add), xaf_file(NULL){ NODE(stderr, "SoundProducer::SoundProducer\n"); AddNodeKind(B_FILE_INTERFACE); AddNodeKind(B_BUFFER_PRODUCER); if (!name) name = "XaoS"; // Create the port that we publish as our ControlPort. // As a simple producer, our queue length doesn't need // to be very long. char pname[32]; sprintf(pname, "%.20s Control", name); m_port = create_port(3, pname); // Finish specifying the media_output. Make sure // it knows the control port associated with the // source, and the index of the source (since we // only have one, that's trivial). m_output.source.port = m_port; m_output.source.id = 1; sprintf(m_output.name, "%.20s Output", name); // Set up the timing variables that we'll be using. m_frames_played = 0; // For downstream latency, we'll fill in a real value // when we're connected. m_downstream_latency = 15000; // For our own latency, we'll take a guess at the // scheduling latency and multiply by a fudge // factor. m_private_latency = estimate_max_scheduling_latency(m_thread)*2; m_tpStart = 0; m_tpStop = 0; m_tpSeekAt = 0; m_tmSeekTo = 0; m_delta = 0; m_running = false; m_starting = false; m_stopping = false; m_seeking = false; m_buffers = 0; SetFormat(NULL);#if !NDEBUG char fm2[100]; string_for_format(m_output.format, fm2, 100); FORMAT(stderr, "XaoSProducer format: %s\n", fm2);#endif m_sendBufferSem = create_sem(1, "send buffer sem"); m_thread = spawn_thread(ThreadEntry, "XaoS Thread", B_DISPLAY_PRIORITY, this); resume_thread(m_thread);}XaoSProducer::~XaoSProducer(){ NODE(stderr, "XaoSProducer::~XaoSProducer()\n"); // Tell our thread that it's bedtime. write_port(m_port, MSG_QUIT_NOW, 0, 0); status_t s; while (wait_for_thread(m_thread, &s) == B_INTERRUPTED) NODE(stderr, "wait_for_thread() B_INTERRUPTED\n"); NODE(stderr, "XaoSProducer::~XaoSProducer(): thread %ld completed\n", m_thread); delete_port(m_port); delete_sem(m_sendBufferSem); if(xaf_file!=NULL) delete xaf_file;}status_t XaoSProducer::GetRef(entry_ref *outRef, char *outMimeType){ strcpy(outMimeType,"video/x-xaos-animation"); fprintf(stderr,"XaoSProducer::GetRef not implemented\n"); *outRef=xaf_ref; return B_OK;}status_t XaoSProducer::SetRef(const entry_ref &file, bool create, bigtime_t *outDuration){ xaf_ref=file; fprintf(stderr, "XaoSProducer::SetRef (partially implemented)\n"); *outDuration=((bigtime_t)60)*60*1000000; /*We don't know time. Set one hour */ if(xaf_file!=NULL) delete xaf_file; xaf_file=new BFile(&file, O_RDONLY); if(xaf_file->InitCheck() != B_OK) return B_ERROR; fprintf(stderr,"OK!\n"); return B_OK;}status_t XaoSProducer::SniffRef(const entry_ref &file, char *outMimeType, float *outQuality){ BFile node(&file, O_RDONLY); int r=XaoSCheckFile(&node); if(r) *outQuality=1.0, strcpy(outMimeType,"video/x-xaos-animation"); fprintf(stderr,"XaoSProducer::SniffRef returns:%i\n",r); return(r?B_OK:B_MEDIA_NO_HANDLER);}status_t XaoSProducer::GetNextFileFormat(int32 *cookie, media_file_format *outFormat){ fprintf(stderr, "XaoSProducer::GetNextFileFormat\n"); if(!*cookie) { *cookie=1; if(outFormat) *outFormat=fileformat; return B_OK; } return B_ERROR;}void XaoSProducer::DisposeFileFormatCookie(int32 cookie ){ fprintf(stderr, "XaoSProducer::DisposeFileFormatCookie\n"); return;}status_t XaoSProducer::GetDuration(bigtime_t *outDuration){ fprintf(stderr, "XaoSProducer::GetDuration (not implemented)\n"); *outDuration=10*1000000*(bigtime_t)60; return B_OK;}void XaoSProducer::SetFormat(const media_raw_video_format* format){ fprintf(stderr,"XaoSProducer::SetFormat\n"); // m_raw_format is the format we've been told to use; // i.e. the format we'd like to use. The object // media_raw_audio_format::wildcard is a format // structure whose fields are all unitialized. m_raw_format = media_raw_video_format::wildcard; if (format != 0) { m_raw_format = *format; } // If anything has been left unspecified in the format // (== media_raw_video_format::wildcard.*), or if any // field is invalid (< media_raw_video_format::wildcard.*), // fill it in with a reasonable default. if (m_raw_format.field_rate <= media_raw_video_format::wildcard.field_rate) { m_raw_format.field_rate = PREFFERED_FIELD_RATE; } if (m_raw_format.interlace <= media_raw_video_format::wildcard.interlace) { m_raw_format.interlace = 1; } if (m_raw_format.first_active <= media_raw_video_format::wildcard.first_active) { m_raw_format.first_active = 0; } if (m_raw_format.last_active <= media_raw_video_format::wildcard.last_active) { m_raw_format.last_active = PREFFERED_HEIGHT-1; } if (m_raw_format.orientation <= media_raw_video_format::wildcard.orientation) { m_raw_format.orientation = B_VIDEO_TOP_LEFT_RIGHT; } if (m_raw_format.pixel_width_aspect <= media_raw_video_format::wildcard.pixel_width_aspect) { m_raw_format.pixel_width_aspect = 1; } if (m_raw_format.pixel_height_aspect <= media_raw_video_format::wildcard.pixel_height_aspect) { m_raw_format.pixel_height_aspect = 1; } if (m_raw_format.display.format <= media_raw_video_format::wildcard.display.format) { m_raw_format.display.format = PREFFERED_COLOR_SPACE; } if (m_raw_format.display.line_width <= media_raw_video_format::wildcard.display.line_width) { m_raw_format.display.line_width = PREFFERED_WIDTH; } if (m_raw_format.display.line_count <= media_raw_video_format::wildcard.display.line_width) { m_raw_format.display.line_count = PREFFERED_HEIGHT; } if (m_raw_format.display.line_offset <= media_raw_video_format::wildcard.display.line_offset) { m_raw_format.display.line_offset = 0; } if (m_raw_format.display.pixel_offset <= media_raw_video_format::wildcard.display.pixel_offset) { m_raw_format.display.pixel_offset = 0; } if (m_raw_format.display.bytes_per_row <= media_raw_video_format::wildcard.display.bytes_per_row) { int mult; switch (m_raw_format.display.format) { /*The 24-bit versions are not compiled in, because BeOS don't support them in most cases. Use 32 instead. */ case B_RGB24: case B_RGB24_BIG: mult=3*8; break; case B_RGB32: case B_RGB32_BIG: case B_RGBA32: case B_RGBA32_BIG: mult=4*8; break; case B_RGB16: case B_RGB16_BIG: case B_RGBA15: case B_RGBA15_BIG: case B_RGB15: case B_RGB15_BIG: mult=2*8; break; case B_CMAP8: case B_GRAY8: mult=8; case B_GRAY1: mult=1; break; default: abort(); } m_raw_format.display.bytes_per_row = (mult*m_raw_format.display.line_width+7)/8; } media_format proposedFormat; proposedFormat.type = B_MEDIA_RAW_VIDEO; proposedFormat.u.raw_video = media_raw_video_format::wildcard; proposedFormat.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; FormatSuggestionRequested(B_MEDIA_RAW_VIDEO, 0, &proposedFormat); // Set the output format. m_output represents the // actual connection, so m_output.format.u.raw_audio // should be equal to the *actual* format we're using, // as opposed to m_raw_format, which is our preferred // format. if (m_output.destination != media_destination::null) { // If there's an existing connection, notify the // downstream consumer that we want to change the // format. The consumer may refuse to change to // the new format, in which case we're pretty much // out of luck. // // Two notes: // 1. We need to stop sending buffers while // we're changing the format, so we guard with a // semaphore. // 2. Theoretically, this allows us to change the // format while we're connected and running. In // practice, however, few nodes right now support // format changes this way. if (acquire_sem(m_sendBufferSem) == B_OK) { NODE(stderr, "XaoSProducer::ChangeFormat(): src = %ld, dest = %ld\n", m_output.source.id, m_output.destination.id); if (ProposeFormatChange(&proposedFormat, m_output.destination) == B_OK && ChangeFormat(m_output.source, m_output.destination, &proposedFormat) == B_OK) { // OK by the consumer! Go ahead and update m_output. m_output.format = proposedFormat; } else { WARNING(stderr, "XaoSProducer::SetFormat(): couldn't change to new format!\n"); } release_sem(m_sendBufferSem); } else { WARNING(stderr, "XaoSProducer::SetFormat(): couldn't acquire SendBuffer semaphore!\n"); } } else { // No active connection, so set m_output to the // desired format; it'll be adjusted when an // actual connection is made. m_output.format = proposedFormat; }}//////////////////////////////////////////////////////////////////////////////////// BMediaNode-derived methods//////////////////////////////////////////////////////////////////////////////////port_id XaoSProducer::ControlPort() const{ return m_port;}BMediaAddOn* XaoSProducer::AddOn( int32 * internal_id) const{ fprintf(stderr,"XaoSProducer::AddOn (OK)\n"); if (internal_id) *internal_id = 0; return addon;}void XaoSProducer::Start( bigtime_t performance_time){ fprintf(stderr,"XaoSProducer::Start (not implemented)\n"); if (!m_stopping || performance_time > m_tpStop) { if (!m_running || m_stopping) {#if 0 if (m_notifyHook) { (*m_notifyHook)(m_cookie, B_WILL_START, performance_time); } else { Notify(B_WILL_START, performance_time); }#endif m_tpStart = performance_time; m_starting = true; TRANSPORT(stderr, "XaoSProducer start at %.4f (now %.4f)\n", us_to_s(m_tpStart), us_to_s(TimeSource()->Now()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -