/** * Create and start an interface. * * @param playlist playlist and parent object for the interface * @param chain configuration chain string * @return VLC_SUCCESS or an error code */ int intf_Create( playlist_t *playlist, const char *chain ) { /* Allocate structure */ intf_thread_t *p_intf = vlc_custom_create( playlist, sizeof( *p_intf ), "interface" ); if( unlikely(p_intf == NULL) ) return VLC_ENOMEM; /* Variable used for interface spawning */ vlc_value_t val, text; var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND ); text.psz_string = _("Add Interface"); var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL ); #if !defined(_WIN32) && defined(HAVE_ISATTY) if( isatty( 0 ) ) #endif { val.psz_string = (char *)"rc,none"; text.psz_string = (char *)_("Console"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); } val.psz_string = (char *)"telnet,none"; text.psz_string = (char *)_("Telnet"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"http,none"; text.psz_string = (char *)_("Web"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"logger,none"; text.psz_string = (char *)_("Debug logging"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"gestures,none"; text.psz_string = (char *)_("Mouse Gestures"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); var_AddCallback( p_intf, "intf-add", AddIntfCallback, playlist ); /* Choose the best module */ char *module; p_intf->p_cfg = NULL; free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) ); p_intf->p_module = module_need( p_intf, "interface", module, true ); free(module); if( p_intf->p_module == NULL ) { msg_Err( p_intf, "no suitable interface module" ); goto error; } vlc_mutex_lock( &lock ); p_intf->p_next = pl_priv( playlist )->interface; pl_priv( playlist )->interface = p_intf; vlc_mutex_unlock( &lock ); return VLC_SUCCESS; error: if( p_intf->p_module ) module_unneed( p_intf, p_intf->p_module ); config_ChainDestroy( p_intf->p_cfg ); vlc_object_release( p_intf ); return VLC_EGENERIC; }
//--------------------------------------------------------------------------- // Run: main loop //--------------------------------------------------------------------------- static void *Run( void * p_obj ) { int canc = vlc_savecancel(); intf_thread_t *p_intf = (intf_thread_t *)p_obj; bool b_error = false; char *skin_last = NULL; ThemeLoader *pLoader = NULL; OSLoop *loop = NULL; vlc_mutex_lock( &p_intf->p_sys->init_lock ); // Initialize singletons if( OSFactory::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize OSFactory" ); b_error = true; goto end; } if( AsyncQueue::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize AsyncQueue" ); b_error = true; goto end; } if( Interpreter::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate Interpreter" ); b_error = true; goto end; } if( VarManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate VarManager" ); b_error = true; goto end; } if( VlcProc::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize VLCProc" ); b_error = true; goto end; } if( VoutManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate VoutManager" ); b_error = true; goto end; } if( ArtManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate ArtManager" ); b_error = true; goto end; } if( ThemeRepository::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate ThemeRepository" ); b_error = true; goto end; } if( Dialogs::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate qt4 dialogs provider" ); b_error = true; goto end; } // Load a theme skin_last = config_GetPsz( p_intf, "skins2-last" ); pLoader = new ThemeLoader( p_intf ); if( !skin_last || !pLoader->load( skin_last ) ) { // No skins (not even the default one). let's quit CmdQuit *pCmd = new CmdQuit( p_intf ); AsyncQueue *pQueue = AsyncQueue::instance( p_intf ); pQueue->push( CmdGenericPtr( pCmd ) ); msg_Err( p_intf, "no skins found : exiting"); } delete pLoader; free( skin_last ); // Get the instance of OSLoop loop = OSFactory::instance( p_intf )->getOSLoop(); // Signal the main thread this thread is now ready p_intf->p_sys->b_error = false; p_intf->p_sys->b_ready = true; vlc_cond_signal( &p_intf->p_sys->init_wait ); vlc_mutex_unlock( &p_intf->p_sys->init_lock ); // Enter the main event loop loop->run(); // Destroy OSLoop OSFactory::instance( p_intf )->destroyOSLoop(); // save and delete the theme if( p_intf->p_sys->p_theme ) { p_intf->p_sys->p_theme->saveConfig(); delete p_intf->p_sys->p_theme; p_intf->p_sys->p_theme = NULL; msg_Dbg( p_intf, "current theme deleted" ); } // save config file config_SaveConfigFile( p_intf ); end: // Destroy "singleton" objects Dialogs::destroy( p_intf ); ThemeRepository::destroy( p_intf ); ArtManager::destroy( p_intf ); VoutManager::destroy( p_intf ); VlcProc::destroy( p_intf ); VarManager::destroy( p_intf ); Interpreter::destroy( p_intf ); AsyncQueue::destroy( p_intf ); OSFactory::destroy( p_intf ); if( b_error ) { p_intf->p_sys->b_error = true; p_intf->p_sys->b_ready = true; vlc_cond_signal( &p_intf->p_sys->init_wait ); vlc_mutex_unlock( &p_intf->p_sys->init_lock ); } vlc_restorecancel(canc); return NULL; }
static int Open(vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; /* Connect to the display server */ char *dpy_name = var_InheritString(demux, "wl-display"); sys->display = wl_display_connect(dpy_name); free(dpy_name); if (sys->display == NULL) { free(sys); return VLC_EGENERIC; } sys->output = NULL; sys->shm = NULL; sys->screenshooter = NULL; sys->es = NULL; sys->pagemask = sysconf(_SC_PAGE_SIZE) - 1; sys->rate = var_InheritFloat(demux, "screen-fps"); sys->x = var_InheritInteger(demux, "screen-left"); sys->y = var_InheritInteger(demux, "screen-top"); sys->w = var_InheritInteger(demux, "screen-width"); sys->h = var_InheritInteger(demux, "screen-height"); if (1000.f * sys->rate <= 0x1.p-30) goto error; demux->p_sys = sys; /* Find the interesting singleton(s) */ struct wl_registry *registry = wl_display_get_registry(sys->display); if (registry == NULL) goto error; wl_registry_add_listener(registry, ®istry_cbs, demux); wl_display_roundtrip(sys->display); wl_registry_destroy(registry); if (sys->output == NULL || sys->shm == NULL || sys->screenshooter == NULL) { msg_Err(demux, "screenshooter extension not supported"); goto error; } wl_output_add_listener(sys->output, &output_cbs, demux); screenshooter_add_listener(sys->screenshooter, &screenshooter_cbs, &sys->done); wl_display_roundtrip(sys->display); if (DisplayError(demux, sys->display)) goto error; /* Initializes demux */ sys->start = mdate(); if (vlc_clone(&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT)) goto error; demux->pf_demux = NULL; demux->pf_control = Control; return VLC_SUCCESS; error: if (sys->screenshooter != NULL) screenshooter_destroy(sys->screenshooter); if (sys->shm != NULL) wl_shm_destroy(sys->shm); if (sys->output != NULL) wl_output_destroy(sys->output); wl_display_disconnect(sys->display); free(sys); return VLC_EGENERIC; }
/***************************************************************************** * QTVideoInit: *****************************************************************************/ static int QTVideoInit( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; #ifdef __APPLE__ p_sys->FindNextComponent = (void*)FindNextComponent; p_sys->OpenComponent = (void*)OpenComponent; p_sys->ImageCodecInitialize = (void*)ImageCodecInitialize; p_sys->ImageCodecGetCodecInfo = (void*)ImageCodecGetCodecInfo; p_sys->ImageCodecPreDecompress = (void*)ImageCodecPreDecompress; p_sys->ImageCodecBandDecompress = (void*)ImageCodecBandDecompress; p_sys->GetGWorldPixMap = (void*)GetGWorldPixMap; p_sys->QTNewGWorldFromPtr = (void*)QTNewGWorldFromPtr; p_sys->NewHandleClear = (void*)NewHandleClear; #else #ifdef LOADER p_sys->ldt_fs = Setup_LDT_Keeper(); #endif /* LOADER */ p_sys->qts = LoadLibraryA( "QuickTime.qts" ); if( p_sys->qts == NULL ) { msg_Dbg( p_dec, "failed loading QuickTime.qts" ); return VLC_EGENERIC; } msg_Dbg( p_dec, "QuickTime.qts loaded" ); p_sys->qtml = LoadLibraryA( "qtmlClient.dll" ); if( p_sys->qtml == NULL ) { msg_Dbg( p_dec, "failed loading qtmlClient.dll" ); return VLC_EGENERIC; } msg_Dbg( p_dec, "qtmlClient.dll loaded" ); /* (void*) to shut up gcc */ p_sys->InitializeQTML = (void*)GetProcAddress( p_sys->qtml, "InitializeQTML" ); p_sys->FindNextComponent = (void*)GetProcAddress( p_sys->qtml, "FindNextComponent" ); p_sys->OpenComponent = (void*)GetProcAddress( p_sys->qtml, "OpenComponent" ); p_sys->ImageCodecInitialize = (void*)GetProcAddress( p_sys->qtml, "ImageCodecInitialize" ); p_sys->ImageCodecGetCodecInfo = (void*)GetProcAddress( p_sys->qtml, "ImageCodecGetCodecInfo" ); p_sys->ImageCodecPreDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecPreDecompress" ); p_sys->ImageCodecBandDecompress = (void*)GetProcAddress( p_sys->qtml, "ImageCodecBandDecompress" ); p_sys->GetGWorldPixMap = (void*)GetProcAddress( p_sys->qtml, "GetGWorldPixMap" ); p_sys->QTNewGWorldFromPtr = (void*)GetProcAddress( p_sys->qtml, "QTNewGWorldFromPtr" ); p_sys->NewHandleClear = (void*)GetProcAddress( p_sys->qtml, "NewHandleClear" ); if( p_sys->InitializeQTML == NULL ) { msg_Dbg( p_dec, "failed getting proc address InitializeQTML" ); return VLC_EGENERIC; } if( p_sys->FindNextComponent == NULL || p_sys->OpenComponent == NULL || p_sys->ImageCodecInitialize == NULL || p_sys->ImageCodecGetCodecInfo == NULL || p_sys->ImageCodecPreDecompress == NULL || p_sys->ImageCodecBandDecompress == NULL || p_sys->GetGWorldPixMap == NULL || p_sys->QTNewGWorldFromPtr == NULL || p_sys->NewHandleClear == NULL ) { msg_Err( p_dec, "failed getting proc address" ); return VLC_EGENERIC; } #endif /* __APPLE__ */ return VLC_SUCCESS; }
/***************************************************************************** * OpenVideo: *****************************************************************************/ static int OpenVideo( decoder_t *p_dec ) { #ifndef WIN32 decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; long i_result; ComponentDescription desc; Component prev; ComponentResult cres; ImageSubCodecDecompressCapabilities icap; /* for ImageCodecInitialize() */ CodecInfo cinfo; /* for ImageCodecGetCodecInfo() */ ImageDescription *id; char fcc[4]; int i_vide = p_dec->fmt_in.i_extra; uint8_t *p_vide = p_dec->fmt_in.p_extra; p_dec->p_sys = p_sys; p_dec->pf_decode_video = DecodeVideo; p_sys->i_late = 0; if( i_vide <= 0 ) { msg_Err( p_dec, "missing extra info" ); free( p_sys ); return VLC_EGENERIC; } if( p_dec->fmt_in.i_original_fourcc ) memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 ); else memcpy( fcc, &p_dec->fmt_in.i_codec, 4 ); msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d", fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); /* get lock, avoid segfault */ vlc_mutex_lock( &qt_mutex ); #ifdef __APPLE__ EnterMovies(); #endif if( QTVideoInit( p_dec ) ) { msg_Err( p_dec, "cannot initialize QT"); goto exit_error; } #ifndef __APPLE__ if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) ) { msg_Dbg( p_dec, "error on InitializeQTML = %d", (int)i_result ); goto exit_error; } #endif /* init ComponentDescription */ memset( &desc, 0, sizeof( ComponentDescription ) ); desc.componentType = FCC( 'i', 'm', 'd', 'c' ); desc.componentSubType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); desc.componentManufacturer = 0; desc.componentFlags = 0; desc.componentFlagsMask = 0; if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) ) { msg_Err( p_dec, "cannot find requested component" ); goto exit_error; } msg_Dbg( p_dec, "component id=0x%p", prev ); p_sys->ci = p_sys->OpenComponent( prev ); msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci ); memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) ); cres = p_sys->ImageCodecInitialize( p_sys->ci, &icap ); msg_Dbg( p_dec, "ImageCodecInitialize->0x%X size=%d (%d)", (int)cres, (int)icap.recordSize, (int)icap.decompressRecordSize); memset( &cinfo, 0, sizeof( CodecInfo ) ); cres = p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo ); msg_Dbg( p_dec, "Flags: compr: 0x%x decomp: 0x%x format: 0x%x", (unsigned int)cinfo.compressFlags, (unsigned int)cinfo.decompressFlags, (unsigned int)cinfo.formatFlags ); msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s", ((unsigned char*)&cinfo.typeName)[0], ((unsigned char*)&cinfo.typeName)+1 ); /* make a yuy2 gworld */ p_sys->OutBufferRect.top = 0; p_sys->OutBufferRect.left = 0; p_sys->OutBufferRect.right = p_dec->fmt_in.video.i_width; p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height; /* codec data FIXME use codec not SVQ3 */ msg_Dbg( p_dec, "vide = %d", i_vide ); id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) ); if( !id ) goto exit_error; id->idSize = sizeof( ImageDescription ) + ( i_vide - 70 ); id->cType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); id->version = GetWBE ( p_vide + 0 ); id->revisionLevel = GetWBE ( p_vide + 2 ); id->vendor = GetDWBE( p_vide + 4 ); id->temporalQuality = GetDWBE( p_vide + 8 ); id->spatialQuality = GetDWBE( p_vide + 12 ); id->width = GetWBE ( p_vide + 16 ); id->height = GetWBE ( p_vide + 18 ); id->hRes = GetDWBE( p_vide + 20 ); id->vRes = GetDWBE( p_vide + 24 ); id->dataSize = GetDWBE( p_vide + 28 ); id->frameCount = GetWBE ( p_vide + 32 ); memcpy( &id->name, p_vide + 34, 32 ); id->depth = GetWBE ( p_vide + 66 ); id->clutID = GetWBE ( p_vide + 68 ); if( i_vide > 70 ) { memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 ); } msg_Dbg( p_dec, "idSize=%d ver=%d rev=%d vendor=%d tempQ=%d " "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d depth=%d frameCount=%d clutID=%d", (int)id->idSize, id->version, id->revisionLevel, (int)id->vendor, (int)id->temporalQuality, (int)id->spatialQuality, (int)id->width, (int)id->height, (int)id->hRes, (int)id->vRes, (int)id->dataSize, id->depth, id->frameCount, id->clutID ); p_sys->framedescHandle = (ImageDescriptionHandle) NewHandleClear( id->idSize ); memcpy( *p_sys->framedescHandle, id, id->idSize ); if( p_dec->fmt_in.video.i_width != 0 && p_dec->fmt_in.video.i_height != 0) p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 ); if( !p_sys->plane ) goto exit_error; i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld, /*pixel format of new GWorld==YUY2 */ kYUVSPixelFormat, /* we should benchmark if yvu9 is * faster for svq3, too */ &p_sys->OutBufferRect, 0, 0, 0, p_sys->plane, p_dec->fmt_in.video.i_width * 2 ); msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld", 65536 - ( i_result&0xffff ) ); memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) ); p_sys->decpar.imageDescription = p_sys->framedescHandle; p_sys->decpar.startLine = 0; p_sys->decpar.stopLine = ( **p_sys->framedescHandle ).height; p_sys->decpar.frameNumber = 1; p_sys->decpar.matrixFlags = 0; p_sys->decpar.matrixType = 0; p_sys->decpar.matrix = 0; p_sys->decpar.capabilities = &p_sys->codeccap; p_sys->decpar.accuracy = codecNormalQuality; p_sys->decpar.srcRect = p_sys->OutBufferRect; p_sys->decpar.transferMode = srcCopy; p_sys->decpar.dstPixMap = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap; */ cres = p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar ); msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X", (int)cres ); es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_CODEC_YUYV); p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width; p_dec->fmt_out.video.i_height= p_dec->fmt_in.video.i_height; p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; vlc_mutex_unlock( &qt_mutex ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( &qt_mutex ); #else VLC_UNUSED( p_dec ); #endif /* !WIN32 */ return VLC_EGENERIC; }
int vout_snapshot_SaveImage(char **name, int *sequential, const block_t *image, vlc_object_t *object, const vout_snapshot_save_cfg_t *cfg) { /* */ char *filename; DIR *pathdir = vlc_opendir(cfg->path); if (pathdir != NULL) { /* The use specified a directory path */ closedir(pathdir); /* */ char *prefix = NULL; if (cfg->prefix_fmt) prefix = str_format(object, cfg->prefix_fmt); if (prefix) filename_sanitize(prefix); else { prefix = strdup("vlcsnap-"); if (!prefix) goto error; } if (cfg->is_sequential) { for (int num = cfg->sequence; ; num++) { struct stat st; if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", cfg->path, prefix, num, cfg->format) < 0) { free(prefix); goto error; } if (vlc_stat(filename, &st)) { *sequential = num; break; } free(filename); } } else { struct tm curtime; time_t lcurtime = time(NULL) ; if (!localtime_r(&lcurtime, &curtime)) { const unsigned int id = (image->i_pts / 100000) & 0xFFFFFF; msg_Warn(object, "failed to get current time. Falling back to legacy snapshot naming"); if (asprintf(&filename, "%s" DIR_SEP "%s%u.%s", cfg->path, prefix, id, cfg->format) < 0) filename = NULL; } else { /* suffix with the last decimal digit in 10s of seconds resolution * FIXME gni ? */ const int id = (image->i_pts / (100*1000)) & 0xFF; char buffer[128]; if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime)) strcpy(buffer, "error"); if (asprintf(&filename, "%s" DIR_SEP "%s%s%1u.%s", cfg->path, prefix, buffer, id, cfg->format) < 0) filename = NULL; } } free(prefix); } else { /* The user specified a full path name (including file name) */ filename = str_format(object, cfg->path); path_sanitize(filename); } if (!filename) goto error; /* Save the snapshot */ FILE *file = vlc_fopen(filename, "wb"); if (!file) { msg_Err(object, "Failed to open '%s'", filename); free(filename); goto error; } if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { msg_Err(object, "Failed to write to '%s'", filename); fclose(file); free(filename); goto error; } fclose(file); /* */ if (name) *name = filename; else free(filename); return VLC_SUCCESS; error: msg_Err(object, "could not save snapshot"); return VLC_EGENERIC; }
/** * Rearranges audio blocks in correct number of samples. * @note (FIXME) This is left here for historical reasons. It belongs in the * output code. Besides, this operation should be avoided if possible. */ static block_t *aout_OutputSlice (audio_output_t *p_aout) { aout_packet_t *p = aout_packet (p_aout); aout_fifo_t *p_fifo = &p->partial; const unsigned samples = p->samples; assert( samples > 0 ); /* Retrieve the date of the next buffer. */ date_t exact_start_date = p->fifo.end_date; mtime_t start_date = date_Get( &exact_start_date ); /* Check if there is enough data to slice a new buffer. */ aout_buffer_t *p_buffer = p_fifo->p_first; if( p_buffer == NULL ) return NULL; /* Find the earliest start date available. */ if ( start_date == VLC_TS_INVALID ) { start_date = p_buffer->i_pts; date_Set( &exact_start_date, start_date ); } /* Compute the end date for the new buffer. */ mtime_t end_date = date_Increment( &exact_start_date, samples ); /* Check that we have enough samples (TODO merge with next loop). */ for( unsigned available = 0; available < samples; ) { p_buffer = p_buffer->p_next; if( p_buffer == NULL ) return NULL; available += p_buffer->i_nb_samples; } if( AOUT_FMT_LINEAR( &p_aout->format ) ) { const unsigned framesize = p_aout->format.i_bytes_per_frame; /* Build packet with adequate number of samples */ unsigned needed = samples * framesize; p_buffer = block_Alloc( needed ); if( unlikely(p_buffer == NULL) ) /* XXX: should free input buffers */ return NULL; p_buffer->i_nb_samples = samples; for( uint8_t *p_out = p_buffer->p_buffer; needed > 0; ) { aout_buffer_t *p_inbuf = p_fifo->p_first; if( unlikely(p_inbuf == NULL) ) { msg_Err( p_aout, "packetization error" ); vlc_memset( p_out, 0, needed ); break; } const uint8_t *p_in = p_inbuf->p_buffer; size_t avail = p_inbuf->i_nb_samples * framesize; if( avail > needed ) { vlc_memcpy( p_out, p_in, needed ); p_fifo->p_first->p_buffer += needed; p_fifo->p_first->i_buffer -= needed; needed /= framesize; p_fifo->p_first->i_nb_samples -= needed; mtime_t t = needed * CLOCK_FREQ / p_aout->format.i_rate; p_fifo->p_first->i_pts += t; p_fifo->p_first->i_length -= t; break; } vlc_memcpy( p_out, p_in, avail ); needed -= avail; p_out += avail; /* Next buffer */ aout_BufferFree( aout_FifoPop( p_fifo ) ); } } else p_buffer = aout_FifoPop( p_fifo ); p_buffer->i_pts = start_date; p_buffer->i_length = end_date - start_date; return p_buffer; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; switch( p_dec->fmt_in.i_codec ) { case VLC_CODEC_SUBT: case VLC_CODEC_SSA: case VLC_CODEC_ITU_T140: break; default: return VLC_EGENERIC; } p_dec->pf_decode_sub = DecodeBlock; p_dec->fmt_out.i_cat = SPU_ES; p_dec->fmt_out.i_codec = 0; /* Allocate the memory needed to store the decoder's structure */ p_dec->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) ); if( p_sys == NULL ) return VLC_ENOMEM; /* init of p_sys */ p_sys->i_align = 0; p_sys->iconv_handle = (vlc_iconv_t)-1; p_sys->b_autodetect_utf8 = false; p_sys->b_ass = false; p_sys->i_original_height = -1; p_sys->i_original_width = -1; TAB_INIT( p_sys->i_ssa_styles, p_sys->pp_ssa_styles ); TAB_INIT( p_sys->i_images, p_sys->pp_images ); char *psz_charset = NULL; /* First try demux-specified encoding */ if( p_dec->fmt_in.i_codec == VLC_CODEC_ITU_T140 ) psz_charset = strdup( "UTF-8" ); /* IUT T.140 is always using UTF-8 */ else if( p_dec->fmt_in.subs.psz_encoding && *p_dec->fmt_in.subs.psz_encoding ) { psz_charset = strdup (p_dec->fmt_in.subs.psz_encoding); msg_Dbg (p_dec, "trying demuxer-specified character encoding: %s", p_dec->fmt_in.subs.psz_encoding ? p_dec->fmt_in.subs.psz_encoding : "not specified"); } /* Second, try configured encoding */ if (psz_charset == NULL) { psz_charset = var_InheritString (p_dec, "subsdec-encoding"); msg_Dbg (p_dec, "trying configured character encoding: %s", psz_charset ? psz_charset : "not specified"); if (psz_charset != NULL && !strcmp (psz_charset, "system")) { free (psz_charset); psz_charset = strdup (""); /* ^ iconv() treats "" as nl_langinfo(CODESET) */ } } /* Third, try "local" encoding with optional UTF-8 autodetection */ if (psz_charset == NULL) { /* xgettext: The Windows ANSI code page most commonly used for this language. VLC uses this as a guess of the subtitle files character set (if UTF-8 and UTF-16 autodetection fails). Western European languages normally use "CP1252", which is a Microsoft-variant of ISO 8859-1. That suits the Latin alphabet. Other scripts use other code pages. This MUST be a valid iconv character set. If unsure, please refer the VideoLAN translators mailing list. */ const char *acp = vlc_pgettext("GetACP", "CP1252"); psz_charset = strdup (acp); msg_Dbg (p_dec, "trying default character encoding: %s", psz_charset ? psz_charset : "not specified"); if (var_InheritBool (p_dec, "subsdec-autodetect-utf8")) { msg_Dbg (p_dec, "using automatic UTF-8 detection"); p_sys->b_autodetect_utf8 = true; } } /* Forth, don't do character decoding, i.e. assume UTF-8 */ if (psz_charset == NULL) { psz_charset = strdup ("UTF-8"); msg_Dbg (p_dec, "using UTF-8 character encoding" ); } if ((psz_charset != NULL) && strcasecmp (psz_charset, "UTF-8") && strcasecmp (psz_charset, "utf8")) { p_sys->iconv_handle = vlc_iconv_open ("UTF-8", psz_charset); if (p_sys->iconv_handle == (vlc_iconv_t)(-1)) msg_Err (p_dec, "cannot convert from %s: %m", psz_charset); } free (psz_charset); p_sys->i_align = var_InheritInteger( p_dec, "subsdec-align" ); if( p_dec->fmt_in.i_codec == VLC_CODEC_SSA && var_InheritBool( p_dec, "subsdec-formatted" ) ) { if( p_dec->fmt_in.i_extra > 0 ) ParseSSAHeader( p_dec ); } return VLC_SUCCESS; }
/***************************************************************************** * ParseText: parse an text subtitle packet and send it to the video output *****************************************************************************/ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; char *psz_subtitle = NULL; video_format_t fmt; /* We cannot display a subpicture with no date */ if( p_block->i_pts <= VLC_TS_INVALID ) { msg_Warn( p_dec, "subtitle without a date" ); return NULL; } /* Check validity of packet data */ /* An "empty" line containing only \0 can be used to force and ephemer picture from the screen */ if( p_block->i_buffer < 1 ) { msg_Warn( p_dec, "no subtitle data" ); return NULL; } /* Should be resiliant against bad subtitles */ psz_subtitle = malloc( p_block->i_buffer + 1 ); if( psz_subtitle == NULL ) return NULL; memcpy( psz_subtitle, p_block->p_buffer, p_block->i_buffer ); psz_subtitle[p_block->i_buffer] = '\0'; if( p_sys->iconv_handle == (vlc_iconv_t)-1 ) { if (EnsureUTF8( psz_subtitle ) == NULL) { msg_Err( p_dec, "failed to convert subtitle encoding.\n" "Try manually setting a character-encoding " "before you open the file." ); } } else { if( p_sys->b_autodetect_utf8 ) { if( IsUTF8( psz_subtitle ) == NULL ) { msg_Dbg( p_dec, "invalid UTF-8 sequence: " "disabling UTF-8 subtitles autodetection" ); p_sys->b_autodetect_utf8 = false; } } if( !p_sys->b_autodetect_utf8 ) { size_t inbytes_left = strlen( psz_subtitle ); size_t outbytes_left = 6 * inbytes_left; char *psz_new_subtitle = xmalloc( outbytes_left + 1 ); char *psz_convert_buffer_out = psz_new_subtitle; const char *psz_convert_buffer_in = psz_subtitle; size_t ret = vlc_iconv( p_sys->iconv_handle, &psz_convert_buffer_in, &inbytes_left, &psz_convert_buffer_out, &outbytes_left ); *psz_convert_buffer_out++ = '\0'; free( psz_subtitle ); if( ( ret == (size_t)(-1) ) || inbytes_left ) { free( psz_new_subtitle ); msg_Err( p_dec, "failed to convert subtitle encoding.\n" "Try manually setting a character-encoding " "before you open the file." ); return NULL; } psz_subtitle = realloc( psz_new_subtitle, psz_convert_buffer_out - psz_new_subtitle ); if( !psz_subtitle ) psz_subtitle = psz_new_subtitle; } } /* Create the subpicture unit */ p_spu = decoder_NewSubpicture( p_dec, NULL ); if( !p_spu ) { msg_Warn( p_dec, "can't get spu buffer" ); free( psz_subtitle ); return NULL; } /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_CODEC_TEXT; fmt.i_width = fmt.i_height = 0; fmt.i_x_offset = fmt.i_y_offset = 0; p_spu->p_region = subpicture_region_New( &fmt ); if( !p_spu->p_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); free( psz_subtitle ); decoder_DeleteSubpicture( p_dec, p_spu ); return NULL; } /* Decode and format the subpicture unit */ if( p_dec->fmt_in.i_codec != VLC_CODEC_SSA ) { /* Normal text subs, easy markup */ p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align; p_spu->p_region->i_x = p_sys->i_align ? 20 : 0; p_spu->p_region->i_y = 10; /* Remove formatting from string */ p_spu->p_region->psz_text = StripTags( psz_subtitle ); if( var_InheritBool( p_dec, "subsdec-formatted" ) ) { p_spu->p_region->psz_html = CreateHtmlSubtitle( &p_spu->p_region->i_align, psz_subtitle ); } p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; } else { /* Decode SSA/USF strings */ ParseSSAString( p_dec, psz_subtitle, p_spu ); p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; p_spu->i_original_picture_width = p_sys->i_original_width; p_spu->i_original_picture_height = p_sys->i_original_height; } free( psz_subtitle ); return p_spu; }
/***************************************************************************** * OpenFilter: probe the filter and return score *****************************************************************************/ static int OpenFilter( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys; if( !p_filter->b_allow_fmt_out_change ) { msg_Err( p_filter, "Picture format change isn't allowed" ); return VLC_EGENERIC; } if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma ) { msg_Err( p_filter, "Input and output chromas don't match" ); /* In fact we don't really care about this since we're allowed * to change the output format ... FIXME? */ return VLC_EGENERIC; } p_filter->p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) ); if( !p_filter->p_sys ) return VLC_ENOMEM; config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options, p_filter->p_cfg ); p_sys = p_filter->p_sys; #define GET_OPTION( name ) \ p_sys->i_ ## name = var_CreateGetInteger( p_filter, CFG_PREFIX #name ); \ if( p_sys->i_ ## name & 1 ) \ msg_Warn( p_filter, "Using even values for `" #name "' is recommended" ); GET_OPTION( croptop ) GET_OPTION( cropbottom ) GET_OPTION( cropleft ) GET_OPTION( cropright ) GET_OPTION( paddtop ) GET_OPTION( paddbottom ) GET_OPTION( paddleft ) GET_OPTION( paddright ) p_filter->fmt_out.video.i_height = p_filter->fmt_out.video.i_visible_height = p_filter->fmt_in.video.i_visible_height - p_sys->i_croptop - p_sys->i_cropbottom + p_sys->i_paddtop + p_sys->i_paddbottom; p_filter->fmt_out.video.i_width = p_filter->fmt_out.video.i_visible_width = p_filter->fmt_in.video.i_visible_width - p_sys->i_cropleft - p_sys->i_cropright + p_sys->i_paddleft + p_sys->i_paddright; p_filter->pf_video_filter = Filter; msg_Dbg( p_filter, "Crop: Top: %d, Bottom: %d, Left: %d, Right: %d", p_sys->i_croptop, p_sys->i_cropbottom, p_sys->i_cropleft, p_sys->i_cropright ); msg_Dbg( p_filter, "Padd: Top: %d, Bottom: %d, Left: %d, Right: %d", p_sys->i_paddtop, p_sys->i_paddbottom, p_sys->i_paddleft, p_sys->i_paddright ); msg_Dbg( p_filter, "%dx%d -> %dx%d", p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height, p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height ); return VLC_SUCCESS; }
/** * This function allocates and initializes a aa vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; #ifndef _WIN32 if (!vlc_xlib_init (object)) return VLC_EGENERIC; #endif /* Allocate structure */ vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; /* Don't parse any options, but take $AAOPTS into account */ aa_parseoptions(NULL, NULL, NULL, NULL); /* */ sys->aa_context = aa_autoinit(&aa_defparams); if (!sys->aa_context) { msg_Err(vd, "cannot initialize aalib"); goto error; } vout_display_DeleteWindow(vd, NULL); aa_autoinitkbd(sys->aa_context, 0); aa_autoinitmouse(sys->aa_context, AA_MOUSEALLMASK); /* */ video_format_t fmt = vd->fmt; fmt.i_chroma = VLC_CODEC_RGB8; fmt.i_width = aa_imgwidth(sys->aa_context); fmt.i_height = aa_imgheight(sys->aa_context); fmt.i_visible_width = fmt.i_width; fmt.i_visible_height = fmt.i_height; /* */ vout_display_info_t info = vd->info; info.has_pictures_invalid = true; /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = Prepare; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* Inspect initial configuration and send correction events * FIXME how to handle aspect ratio with aa ? */ sys->state = *vd->cfg; sys->state.is_fullscreen = false; vout_display_SendEventFullscreen(vd, false); vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height); return VLC_SUCCESS; error: if (sys && sys->aa_context) aa_close(sys->aa_context); free(sys); return VLC_EGENERIC; }
static int Setup( vlc_va_t *external, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma, int i_width, int i_height ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( external ); if( p_va->hw_ctx.width == i_width && p_va->hw_ctx.height == i_height && p_va->hw_ctx.decoder ) { *pp_hw_ctx = &p_va->hw_ctx; *pi_chroma = p_va->i_chroma; return VLC_SUCCESS; } if( p_va->hw_ctx.decoder ) { ff_vda_destroy_decoder( &p_va->hw_ctx ); goto ok; } memset( &p_va->hw_ctx, 0, sizeof(p_va->hw_ctx) ); p_va->hw_ctx.format = 'avc1'; int i_pix_fmt = var_CreateGetInteger( p_va->p_log, "avcodec-vda-pix-fmt" ); switch( i_pix_fmt ) { case 1 : p_va->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8; p_va->i_chroma = VLC_CODEC_UYVY; msg_Dbg(p_va->p_log, "using pixel format 422YpCbCr8"); break; case 0 : default : p_va->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8Planar; p_va->i_chroma = VLC_CODEC_I420; CopyInitCache( &p_va->image_cache, i_width ); msg_Dbg(p_va->p_log, "using pixel format 420YpCbCr8Planar"); } ok: /* Setup the libavcodec hardware context */ *pp_hw_ctx = &p_va->hw_ctx; *pi_chroma = p_va->i_chroma; p_va->hw_ctx.width = i_width; p_va->hw_ctx.height = i_height; /* create the decoder */ int status = ff_vda_create_decoder( &p_va->hw_ctx, p_va->p_extradata, p_va->i_extradata ); if( status ) { msg_Err( p_va->p_log, "Failed to create decoder: %i", status ); return VLC_EGENERIC; } else msg_Dbg( p_va->p_log, "VDA decoder created"); return VLC_SUCCESS; }
static int Control (vout_display_t *vd, int query, va_list ap) { vout_display_sys_t *p_sys = vd->sys; switch (query) { case VOUT_DISPLAY_CHANGE_FULLSCREEN: { const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *); return vout_window_SetFullScreen (p_sys->embed, c->is_fullscreen); } case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *p_cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *); const bool is_forced = (bool)va_arg (ap, int); if (is_forced && vout_window_SetSize (p_sys->embed, p_cfg->display.width, p_cfg->display.height)) return VLC_EGENERIC; vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, p_cfg, false); if (place.width != vd->fmt.i_visible_width || place.height != vd->fmt.i_visible_height) { vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; } /* Move the picture within the window */ const uint32_t values[] = { place.x, place.y }; xcb_configure_window (p_sys->conn, p_sys->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_WINDOW_STATE: { unsigned state = va_arg (ap, unsigned); return vout_window_SetState (p_sys->embed, state); } case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: /* I am not sure it is always necessary, but it is way simpler ... */ vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: { ResetPictures (vd); vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, vd->cfg, false); vd->fmt.i_width = vd->source.i_width * place.width / vd->source.i_visible_width; vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height; vd->fmt.i_visible_width = place.width; vd->fmt.i_visible_height = place.height; vd->fmt.i_x_offset = vd->source.i_x_offset * place.width / vd->source.i_visible_width; vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height; return VLC_SUCCESS; } /* Hide the mouse. It will be send when * vout_display_t::info.b_hide_mouse is false */ case VOUT_DISPLAY_HIDE_MOUSE: xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid, XCB_CW_CURSOR, &(uint32_t){ p_sys->cursor }); xcb_flush (p_sys->conn); return VLC_SUCCESS; default: msg_Err (vd, "Unknown request in XCB vout display"); return VLC_EGENERIC; } }
/** * Probe the X server. */ static int Open (vlc_object_t *obj) { vout_display_t *vd = (vout_display_t *)obj; vout_display_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; vd->sys = p_sys; p_sys->pool = NULL; /* Get window, connect to X server */ const xcb_screen_t *scr; p_sys->embed = GetWindow (vd, &p_sys->conn, &scr, &(uint8_t){ 0 }); if (p_sys->embed == NULL) { free (p_sys); return VLC_EGENERIC; } const xcb_setup_t *setup = xcb_get_setup (p_sys->conn); p_sys->byte_order = setup->image_byte_order; /* Determine our pixel format */ xcb_visualid_t vid = 0; p_sys->depth = 0; for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup), *end = fmt + xcb_setup_pixmap_formats_length (setup); fmt < end; fmt++) { if (fmt->depth <= p_sys->depth) continue; /* no better than earlier format */ video_format_t fmt_pic = vd->fmt; /* Check that the pixmap format is supported by VLC. */ switch (fmt->depth) { case 32: if (fmt->bits_per_pixel != 32) continue; #ifdef FIXED_VLC_RGBA_MASK fmt_pic.i_chroma = VLC_CODEC_RGBA; break; #else msg_Dbg (vd, "X11 visual with alpha-channel not supported"); continue; #endif case 24: if (fmt->bits_per_pixel == 32) fmt_pic.i_chroma = VLC_CODEC_RGB32; else if (fmt->bits_per_pixel == 24) fmt_pic.i_chroma = VLC_CODEC_RGB24; else continue; break; case 16: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB16; break; case 15: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB15; break; case 8: if (fmt->bits_per_pixel != 8) continue; fmt_pic.i_chroma = VLC_CODEC_RGB8; break; default: continue; } /* VLC pads lines to 16 pixels internally */ if ((fmt->bits_per_pixel << 4) % fmt->scanline_pad) continue; /* Byte sex is a non-issue for 8-bits. It can be worked around with * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */ if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER) continue; /* Check that the selected screen supports this depth */ const xcb_depth_t *d = FindDepth (scr, fmt->depth); if (d == NULL) continue; /* Find a visual type for the selected depth */ const xcb_visualtype_t *vt = xcb_depth_visuals (d); /* First try True Color class */ for (int i = xcb_depth_visuals_length (d); i > 0; i--) { if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR) { fmt_pic.i_rmask = vt->red_mask; fmt_pic.i_gmask = vt->green_mask; fmt_pic.i_bmask = vt->blue_mask; goto found_visual; } vt++; } /* Then try Static Gray class */ if (fmt->depth == 8) for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--) { if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY) goto found_grey; vt++; } continue; /* Fail: unusable pixel format */ found_grey: fmt_pic.i_chroma = VLC_CODEC_GREY; found_visual: p_sys->bpp = fmt->bits_per_pixel; p_sys->pad = fmt->scanline_pad; p_sys->depth = fmt->depth; vd->fmt = fmt_pic; vid = vt->visual_id; } if (!vid) { msg_Err (obj, "no supported pixel format & visual"); goto error; } msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid); msg_Dbg (vd, " %"PRIu8" bits depth", p_sys->depth); msg_Dbg (vd, " %"PRIu8" bits per pixel", p_sys->bpp); msg_Dbg (vd, " %"PRIu8" bits line pad", p_sys->pad); /* Create colormap (needed to select non-default visual) */ xcb_colormap_t cmap; if (vid != scr->root_visual) { cmap = xcb_generate_id (p_sys->conn); xcb_create_colormap (p_sys->conn, XCB_COLORMAP_ALLOC_NONE, cmap, scr->root, vid); } else cmap = scr->default_colormap; /* Create window */ unsigned width, height; if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height)) goto error; p_sys->window = xcb_generate_id (p_sys->conn); p_sys->gc = xcb_generate_id (p_sys->conn); xcb_pixmap_t pixmap = xcb_generate_id (p_sys->conn); { const uint32_t mask = XCB_CW_BACK_PIXMAP | XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; const uint32_t values[] = { /* XCB_CW_BACK_PIXMAP */ pixmap, /* XCB_CW_BACK_PIXEL */ scr->black_pixel, /* XCB_CW_BORDER_PIXMAP */ pixmap, /* XCB_CW_BORDER_PIXEL */ scr->black_pixel, /* XCB_CW_EVENT_MASK */ XCB_EVENT_MASK_VISIBILITY_CHANGE, /* XCB_CW_COLORMAP */ cmap, }; xcb_void_cookie_t c; xcb_create_pixmap (p_sys->conn, p_sys->depth, pixmap, scr->root, 1, 1); c = xcb_create_window_checked (p_sys->conn, p_sys->depth, p_sys->window, p_sys->embed->handle.xid, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vid, mask, values); xcb_map_window (p_sys->conn, p_sys->window); /* Create graphic context (I wonder why the heck do we need this) */ xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL); if (CheckError (vd, p_sys->conn, "cannot create X11 window", c)) goto error; } msg_Dbg (vd, "using X11 window %08"PRIx32, p_sys->window); msg_Dbg (vd, "using X11 graphic context %08"PRIx32, p_sys->gc); p_sys->cursor = CreateBlankCursor (p_sys->conn, scr); p_sys->visible = false; CheckSHM (obj, p_sys->conn, &p_sys->shm); /* */ vout_display_info_t info = vd->info; info.has_pictures_invalid = true; /* Setup vout_display_t once everything is fine */ vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; /* */ vout_display_SendEventFullscreen (vd, false); vout_display_SendEventDisplaySize (vd, width, height, false); return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
/**************************************************************************** * darwin_getTOC: get the TOC ****************************************************************************/ static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev ) { mach_port_t port; char *psz_devname; kern_return_t ret; CDTOC *pTOC = NULL; io_iterator_t iterator; io_registry_entry_t service; CFMutableDictionaryRef properties; CFDataRef data; /* get the device name */ if( ( psz_devname = strrchr( p_vcddev->psz_dev, '/') ) != NULL ) ++psz_devname; else psz_devname = p_vcddev->psz_dev; /* unraw the device name */ if( *psz_devname == 'r' ) ++psz_devname; /* get port for IOKit communication */ if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOMasterPort: 0x%08x", ret ); return( NULL ); } /* get service iterator for the device */ if( ( ret = IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, psz_devname ), &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOServiceGetMatchingServices: 0x%08x", ret ); return( NULL ); } /* first service */ service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); /* search for kIOCDMediaClass */ while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) ) { if( ( ret = IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryGetParentIterator: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } IOObjectRelease( service ); service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); } if( !service ) { msg_Err( p_this, "search for kIOCDMediaClass came up empty" ); return( NULL ); } /* create a CF dictionary containing the TOC */ if( ( ret = IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryCreateCFProperties: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } /* get the TOC from the dictionary */ if( ( data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) ) ) != NULL ) { CFRange range; CFIndex buf_len; buf_len = CFDataGetLength( data ) + 1; range = CFRangeMake( 0, buf_len ); if( ( pTOC = malloc( buf_len ) ) != NULL ) { CFDataGetBytes( data, range, (u_char *)pTOC ); } } else { msg_Err( p_this, "CFDictionaryGetValue failed" ); } CFRelease( properties ); IOObjectRelease( service ); return( pTOC ); }
/***************************************************************************** * Packetize: form dated encapsulation units from anything *****************************************************************************/ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = NULL; int i_flushing = 0; if( pp_block && *pp_block ) { p_block = *pp_block; *pp_block = NULL; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) { /* pre-emptively insert an EOS at a discontinuity, protects * any decoders from any sudden changes */ block_Release( p_block ); p_block = dirac_EmitEOS( p_dec, 0 ); if( p_block ) { p_block->p_next = dirac_EmitEOS( p_dec, 13 ); /* need two EOS to ensure it gets detected by syncro * duplicates get discarded in forming encapsulation unit */ } } else if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) { /* silently discard corruption sentinels, * synchronizer will then discard affected data units. * do not produce an EOS data unit as this is very * disruptive to the stream (and may make a larger error). */ block_Release( p_block ); p_block = NULL; } if( p_block ) block_BytestreamPush( &p_sys->bytestream, p_block ); } /* form as many encapsulation units as possible, give up * when the syncronizer runs out of input data */ while( ( p_block = dirac_DoSync( p_dec ) ) ) { p_block = dirac_BuildEncapsulationUnit( p_dec, p_block ); if( !p_block ) continue; /* add to tail of output queue (ie, not reordered) */ block_ChainLastAppend( &p_sys->pp_outqueue_last, p_block ); /* insert encapsulation unit into timestamp generator * which then calculates some timestamps if required */ i_flushing = dirac_TimeGenPush( p_dec, p_block ); if( i_flushing ) break; } block_t *p_output = NULL; block_t **pp_output = &p_output; /* extract all the dated packets from the head of the output queue */ /* explicitly nondated packets repeat the previous timestamps to * stop vlc discarding them */ while( (p_block = p_sys->p_outqueue) ) { if( p_block->i_flags & DIRAC_DISCARD ) { p_sys->p_outqueue = p_block->p_next; p_block->p_next = NULL; block_Release( p_block ); continue; } if( i_flushing || p_block->i_flags & DIRAC_NON_DATED ) { p_block->i_dts = p_sys->i_dts_last_out; p_block->i_pts = p_sys->i_pts_last_out; } else if( p_block->i_pts <= VLC_TS_INVALID ) break; else if( p_block->i_dts <= VLC_TS_INVALID ) break; p_sys->i_dts_last_out = p_block->i_dts; p_sys->i_pts_last_out = p_block->i_pts; p_sys->p_outqueue = p_block->p_next; p_block->p_next = NULL; /* clear any flags we set */ p_block->i_flags &= ~BLOCK_FLAG_PRIVATE_MASK; block_ChainLastAppend( &pp_output, p_block ); mtime_t i_delay = p_block->i_pts - p_block->i_dts; if( i_delay < 0 ) msg_Err( p_dec, "pts - dts is negative(%"PRId64"): incorrect RoB size", i_delay ); } if( i_flushing ) { p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID; /* reset timegen state (except synchronizer) */ p_sys->b_seen_seq_hdr = false; if( i_flushing < 2 ) { /* this state isn't safe to loose if there was * an unsignalled discontinuity */ p_sys->b_pts = p_sys->b_dts = false; } p_sys->b_tg_last_picnum = false; dirac_ReorderInit( &p_sys->reorder_buf ); assert( p_sys->p_outqueue == NULL ); p_sys->p_out_dts = NULL; } /* perform sanity check: * if there were a block at the front of outqueue that never * satisfied the extraction criteria, but all blocks after did, * the output queue would grow bounded by the stream length. * If there are 10 data units in the output queue, assume this * has happened and purge all blocks that fail extraction criteria */ int i_count; block_ChainProperties( p_sys->p_outqueue, &i_count, NULL, NULL ); if( i_count > 9 ) { p_block = p_sys->p_outqueue; while( p_block ) { block_t *p_block_next = p_block->p_next; if( p_block->i_pts > VLC_TS_INVALID && p_block->i_dts > VLC_TS_INVALID ) break; block_Release( p_block ); p_sys->p_outqueue = p_block = p_block_next; } } if( !p_sys->p_outqueue ) { p_sys->pp_outqueue_last = &p_sys->p_outqueue; } return p_output; }
/* Helpers */ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain, const char *psz_name, config_chain_t *p_cfg, const es_format_t *p_fmt_in, const es_format_t *p_fmt_out ) { chained_filter_t *p_chained = vlc_custom_create( p_chain->p_this, sizeof(*p_chained), VLC_OBJECT_GENERIC, "filter" ); filter_t *p_filter = &p_chained->filter; if( !p_filter ) return NULL; vlc_object_attach( p_filter, p_chain->p_this ); if( !p_fmt_in ) { if( p_chain->last != NULL ) p_fmt_in = &p_chain->last->filter.fmt_out; else p_fmt_in = &p_chain->fmt_in; } if( !p_fmt_out ) { p_fmt_out = &p_chain->fmt_out; } es_format_Copy( &p_filter->fmt_in, p_fmt_in ); es_format_Copy( &p_filter->fmt_out, p_fmt_out ); p_filter->p_cfg = p_cfg; p_filter->b_allow_fmt_out_change = p_chain->b_allow_fmt_out_change; p_filter->p_module = module_need( p_filter, p_chain->psz_capability, psz_name, psz_name != NULL ); if( !p_filter->p_module ) goto error; if( p_filter->b_allow_fmt_out_change ) { es_format_Clean( &p_chain->fmt_out ); es_format_Copy( &p_chain->fmt_out, &p_filter->fmt_out ); } if( AllocatorInit( &p_chain->allocator, p_chained ) ) goto error; if( p_chain->last == NULL ) { assert( p_chain->first == NULL ); p_chain->first = p_chained; } else p_chain->last->next = p_chained; p_chained->prev = p_chain->last; p_chain->last = p_chained; p_chained->next = NULL; p_chain->length++; vlc_mouse_t *p_mouse = malloc( sizeof(*p_mouse) ); if( p_mouse ) vlc_mouse_Init( p_mouse ); p_chained->mouse = p_mouse; msg_Dbg( p_chain->p_this, "Filter '%s' (%p) appended to chain", psz_name ? psz_name : module_get_name(p_filter->p_module, false), p_filter ); return p_filter; error: if( psz_name ) msg_Err( p_chain->p_this, "Failed to create %s '%s'", p_chain->psz_capability, psz_name ); else msg_Err( p_chain->p_this, "Failed to create %s", p_chain->psz_capability ); if( p_filter->p_module ) module_unneed( p_filter, p_filter->p_module ); es_format_Clean( &p_filter->fmt_in ); es_format_Clean( &p_filter->fmt_out ); vlc_object_release( p_filter ); return NULL; }
/***************************************************************************** * aout_OutputNew : allocate a new output and rework the filter pipeline ***************************************************************************** * This function is entered with the mixer lock. *****************************************************************************/ int aout_OutputNew( aout_instance_t * p_aout, audio_sample_format_t * p_format ) { /* Retrieve user defaults. */ int i_rate = config_GetInt( p_aout, "aout-rate" ); vlc_value_t val, text; /* kludge to avoid a fpu error when rate is 0... */ if( i_rate == 0 ) i_rate = -1; memcpy( &p_aout->output.output, p_format, sizeof(audio_sample_format_t) ); if ( i_rate != -1 ) p_aout->output.output.i_rate = i_rate; aout_FormatPrepare( &p_aout->output.output ); aout_lock_output_fifo( p_aout ); /* Find the best output plug-in. */ p_aout->output.p_module = module_Need( p_aout, "audio output", "$aout", 0); if ( p_aout->output.p_module == NULL ) { msg_Err( p_aout, "no suitable audio output module" ); aout_unlock_output_fifo( p_aout ); return -1; } if ( var_Type( p_aout, "audio-channels" ) == (VLC_VAR_INTEGER | VLC_VAR_HASCHOICE) ) { /* The user may have selected a different channels configuration. */ var_Get( p_aout, "audio-channels", &val ); if ( val.i_int == AOUT_VAR_CHAN_RSTEREO ) { p_aout->output.output.i_original_channels |= AOUT_CHAN_REVERSESTEREO; } else if ( val.i_int == AOUT_VAR_CHAN_STEREO ) { p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } else if ( val.i_int == AOUT_VAR_CHAN_LEFT ) { p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT; } else if ( val.i_int == AOUT_VAR_CHAN_RIGHT ) { p_aout->output.output.i_original_channels = AOUT_CHAN_RIGHT; } else if ( val.i_int == AOUT_VAR_CHAN_DOLBYS ) { p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DOLBYSTEREO; } } else if ( p_aout->output.output.i_physical_channels == AOUT_CHAN_CENTER && (p_aout->output.output.i_original_channels & AOUT_CHAN_PHYSMASK) == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) ) { /* Mono - create the audio-channels variable. */ var_Create( p_aout, "audio-channels", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = _("Audio Channels"); var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL ); val.i_int = AOUT_VAR_CHAN_STEREO; text.psz_string = _("Stereo"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DUALMONO ) { /* Go directly to the left channel. */ p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT; val.i_int = AOUT_VAR_CHAN_LEFT; var_Set( p_aout, "audio-channels", val ); } var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart, NULL ); } else if ( p_aout->output.output.i_physical_channels == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) && (p_aout->output.output.i_original_channels & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) ) { /* Stereo - create the audio-channels variable. */ var_Create( p_aout, "audio-channels", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = _("Audio Channels"); var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL ); if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DOLBYSTEREO ) { val.i_int = AOUT_VAR_CHAN_DOLBYS; text.psz_string = _("Dolby Surround"); } else { val.i_int = AOUT_VAR_CHAN_STEREO; text.psz_string = _("Stereo"); } var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); val.i_int = AOUT_VAR_CHAN_RSTEREO; text.psz_string=_("Reverse stereo"); var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text ); if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DUALMONO ) { /* Go directly to the left channel. */ p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT; val.i_int = AOUT_VAR_CHAN_LEFT; var_Set( p_aout, "audio-channels", val ); } var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart, NULL ); } val.b_bool = true; var_Set( p_aout, "intf-change", val ); aout_FormatPrepare( &p_aout->output.output ); /* Prepare FIFO. */ aout_FifoInit( p_aout, &p_aout->output.fifo, p_aout->output.output.i_rate ); aout_unlock_output_fifo( p_aout ); aout_FormatPrint( p_aout, "output", &p_aout->output.output ); /* Calculate the resulting mixer output format. */ memcpy( &p_aout->mixer.mixer, &p_aout->output.output, sizeof(audio_sample_format_t) ); if ( !AOUT_FMT_NON_LINEAR(&p_aout->output.output) ) { /* Non-S/PDIF mixer only deals with float32 or fixed32. */ p_aout->mixer.mixer.i_format = (vlc_CPU() & CPU_CAPABILITY_FPU) ? VLC_FOURCC('f','l','3','2') : VLC_FOURCC('f','i','3','2'); aout_FormatPrepare( &p_aout->mixer.mixer ); } else { p_aout->mixer.mixer.i_format = p_format->i_format; } aout_FormatPrint( p_aout, "mixer", &p_aout->mixer.mixer ); /* Create filters. */ p_aout->output.i_nb_filters = 0; if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters, &p_aout->output.i_nb_filters, &p_aout->mixer.mixer, &p_aout->output.output ) < 0 ) { msg_Err( p_aout, "couldn't create audio output pipeline" ); module_Unneed( p_aout, p_aout->output.p_module ); return -1; } /* Prepare hints for the buffer allocator. */ p_aout->mixer.output_alloc.i_alloc_type = AOUT_ALLOC_HEAP; p_aout->mixer.output_alloc.i_bytes_per_sec = p_aout->mixer.mixer.i_bytes_per_frame * p_aout->mixer.mixer.i_rate / p_aout->mixer.mixer.i_frame_length; aout_FiltersHintBuffers( p_aout, p_aout->output.pp_filters, p_aout->output.i_nb_filters, &p_aout->mixer.output_alloc ); p_aout->output.b_error = 0; return 0; }
void MainInterface::createTaskBarButtons() { taskbar_wmsg = WM_NULL; /*Here is the code for the taskbar thumb buttons FIXME:We need pretty buttons in 16x16 px that are handled correctly by masks in Qt FIXME:the play button's picture doesn't changed to pause when clicked */ CoInitialize( 0 ); if( S_OK == CoCreateInstance( &clsid_ITaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&p_taskbl) ) { p_taskbl->vt->HrInit(p_taskbl); if( (himl = ImageList_Create( 20, //cx 20, //cy ILC_COLOR32,//flags 4,//initial nb of images 0//nb of images that can be added ) ) != NULL ) { QPixmap img = QPixmap(":/win7/prev"); QPixmap img2 = QPixmap(":/win7/pause"); QPixmap img3 = QPixmap(":/win7/play"); QPixmap img4 = QPixmap(":/win7/next"); QBitmap mask = img.createMaskFromColor(Qt::transparent); QBitmap mask2 = img2.createMaskFromColor(Qt::transparent); QBitmap mask3 = img3.createMaskFromColor(Qt::transparent); QBitmap mask4 = img4.createMaskFromColor(Qt::transparent); if(-1 == ImageList_Add(himl, img.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask.toWinHBITMAP())) msg_Err( p_intf, "First ImageList_Add failed" ); if(-1 == ImageList_Add(himl, img2.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask2.toWinHBITMAP())) msg_Err( p_intf, "Second ImageList_Add failed" ); if(-1 == ImageList_Add(himl, img3.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask3.toWinHBITMAP())) msg_Err( p_intf, "Third ImageList_Add failed" ); if(-1 == ImageList_Add(himl, img4.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask4.toWinHBITMAP())) msg_Err( p_intf, "Fourth ImageList_Add failed" ); } // Define an array of two buttons. These buttons provide images through an // image list and also provide tooltips. DWORD dwMask = THB_BITMAP | THB_FLAGS; THUMBBUTTON thbButtons[3]; thbButtons[0].dwMask = dwMask; thbButtons[0].iId = 0; thbButtons[0].iBitmap = 0; thbButtons[0].dwFlags = THBF_HIDDEN; thbButtons[1].dwMask = dwMask; thbButtons[1].iId = 1; thbButtons[1].iBitmap = 2; thbButtons[1].dwFlags = THBF_HIDDEN; thbButtons[2].dwMask = dwMask; thbButtons[2].iId = 2; thbButtons[2].iBitmap = 3; thbButtons[2].dwFlags = THBF_HIDDEN; HRESULT hr = p_taskbl->vt->ThumbBarSetImageList(p_taskbl, winId(), himl ); if(S_OK != hr) msg_Err( p_intf, "ThumbBarSetImageList failed with error %08lx", hr ); else { hr = p_taskbl->vt->ThumbBarAddButtons(p_taskbl, winId(), 3, thbButtons); if(S_OK != hr) msg_Err( p_intf, "ThumbBarAddButtons failed with error %08lx", hr ); } CONNECT( THEMIM->getIM(), playingStatusChanged( int ), this, changeThumbbarButtons( int ) ); }
static sout_stream_id_sys_t * Add( sout_stream_t *p_stream, const es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; bridge_t *p_bridge; bridged_es_t *p_es; char *psz_chain; int i; if( p_sys->b_inited || p_fmt->i_cat != VIDEO_ES ) return NULL; /* Create decoder object */ p_sys->p_decoder = vlc_object_create( p_stream, sizeof( decoder_t ) ); if( !p_sys->p_decoder ) return NULL; p_sys->p_decoder->p_module = NULL; p_sys->p_decoder->fmt_in = *p_fmt; p_sys->p_decoder->b_frame_drop_allowed = true; p_sys->p_decoder->fmt_out = p_sys->p_decoder->fmt_in; p_sys->p_decoder->fmt_out.i_extra = 0; p_sys->p_decoder->fmt_out.p_extra = 0; p_sys->p_decoder->pf_decode_video = 0; p_sys->p_decoder->pf_vout_format_update = video_update_format_decoder; p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder; p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) ); if( !p_sys->p_decoder->p_owner ) { vlc_object_release( p_sys->p_decoder ); return NULL; } p_sys->p_decoder->p_owner->video = p_fmt->video; //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg; p_sys->p_decoder->p_module = module_need( p_sys->p_decoder, "decoder", "$codec", false ); if( !p_sys->p_decoder->p_module || !p_sys->p_decoder->pf_decode_video ) { if( p_sys->p_decoder->p_module ) { msg_Err( p_stream, "instanciated a non video decoder" ); module_unneed( p_sys->p_decoder, p_sys->p_decoder->p_module ); } else { msg_Err( p_stream, "cannot find decoder" ); } free( p_sys->p_decoder->p_owner ); vlc_object_release( p_sys->p_decoder ); return NULL; } p_sys->b_inited = true; vlc_global_lock( VLC_MOSAIC_MUTEX ); p_bridge = GetBridge( p_stream ); if ( p_bridge == NULL ) { vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->obj.libvlc ); vlc_value_t val; p_bridge = xmalloc( sizeof( bridge_t ) ); var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS ); val.p_address = p_bridge; var_Set( p_libvlc, "mosaic-struct", val ); p_bridge->i_es_num = 0; p_bridge->pp_es = NULL; } for ( i = 0; i < p_bridge->i_es_num; i++ ) { if ( p_bridge->pp_es[i]->b_empty ) break; } if ( i == p_bridge->i_es_num ) { p_bridge->pp_es = xrealloc( p_bridge->pp_es, (p_bridge->i_es_num + 1) * sizeof(bridged_es_t *) ); p_bridge->i_es_num++; p_bridge->pp_es[i] = xmalloc( sizeof(bridged_es_t) ); } p_sys->p_es = p_es = p_bridge->pp_es[i]; p_es->i_alpha = var_GetInteger( p_stream, CFG_PREFIX "alpha" ); p_es->i_x = var_GetInteger( p_stream, CFG_PREFIX "x" ); p_es->i_y = var_GetInteger( p_stream, CFG_PREFIX "y" ); //p_es->fmt = *p_fmt; p_es->psz_id = p_sys->psz_id; p_es->p_picture = NULL; p_es->pp_last = &p_es->p_picture; p_es->b_empty = false; vlc_global_unlock( VLC_MOSAIC_MUTEX ); if ( p_sys->i_height || p_sys->i_width ) { p_sys->p_image = image_HandlerCreate( p_stream ); } else { p_sys->p_image = NULL; } msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i ); /* Create user specified video filters */ psz_chain = var_GetNonEmptyString( p_stream, CFG_PREFIX "vfilter" ); msg_Dbg( p_stream, "psz_chain: %s", psz_chain ); if( psz_chain ) { filter_owner_t owner = { .sys = p_sys->p_decoder->p_owner, .video = { .buffer_new = video_new_buffer_filter, }, }; p_sys->p_vf2 = filter_chain_NewVideo( p_stream, false, &owner ); es_format_t fmt; es_format_Copy( &fmt, &p_sys->p_decoder->fmt_out ); if( p_sys->i_chroma ) fmt.video.i_chroma = p_sys->i_chroma; filter_chain_Reset( p_sys->p_vf2, &fmt, &fmt ); filter_chain_AppendFromString( p_sys->p_vf2, psz_chain ); free( psz_chain ); } else {
/***************************************************************************** * Open: open a scope effect plugin *****************************************************************************/ static int Open( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; goom_thread_t *p_thread; video_format_t fmt; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) ); /* Create goom thread */ p_sys->p_thread = p_thread = calloc( 1, sizeof(*p_thread) ); const int width = p_thread->i_width = var_InheritInteger( p_filter, "goom-width" ); const int height = p_thread->i_height = var_InheritInteger( p_filter, "goom-height" ); memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_width = fmt.i_visible_width = width; fmt.i_height = fmt.i_visible_height = height; fmt.i_chroma = VLC_CODEC_RGB32; fmt.i_sar_num = fmt.i_sar_den = 1; p_thread->p_vout = aout_filter_RequestVout( p_filter, NULL, &fmt ); if( p_thread->p_vout == NULL ) { msg_Err( p_filter, "no suitable vout module" ); free( p_thread ); free( p_sys ); return VLC_EGENERIC; } p_thread->i_speed = MAX_SPEED - var_InheritInteger( p_filter, "goom-speed" ); if( p_thread->i_speed < 0 ) p_thread->i_speed = 0; vlc_mutex_init( &p_thread->lock ); vlc_cond_init( &p_thread->wait ); p_thread->i_blocks = 0; date_Init( &p_thread->date, p_filter->fmt_in.audio.i_rate, 1 ); date_Set( &p_thread->date, 0 ); p_thread->i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); if( vlc_clone( &p_thread->thread, Thread, p_thread, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_filter, "cannot lauch goom thread" ); vlc_mutex_destroy( &p_thread->lock ); vlc_cond_destroy( &p_thread->wait ); aout_filter_RequestVout( p_filter, p_thread->p_vout, NULL ); free( p_thread ); free( p_sys ); return VLC_EGENERIC; } p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; }
/***************************************************************************** * ProcessHeaders: process Theora headers. *****************************************************************************/ static int ProcessHeaders( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; ogg_packet oggpacket; unsigned pi_size[XIPH_MAX_HEADER_COUNT]; void *pp_data[XIPH_MAX_HEADER_COUNT]; unsigned i_count; if( xiph_SplitHeaders( pi_size, pp_data, &i_count, p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) ) return VLC_EGENERIC; if( i_count < 3 ) goto error; oggpacket.granulepos = -1; oggpacket.e_o_s = 0; oggpacket.packetno = 0; /* Take care of the initial Vorbis header */ oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ oggpacket.bytes = pi_size[0]; oggpacket.packet = pp_data[0]; if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { msg_Err( p_dec, "this bitstream does not contain Theora video data" ); goto error; } /* Set output properties */ if( !p_sys->b_packetizer ) switch( p_sys->ti.pixelformat ) { case OC_PF_420: p_dec->fmt_out.i_codec = VLC_CODEC_I420; break; case OC_PF_422: p_dec->fmt_out.i_codec = VLC_CODEC_I422; break; case OC_PF_444: p_dec->fmt_out.i_codec = VLC_CODEC_I444; break; case OC_PF_RSVD: default: msg_Err( p_dec, "unknown chroma in theora sample" ); break; } p_dec->fmt_out.video.i_width = p_sys->ti.width; p_dec->fmt_out.video.i_height = p_sys->ti.height; if( p_sys->ti.frame_width && p_sys->ti.frame_height ) { p_dec->fmt_out.video.i_visible_width = p_sys->ti.frame_width; p_dec->fmt_out.video.i_visible_height = p_sys->ti.frame_height; if( p_sys->ti.offset_x || p_sys->ti.offset_y ) { p_dec->fmt_out.video.i_x_offset = p_sys->ti.offset_x; p_dec->fmt_out.video.i_y_offset = p_sys->ti.offset_y; } } if( p_sys->ti.aspect_denominator && p_sys->ti.aspect_numerator ) { p_dec->fmt_out.video.i_sar_num = p_sys->ti.aspect_numerator; p_dec->fmt_out.video.i_sar_den = p_sys->ti.aspect_denominator; } else { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } if( p_sys->ti.fps_numerator > 0 && p_sys->ti.fps_denominator > 0 ) { p_dec->fmt_out.video.i_frame_rate = p_sys->ti.fps_numerator; p_dec->fmt_out.video.i_frame_rate_base = p_sys->ti.fps_denominator; } msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content " "is %dx%d with offset (%d,%d)", p_sys->ti.width, p_sys->ti.height, (double)p_sys->ti.fps_numerator/p_sys->ti.fps_denominator, p_sys->ti.frame_width, p_sys->ti.frame_height, p_sys->ti.offset_x, p_sys->ti.offset_y ); /* Sanity check that seems necessary for some corrupted files */ if( p_sys->ti.width < p_sys->ti.frame_width || p_sys->ti.height < p_sys->ti.frame_height ) { msg_Warn( p_dec, "trying to correct invalid theora header " "(frame size (%dx%d) is smaller than frame content (%d,%d))", p_sys->ti.width, p_sys->ti.height, p_sys->ti.frame_width, p_sys->ti.frame_height ); if( p_sys->ti.width < p_sys->ti.frame_width ) p_sys->ti.width = p_sys->ti.frame_width; if( p_sys->ti.height < p_sys->ti.frame_height ) p_sys->ti.height = p_sys->ti.frame_height; } /* The next packet in order is the comments header */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[1]; oggpacket.packet = pp_data[1]; if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { msg_Err( p_dec, "2nd Theora header is corrupted" ); goto error; } ParseTheoraComments( p_dec ); /* The next packet in order is the codebooks header * We need to watch out that this packet is not missing as a * missing or corrupted header is fatal. */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[2]; oggpacket.packet = pp_data[2]; if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { msg_Err( p_dec, "3rd Theora header is corrupted" ); goto error; } if( !p_sys->b_packetizer ) { /* We have all the headers, initialize decoder */ theora_decode_init( &p_sys->td, &p_sys->ti ); } else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); } for( unsigned i = 0; i < i_count; i++ ) free( pp_data[i] ); return VLC_SUCCESS; error: for( unsigned i = 0; i < i_count; i++ ) free( pp_data[i] ); return VLC_EGENERIC; }
/***************************************************************************** * OpenAudio: *****************************************************************************/ static int OpenAudio( decoder_t *p_dec ) { decoder_sys_t *p_sys; int i_error; char fcc[4]; unsigned long WantedBufferSize; unsigned long InputBufferSize = 0; unsigned long OutputBufferSize = 0; /* get lock, avoid segfault */ vlc_mutex_lock( &qt_mutex ); p_sys = calloc( 1, sizeof( decoder_sys_t ) ); p_dec->p_sys = p_sys; p_dec->pf_decode_audio = DecodeAudio; if( p_dec->fmt_in.i_original_fourcc ) memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 ); else memcpy( fcc, &p_dec->fmt_in.i_codec, 4 ); #ifdef __APPLE__ EnterMovies(); #endif if( QTAudioInit( p_dec ) ) { msg_Err( p_dec, "cannot initialize QT"); goto exit_error; } #ifndef __APPLE__ if( ( i_error = p_sys->InitializeQTML( 6 + 16 ) ) ) { msg_Dbg( p_dec, "error on InitializeQTML = %d", i_error ); goto exit_error; } #endif /* input format settings */ p_sys->InputFormatInfo.flags = 0; p_sys->InputFormatInfo.sampleCount = 0; p_sys->InputFormatInfo.buffer = NULL; p_sys->InputFormatInfo.reserved = 0; p_sys->InputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels; p_sys->InputFormatInfo.sampleSize = p_dec->fmt_in.audio.i_bitspersample; p_sys->InputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate; p_sys->InputFormatInfo.format = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); /* output format settings */ p_sys->OutputFormatInfo.flags = 0; p_sys->OutputFormatInfo.sampleCount = 0; p_sys->OutputFormatInfo.buffer = NULL; p_sys->OutputFormatInfo.reserved = 0; p_sys->OutputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels; p_sys->OutputFormatInfo.sampleSize = 16; p_sys->OutputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate; p_sys->OutputFormatInfo.format = FCC( 'N', 'O', 'N', 'E' ); i_error = p_sys->SoundConverterOpen( &p_sys->InputFormatInfo, &p_sys->OutputFormatInfo, &p_sys->myConverter ); if( i_error ) { msg_Err( p_dec, "error on SoundConverterOpen = %d", i_error ); goto exit_error; } #if 0 /* tell the sound converter we accept VBR formats */ i_error = SoundConverterSetInfo( p_dec->myConverter, siClientAcceptsVBR, (void *)true ); #endif if( p_dec->fmt_in.i_extra > 36 + 8 ) { i_error = p_sys->SoundConverterSetInfo( p_sys->myConverter, FCC( 'w', 'a', 'v', 'e' ), ((uint8_t*)p_dec->fmt_in.p_extra) + 36 + 8 ); msg_Dbg( p_dec, "error on SoundConverterSetInfo = %d", i_error ); } WantedBufferSize = p_sys->OutputFormatInfo.numChannels * p_sys->OutputFormatInfo.sampleRate * 2; p_sys->FramesToGet = 0; i_error = p_sys->SoundConverterGetBufferSizes( p_sys->myConverter, WantedBufferSize, &p_sys->FramesToGet, &InputBufferSize, &OutputBufferSize ); msg_Dbg( p_dec, "WantedBufferSize=%li InputBufferSize=%li " "OutputBufferSize=%li FramesToGet=%li", WantedBufferSize, InputBufferSize, OutputBufferSize, p_sys->FramesToGet ); p_sys->InFrameSize = (InputBufferSize + p_sys->FramesToGet - 1 ) / p_sys->FramesToGet; p_sys->OutFrameSize = OutputBufferSize / p_sys->FramesToGet; msg_Dbg( p_dec, "frame size %d -> %d", p_sys->InFrameSize, p_sys->OutFrameSize ); if( (i_error = p_sys->SoundConverterBeginConversion(p_sys->myConverter)) ) { msg_Err( p_dec, "error on SoundConverterBeginConversion = %d", i_error ); goto exit_error; } es_format_Init( &p_dec->fmt_out, AUDIO_ES, VLC_CODEC_S16N ); p_dec->fmt_out.audio.i_rate = p_sys->OutputFormatInfo.sampleRate; p_dec->fmt_out.audio.i_channels = p_sys->OutputFormatInfo.numChannels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_sys->OutputFormatInfo.numChannels]; date_Init( &p_sys->date, p_dec->fmt_out.audio.i_rate, 1 ); p_sys->i_buffer = 0; p_sys->i_buffer_size = 100*1000; p_sys->p_buffer = malloc( p_sys->i_buffer_size ); if( !p_sys->p_buffer ) goto exit_error; p_sys->i_out = 0; p_sys->i_out_frames = 0; vlc_mutex_unlock( &qt_mutex ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( &qt_mutex ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Open: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *) p_this; decoder_sys_t *p_sys = NULL; if( p_dec->fmt_in.i_codec != VLC_CODEC_TELETEXT ) return VLC_EGENERIC; p_dec->pf_decode_sub = Decode; p_sys = p_dec->p_sys = calloc( 1, sizeof(decoder_sys_t) ); if( p_sys == NULL ) return VLC_ENOMEM; p_sys->i_key[0] = p_sys->i_key[1] = p_sys->i_key[2] = '*' - '0'; p_sys->b_update = false; p_sys->p_vbi_dec = vbi_decoder_new(); vlc_mutex_init( &p_sys->lock ); if( p_sys->p_vbi_dec == NULL ) { msg_Err( p_dec, "VBI decoder could not be created." ); Close( p_this ); return VLC_ENOMEM; } /* Some broadcasters in countries with level 1 and level 1.5 still not send a G0 to do * matches against table 32 of ETSI 300 706. We try to do some best effort guessing * This is not perfect, but might handle some cases where we know the vbi language * is known. It would be better if people started sending G0 */ for( int i = 0; ppsz_default_triplet[i] != NULL; i++ ) { if( p_dec->fmt_in.psz_language && !strcasecmp( p_dec->fmt_in.psz_language, ppsz_default_triplet[i] ) ) { vbi_teletext_set_default_region( p_sys->p_vbi_dec, pi_default_triplet[i]); msg_Dbg( p_dec, "overwriting default zvbi region: %d", pi_default_triplet[i] ); } } vbi_event_handler_register( p_sys->p_vbi_dec, VBI_EVENT_TTX_PAGE | VBI_EVENT_NETWORK | #ifdef ZVBI_DEBUG VBI_EVENT_CAPTION | VBI_EVENT_TRIGGER | VBI_EVENT_ASPECT | VBI_EVENT_PROG_INFO | VBI_EVENT_NETWORK_ID | #endif 0 , EventHandler, p_dec ); /* Create the var on vlc_global. */ p_sys->i_wanted_page = var_CreateGetInteger( p_dec, "vbi-page" ); var_AddCallback( p_dec, "vbi-page", RequestPage, p_sys ); /* Check if the Teletext track has a known "initial page". */ if( p_sys->i_wanted_page == 100 && p_dec->fmt_in.subs.teletext.i_magazine != -1 ) { p_sys->i_wanted_page = 100 * p_dec->fmt_in.subs.teletext.i_magazine + vbi_bcd2dec( p_dec->fmt_in.subs.teletext.i_page ); var_SetInteger( p_dec, "vbi-page", p_sys->i_wanted_page ); } p_sys->i_wanted_subpage = VBI_ANY_SUBNO; p_sys->b_opaque = var_CreateGetBool( p_dec, "vbi-opaque" ); var_AddCallback( p_dec, "vbi-opaque", Opaque, p_sys ); p_sys->i_align = var_CreateGetInteger( p_dec, "vbi-position" ); var_AddCallback( p_dec, "vbi-position", Position, p_sys ); p_sys->b_text = var_CreateGetBool( p_dec, "vbi-text" ); // var_AddCallback( p_dec, "vbi-text", Text, p_sys ); /* Listen for keys */ var_AddCallback( p_dec->p_libvlc, "key-pressed", EventKey, p_dec ); es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_CODEC_SPU ); if( p_sys->b_text ) p_dec->fmt_out.video.i_chroma = VLC_CODEC_TEXT; else p_dec->fmt_out.video.i_chroma = VLC_CODEC_RGBA; return VLC_SUCCESS; }
/***************************************************************************** * QTAudioInit: *****************************************************************************/ static int QTAudioInit( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; #ifdef __APPLE__ p_sys->SoundConverterOpen = (void*)SoundConverterOpen; p_sys->SoundConverterClose = (void*)SoundConverterClose; p_sys->SoundConverterSetInfo = (void*)SoundConverterSetInfo; p_sys->SoundConverterGetBufferSizes = (void*)SoundConverterGetBufferSizes; p_sys->SoundConverterConvertBuffer = (void*)SoundConverterConvertBuffer; p_sys->SoundConverterBeginConversion= (void*)SoundConverterBeginConversion; p_sys->SoundConverterEndConversion = (void*)SoundConverterEndConversion; #else #ifdef LOADER p_sys->ldt_fs = Setup_LDT_Keeper(); #endif /* LOADER */ p_sys->qts = LoadLibraryA( "QuickTime.qts" ); if( p_sys->qts == NULL ) { msg_Dbg( p_dec, "failed loading QuickTime.qts" ); return VLC_EGENERIC; } p_sys->qtml = LoadLibraryA( "qtmlClient.dll" ); if( p_sys->qtml == NULL ) { msg_Dbg( p_dec, "failed loading qtmlClient.dll" ); return VLC_EGENERIC; } p_sys->InitializeQTML = (void *)GetProcAddress( p_sys->qtml, "InitializeQTML" ); p_sys->TerminateQTML = (void *)GetProcAddress( p_sys->qtml, "TerminateQTML" ); p_sys->SoundConverterOpen = (void *)GetProcAddress( p_sys->qtml, "SoundConverterOpen" ); p_sys->SoundConverterClose = (void *)GetProcAddress( p_sys->qtml, "SoundConverterClose" ); p_sys->SoundConverterSetInfo = (void *)GetProcAddress( p_sys->qtml, "SoundConverterSetInfo" ); p_sys->SoundConverterGetBufferSizes = (void *)GetProcAddress( p_sys->qtml, "SoundConverterGetBufferSizes" ); p_sys->SoundConverterConvertBuffer = (void *)GetProcAddress( p_sys->qtml, "SoundConverterConvertBuffer" ); p_sys->SoundConverterEndConversion = (void *)GetProcAddress( p_sys->qtml, "SoundConverterEndConversion" ); p_sys->SoundConverterBeginConversion= (void *)GetProcAddress( p_sys->qtml, "SoundConverterBeginConversion"); if( p_sys->InitializeQTML == NULL ) { msg_Err( p_dec, "failed getting proc address InitializeQTML" ); return VLC_EGENERIC; } if( p_sys->SoundConverterOpen == NULL || p_sys->SoundConverterClose == NULL || p_sys->SoundConverterSetInfo == NULL || p_sys->SoundConverterGetBufferSizes == NULL || p_sys->SoundConverterConvertBuffer == NULL || p_sys->SoundConverterEndConversion == NULL || p_sys->SoundConverterBeginConversion == NULL ) { msg_Err( p_dec, "failed getting proc address" ); return VLC_EGENERIC; } msg_Dbg( p_dec, "standard init done" ); #endif /* else __APPLE__ */ return VLC_SUCCESS; }
/***************************************************************************** * ioctl_GetTracksMap: Read the Table of Content, fill in the pp_sectors map * if pp_sectors is not null and return the number of * tracks available. *****************************************************************************/ int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev, int **pp_sectors ) { int i_tracks = 0; if( p_vcddev->i_vcdimage_handle != -1 ) { /* * vcd image mode */ i_tracks = p_vcddev->i_tracks; if( pp_sectors ) { *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) return 0; memcpy( *pp_sectors, p_vcddev->p_sectors, (i_tracks + 1) * sizeof(**pp_sectors) ); } return i_tracks; } else { /* * vcd device mode */ #if defined( __APPLE__ ) CDTOC *pTOC; int i_descriptors; if( ( pTOC = darwin_getTOC( p_this, p_vcddev ) ) == NULL ) { msg_Err( p_this, "failed to get the TOC" ); return 0; } i_descriptors = CDTOCGetDescriptorCount( pTOC ); i_tracks = darwin_getNumberOfTracks( pTOC, i_descriptors ); if( pp_sectors ) { int i, i_leadout = -1; CDTOCDescriptor *pTrackDescriptors; u_char track; *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) { darwin_freeTOC( pTOC ); return 0; } pTrackDescriptors = pTOC->descriptors; for( i_tracks = 0, i = 0; i < i_descriptors; i++ ) { track = pTrackDescriptors[i].point; if( track == 0xA2 ) i_leadout = i; if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO ) continue; (*pp_sectors)[i_tracks++] = CDConvertMSFToLBA( pTrackDescriptors[i].p ); } if( i_leadout == -1 ) { msg_Err( p_this, "leadout not found" ); free( *pp_sectors ); darwin_freeTOC( pTOC ); return 0; } /* set leadout sector */ (*pp_sectors)[i_tracks] = CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p ); } darwin_freeTOC( pTOC ); #elif defined( WIN32 ) DWORD dwBytesReturned; CDROM_TOC cdrom_toc; if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_READ_TOC, NULL, 0, &cdrom_toc, sizeof(CDROM_TOC), &dwBytesReturned, NULL ) == 0 ) { msg_Err( p_this, "could not read TOCHDR" ); return 0; } i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1; if( pp_sectors ) { *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) return 0; for( int i = 0 ; i <= i_tracks ; i++ ) { (*pp_sectors)[ i ] = MSF_TO_LBA2( cdrom_toc.TrackData[i].Address[1], cdrom_toc.TrackData[i].Address[2], cdrom_toc.TrackData[i].Address[3] ); msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]); } } #elif defined( __OS2__ ) cdrom_get_tochdr_t get_tochdr = {{'C', 'D', '0', '1'}}; cdrom_tochdr_t tochdr; ULONG param_len; ULONG data_len; ULONG rc; rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIODISK, &get_tochdr, sizeof( get_tochdr ), ¶m_len, &tochdr, sizeof( tochdr ), &data_len ); if( rc ) { msg_Err( p_this, "could not read TOCHDR" ); return 0; } i_tracks = tochdr.last_track - tochdr.first_track + 1; if( pp_sectors ) { cdrom_get_track_t get_track = {{'C', 'D', '0', '1'}, }; cdrom_track_t track; int i; *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) return 0; for( i = 0 ; i < i_tracks ; i++ ) { get_track.track = tochdr.first_track + i; rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOTRACK, &get_track, sizeof(get_track), ¶m_len, &track, sizeof(track), &data_len ); if (rc) { msg_Err( p_this, "could not read %d track", get_track.track ); return 0; } (*pp_sectors)[ i ] = MSF_TO_LBA2( track.start.minute, track.start.second, track.start.frame ); msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]); } /* for lead-out track */ (*pp_sectors)[ i ] = MSF_TO_LBA2( tochdr.lead_out.minute, tochdr.lead_out.second, tochdr.lead_out.frame ); msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]); } #elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H ) \ || defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H ) struct ioc_toc_header tochdr; struct ioc_read_toc_entry toc_entries; if( ioctl( p_vcddev->i_device_handle, CDIOREADTOCHEADER, &tochdr ) == -1 ) { msg_Err( p_this, "could not read TOCHDR" ); return 0; } i_tracks = tochdr.ending_track - tochdr.starting_track + 1; if( pp_sectors ) { int i; *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) return 0; toc_entries.address_format = CD_LBA_FORMAT; toc_entries.starting_track = 0; toc_entries.data_len = ( i_tracks + 1 ) * sizeof( struct cd_toc_entry ); toc_entries.data = (struct cd_toc_entry *) malloc( toc_entries.data_len ); if( toc_entries.data == NULL ) { free( *pp_sectors ); return 0; } /* Read the TOC */ if( ioctl( p_vcddev->i_device_handle, CDIOREADTOCENTRYS, &toc_entries ) == -1 ) { msg_Err( p_this, "could not read the TOC" ); free( *pp_sectors ); free( toc_entries.data ); return 0; } /* Fill the p_sectors structure with the track/sector matches */ for( i = 0 ; i <= i_tracks ; i++ ) { #if defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H ) /* FIXME: is this ok? */ (*pp_sectors)[ i ] = toc_entries.data[i].addr.lba; #else (*pp_sectors)[ i ] = ntohl( toc_entries.data[i].addr.lba ); #endif } } #else struct cdrom_tochdr tochdr; struct cdrom_tocentry tocent; /* First we read the TOC header */ if( ioctl( p_vcddev->i_device_handle, CDROMREADTOCHDR, &tochdr ) == -1 ) { msg_Err( p_this, "could not read TOCHDR" ); return 0; } i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; if( pp_sectors ) { int i; *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) ); if( *pp_sectors == NULL ) return 0; /* Fill the p_sectors structure with the track/sector matches */ for( i = 0 ; i <= i_tracks ; i++ ) { tocent.cdte_format = CDROM_LBA; tocent.cdte_track = ( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i; if( ioctl( p_vcddev->i_device_handle, CDROMREADTOCENTRY, &tocent ) == -1 ) { msg_Err( p_this, "could not read TOCENTRY" ); free( *pp_sectors ); return 0; } (*pp_sectors)[ i ] = tocent.cdte_addr.lba; } } #endif return i_tracks; } }
static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, subpicture_region_t *p_region_in, const vlc_fourcc_t *p_chroma_list ) { filter_sys_t *p_sys = p_filter->p_sys; int i_font_color, i_font_alpha, i_font_size; uint8_t *p_bitmap; TCHAR *psz_string; int i, i_width, i_height; HBITMAP bitmap, bitmap_bak; BITMAPINFO *p_bmi; RECT rect = { 0, 0, 0, 0 }; /* Sanity check */ if( !p_region_in || !p_region_out ) return VLC_EGENERIC; if( !p_region_in->psz_text || !*p_region_in->psz_text ) return VLC_EGENERIC; psz_string = ToT(p_region_in->psz_text); if( psz_string == NULL ) return VLC_EGENERIC; if( !*psz_string ) { free( psz_string ); return VLC_EGENERIC; } if( p_region_in->p_style ) { i_font_color = VLC_CLIP( p_region_in->p_style->i_font_color, 0, 0xFFFFFF ); i_font_alpha = VLC_CLIP( p_region_in->p_style->i_font_alpha, 0, 255 ); i_font_size = VLC_CLIP( p_region_in->p_style->i_font_size, 0, 255 ); } else { i_font_color = p_sys->i_font_color; i_font_alpha = 255 - p_sys->i_font_opacity; i_font_size = p_sys->i_default_font_size; } SetFont( p_filter, i_font_size ); SetTextColor( p_sys->hcdc, RGB( (i_font_color >> 16) & 0xff, (i_font_color >> 8) & 0xff, i_font_color & 0xff) ); DrawText( p_sys->hcdc, psz_string, -1, &rect, DT_CALCRECT | DT_CENTER | DT_NOPREFIX ); i_width = rect.right; i_height = rect.bottom; p_bmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*16); memset( p_bmi, 0, sizeof(BITMAPINFOHEADER) ); p_bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); p_bmi->bmiHeader.biWidth = (i_width+3) & ~3; p_bmi->bmiHeader.biHeight = - i_height; p_bmi->bmiHeader.biPlanes = 1; p_bmi->bmiHeader.biBitCount = 8; p_bmi->bmiHeader.biCompression = BI_RGB; p_bmi->bmiHeader.biClrUsed = 16; for( i = 0; i < 16; i++ ) { p_bmi->bmiColors[i].rgbBlue = p_bmi->bmiColors[i].rgbGreen = p_bmi->bmiColors[i].rgbRed = pi_gamma[i]; } bitmap = CreateDIBSection( p_sys->hcdc, p_bmi, DIB_RGB_COLORS, (void **)&p_bitmap, NULL, 0 ); if( !bitmap ) { msg_Err( p_filter, "could not create bitmap" ); free( psz_string ); return VLC_EGENERIC; } bitmap_bak = SelectObject( p_sys->hcdc, bitmap ); FillRect( p_sys->hcdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) ); if( !DrawText( p_sys->hcdc, psz_string, -1, &rect, DT_CENTER | DT_NOPREFIX ) ) { msg_Err( p_filter, "could not draw text" ); } p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; Render( p_filter, p_region_out, p_bitmap, i_width, i_height ); SelectObject( p_sys->hcdc, bitmap_bak ); DeleteObject( bitmap ); free( psz_string ); return VLC_SUCCESS; }
/**************************************************************************** * ioctl_ReadSector: Read VCD or CDDA sectors ****************************************************************************/ int ioctl_ReadSectors( vlc_object_t *p_this, const vcddev_t *p_vcddev, int i_sector, uint8_t *p_buffer, int i_nb, int i_type ) { uint8_t *p_block; int i; if( i_type == VCD_TYPE ) p_block = malloc( VCD_SECTOR_SIZE * i_nb ); else p_block = p_buffer; if( p_vcddev->i_vcdimage_handle != -1 ) { /* * vcd image mode */ if( lseek( p_vcddev->i_vcdimage_handle, i_sector * VCD_SECTOR_SIZE, SEEK_SET ) == -1 ) { msg_Err( p_this, "Could not lseek to sector %d", i_sector ); goto error; } if( read( p_vcddev->i_vcdimage_handle, p_block, VCD_SECTOR_SIZE * i_nb) == -1 ) { msg_Err( p_this, "Could not read sector %d", i_sector ); goto error; } } else { /* * vcd device mode */ #if defined( __APPLE__ ) dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.offset = i_sector * VCD_SECTOR_SIZE; cd_read.sectorArea = kCDSectorAreaSync | kCDSectorAreaHeader | kCDSectorAreaSubHeader | kCDSectorAreaUser | kCDSectorAreaAuxiliary; cd_read.sectorType = kCDSectorTypeUnknown; cd_read.buffer = p_block; cd_read.bufferLength = VCD_SECTOR_SIZE * i_nb; if( ioctl( p_vcddev->i_device_handle, DKIOCCDREAD, &cd_read ) == -1 ) { msg_Err( p_this, "could not read block %d", i_sector ); goto error; } #elif defined( WIN32 ) DWORD dwBytesReturned; RAW_READ_INFO cdrom_raw; /* Initialize CDROM_RAW_READ structure */ cdrom_raw.DiskOffset.QuadPart = CD_SECTOR_SIZE * i_sector; cdrom_raw.SectorCount = i_nb; cdrom_raw.TrackMode = i_type == VCD_TYPE ? XAForm2 : CDDA; if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_RAW_READ, &cdrom_raw, sizeof(RAW_READ_INFO), p_block, VCD_SECTOR_SIZE * i_nb, &dwBytesReturned, NULL ) == 0 ) { if( i_type == VCD_TYPE ) { /* Retry in YellowMode2 */ cdrom_raw.TrackMode = YellowMode2; if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_RAW_READ, &cdrom_raw, sizeof(RAW_READ_INFO), p_block, VCD_SECTOR_SIZE * i_nb, &dwBytesReturned, NULL ) == 0 ) goto error; } else return -1; } #elif defined( __OS2__ ) cdrom_readlong_t readlong = {{'C', 'D', '0', '1'}, }; ULONG param_len; ULONG data_len; ULONG rc; readlong.addr_mode = 0; /* LBA mode */ readlong.sectors = i_nb; readlong.start = i_sector; rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMDISK, CDROMDISK_READLONG, &readlong, sizeof( readlong ), ¶m_len, p_block, VCD_SECTOR_SIZE * i_nb, &data_len ); if( rc ) { msg_Err( p_this, "could not read block %d", i_sector ); goto error; } #elif defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H ) struct scsireq sc; int i_ret; memset( &sc, 0, sizeof(sc) ); sc.cmd[0] = 0xBE; sc.cmd[1] = i_type == VCD_TYPE ? SECTOR_TYPE_MODE2_FORM2: SECTOR_TYPE_CDDA; sc.cmd[2] = (i_sector >> 24) & 0xff; sc.cmd[3] = (i_sector >> 16) & 0xff; sc.cmd[4] = (i_sector >> 8) & 0xff; sc.cmd[5] = (i_sector >> 0) & 0xff; sc.cmd[6] = (i_nb >> 16) & 0xff; sc.cmd[7] = (i_nb >> 8) & 0xff; sc.cmd[8] = (i_nb ) & 0xff; sc.cmd[9] = i_type == VCD_TYPE ? READ_CD_RAW_MODE2 : READ_CD_USERDATA; sc.cmd[10] = 0; /* sub channel */ sc.cmdlen = 12; sc.databuf = (caddr_t)p_block; sc.datalen = VCD_SECTOR_SIZE * i_nb; sc.senselen = sizeof( sc.sense ); sc.flags = SCCMD_READ; sc.timeout = 10000; i_ret = ioctl( p_vcddev->i_device_handle, SCIOCCOMMAND, &sc ); if( i_ret == -1 ) { msg_Err( p_this, "SCIOCCOMMAND failed" ); goto error; } if( sc.retsts || sc.error ) { msg_Err( p_this, "SCSI command failed: status %d error %d", sc.retsts, sc.error ); goto error; } #elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H ) int i_size = VCD_SECTOR_SIZE; if( ioctl( p_vcddev->i_device_handle, CDRIOCSETBLOCKSIZE, &i_size ) == -1 ) { msg_Err( p_this, "Could not set block size" ); goto error; } if( lseek( p_vcddev->i_device_handle, i_sector * VCD_SECTOR_SIZE, SEEK_SET ) == -1 ) { msg_Err( p_this, "Could not lseek to sector %d", i_sector ); goto error; } if( read( p_vcddev->i_device_handle, p_block, VCD_SECTOR_SIZE * i_nb ) == -1 ) { msg_Err( p_this, "Could not read sector %d", i_sector ); goto error; } #else for( i = 0; i < i_nb; i++ ) { int i_dummy = i_sector + i + 2 * CD_FRAMES; #define p_msf ((struct cdrom_msf0 *)(p_block + i * VCD_SECTOR_SIZE)) p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS); p_msf->second = ( i_dummy % (CD_FRAMES * CD_SECS) ) / CD_FRAMES; p_msf->frame = ( i_dummy % (CD_FRAMES * CD_SECS) ) % CD_FRAMES; #undef p_msf if( ioctl( p_vcddev->i_device_handle, CDROMREADRAW, p_block + i * VCD_SECTOR_SIZE ) == -1 ) { msg_Err( p_this, "could not read block %i from disc", i_sector ); if( i == 0 ) goto error; else break; } } #endif } /* For VCDs, we don't want to keep the header and footer of the * sectors read */ if( i_type == VCD_TYPE ) { for( i = 0; i < i_nb; i++ ) { memcpy( p_buffer + i * VCD_DATA_SIZE, p_block + i * VCD_SECTOR_SIZE + VCD_DATA_START, VCD_DATA_SIZE ); } free( p_block ); } return( 0 ); error: if( i_type == VCD_TYPE ) free( p_block ); return( -1 ); }
/***************************************************************************** * Resample: convert a buffer *****************************************************************************/ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf ) { if( !p_in_buf || !p_in_buf->i_nb_samples ) { if( p_in_buf ) block_Release( p_in_buf ); return NULL; } filter_sys_t *p_sys = p_filter->p_sys; unsigned int i_out_rate = p_filter->fmt_out.audio.i_rate; int i_nb_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); /* Check if we really need to run the resampler */ if( i_out_rate == p_filter->fmt_in.audio.i_rate ) { if( !(p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) && p_sys->i_old_wing ) { /* output the whole thing with the samples from last time */ p_in_buf = block_Realloc( p_in_buf, p_sys->i_old_wing * p_filter->fmt_in.audio.i_bytes_per_frame, p_in_buf->i_buffer ); if( !p_in_buf ) return NULL; memcpy( p_in_buf->p_buffer, p_sys->p_buf + i_nb_channels * p_sys->i_old_wing, p_sys->i_old_wing * p_filter->fmt_in.audio.i_bytes_per_frame ); p_in_buf->i_nb_samples += p_sys->i_old_wing; p_in_buf->i_pts = date_Get( &p_sys->end_date ); p_in_buf->i_length = date_Increment( &p_sys->end_date, p_in_buf->i_nb_samples ) - p_in_buf->i_pts; } p_sys->i_old_wing = 0; p_sys->b_first = true; return p_in_buf; } unsigned i_bytes_per_frame = p_filter->fmt_out.audio.i_channels * p_filter->fmt_out.audio.i_bitspersample / 8; size_t i_out_size = i_bytes_per_frame * ( 1 + ( p_in_buf->i_nb_samples * p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate) ) + p_filter->p_sys->i_buf_size; block_t *p_out_buf = filter_NewAudioBuffer( p_filter, i_out_size ); if( !p_out_buf ) return NULL; float *p_out = (float *)p_out_buf->p_buffer; if( (p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) || p_sys->b_first ) { /* Continuity in sound samples has been broken, we'd better reset * everything. */ p_out_buf->i_flags |= BLOCK_FLAG_DISCONTINUITY; p_sys->i_remainder = 0; date_Init( &p_sys->end_date, i_out_rate, 1 ); date_Set( &p_sys->end_date, p_in_buf->i_pts ); p_sys->d_old_factor = 1; p_sys->i_old_wing = 0; p_sys->b_first = false; } int i_in_nb = p_in_buf->i_nb_samples; int i_in, i_out = 0; double d_factor, d_scale_factor, d_old_scale_factor; int i_filter_wing; #if 0 msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i", p_sys->i_old_rate, p_sys->d_old_factor, p_sys->i_old_wing, i_in_nb ); #endif /* Prepare the source buffer */ i_in_nb += (p_sys->i_old_wing * 2); float p_in_orig[i_in_nb * p_filter->fmt_in.audio.i_bytes_per_frame / 4], *p_in = p_in_orig; /* Copy all our samples in p_in */ if( p_sys->i_old_wing ) { vlc_memcpy( p_in, p_sys->p_buf, p_sys->i_old_wing * 2 * p_filter->fmt_in.audio.i_bytes_per_frame ); } /* XXX: why i_nb_channels instead of i_bytes_per_frame??? */ vlc_memcpy( p_in + p_sys->i_old_wing * 2 * i_nb_channels, p_in_buf->p_buffer, p_in_buf->i_nb_samples * p_filter->fmt_in.audio.i_bytes_per_frame ); block_Release( p_in_buf ); /* Make sure the output buffer is reset */ memset( p_out, 0, p_out_buf->i_buffer ); /* Calculate the new length of the filter wing */ d_factor = (double)i_out_rate / p_filter->fmt_in.audio.i_rate; i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1; /* Account for increased filter gain when using factors less than 1 */ d_old_scale_factor = SMALL_FILTER_SCALE * p_sys->d_old_factor + 0.5; d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5; /* Apply the old rate until we have enough samples for the new one */ i_in = p_sys->i_old_wing; p_in += p_sys->i_old_wing * i_nb_channels; for( ; i_in < i_filter_wing && (i_in + p_sys->i_old_wing) < i_in_nb; i_in++ ) { if( p_sys->d_old_factor == 1 ) { /* Just copy the samples */ memcpy( p_out, p_in, p_filter->fmt_in.audio.i_bytes_per_frame ); p_in += i_nb_channels; p_out += i_nb_channels; i_out++; continue; } while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate ) { if( p_sys->d_old_factor >= 1 ) { /* FilterFloatUP() is faster if we can use it */ /* Perform left-wing inner product */ FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in, p_out, p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, -1, i_nb_channels ); /* Perform right-wing inner product */ FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in + i_nb_channels, p_out, p_filter->fmt_out.audio.i_rate - p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, 1, i_nb_channels ); #if 0 /* Normalize for unity filter gain */ for( i = 0; i < i_nb_channels; i++ ) { *(p_out+i) *= d_old_scale_factor; } #endif /* Sanity check */ if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame <= (unsigned int)i_out+1 ) { p_out += i_nb_channels; i_out++; p_sys->i_remainder += p_filter->fmt_in.audio.i_rate; break; } } else { /* Perform left-wing inner product */ FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in, p_out, p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate, -1, i_nb_channels ); /* Perform right-wing inner product */ FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in + i_nb_channels, p_out, p_filter->fmt_out.audio.i_rate - p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate, 1, i_nb_channels ); } p_out += i_nb_channels; i_out++; p_sys->i_remainder += p_filter->fmt_in.audio.i_rate; } p_in += i_nb_channels; p_sys->i_remainder -= p_filter->fmt_out.audio.i_rate; } /* Apply the new rate for the rest of the samples */ if( i_in < i_in_nb - i_filter_wing ) { p_sys->d_old_factor = d_factor; p_sys->i_old_wing = i_filter_wing; } for( ; i_in < i_in_nb - i_filter_wing; i_in++ ) { while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate ) { if( d_factor >= 1 ) { /* FilterFloatUP() is faster if we can use it */ /* Perform left-wing inner product */ FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in, p_out, p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, -1, i_nb_channels ); /* Perform right-wing inner product */ FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in + i_nb_channels, p_out, p_filter->fmt_out.audio.i_rate - p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, 1, i_nb_channels ); #if 0 /* Normalize for unity filter gain */ for( int i = 0; i < i_nb_channels; i++ ) { *(p_out+i) *= d_old_scale_factor; } #endif /* Sanity check */ if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame <= (unsigned int)i_out+1 ) { p_out += i_nb_channels; i_out++; p_sys->i_remainder += p_filter->fmt_in.audio.i_rate; break; } } else { /* Perform left-wing inner product */ FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in, p_out, p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate, -1, i_nb_channels ); /* Perform right-wing inner product */ FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD, SMALL_FILTER_NWING, p_in + i_nb_channels, p_out, p_filter->fmt_out.audio.i_rate - p_sys->i_remainder, p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate, 1, i_nb_channels ); } p_out += i_nb_channels; i_out++; p_sys->i_remainder += p_filter->fmt_in.audio.i_rate; } p_in += i_nb_channels; p_sys->i_remainder -= p_filter->fmt_out.audio.i_rate; } /* Finalize aout buffer */ p_out_buf->i_nb_samples = i_out; p_out_buf->i_pts = date_Get( &p_sys->end_date ); p_out_buf->i_length = date_Increment( &p_sys->end_date, p_out_buf->i_nb_samples ) - p_out_buf->i_pts; p_out_buf->i_buffer = p_out_buf->i_nb_samples * i_nb_channels * sizeof(int32_t); /* Buffer i_filter_wing * 2 samples for next time */ if( p_sys->i_old_wing ) { size_t newsize = p_sys->i_old_wing * 2 * p_filter->fmt_in.audio.i_bytes_per_frame; if( newsize > p_sys->i_buf_size ) { free( p_sys->p_buf ); p_sys->p_buf = malloc( newsize ); if( p_sys->p_buf != NULL ) p_sys->i_buf_size = newsize; else { p_sys->i_buf_size = p_sys->i_old_wing = 0; /* oops! */ return p_out_buf; } } memcpy( p_sys->p_buf, p_in_orig + (i_in_nb - 2 * p_sys->i_old_wing) * i_nb_channels, (2 * p_sys->i_old_wing) * p_filter->fmt_in.audio.i_bytes_per_frame ); } #if 0 msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_buffer, i_out * p_filter->fmt_in.audio.i_bytes_per_frame ); #endif return p_out_buf; }
/***************************************************************************** * DecodeVideo: Called to decode one or more frames *****************************************************************************/ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; AVCodecContext *p_context = p_sys->p_context; int b_drawpicture; int b_null_size = false; block_t *p_block; if( !pp_block || !*pp_block ) return NULL; if( !p_context->extradata_size && p_dec->fmt_in.i_extra ) { ffmpeg_InitCodec( p_dec ); if( p_sys->b_delayed_open ) { if( ffmpeg_OpenCodec( p_dec ) ) msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); } } p_block = *pp_block; if( p_sys->b_delayed_open ) { block_Release( p_block ); return NULL; } if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ p_sys->i_late_frames = 0; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) avcodec_flush_buffers( p_context ); block_Release( p_block ); return NULL; } if( p_block->i_flags & BLOCK_FLAG_PREROLL ) { /* Do not care about late frames when prerolling * TODO avoid decoding of non reference frame * (ie all B except for H264 where it depends only on nal_ref_idc) */ p_sys->i_late_frames = 0; } if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) && (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) ) { if( p_sys->i_pts > VLC_TS_INVALID ) { msg_Err( p_dec, "more than 5 seconds of late video -> " "dropping frame (computer too slow ?)" ); p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ } block_Release( p_block ); p_sys->i_late_frames--; return NULL; } /* A good idea could be to decode all I pictures and see for the other */ if( !p_dec->b_pace_control && p_sys->b_hurry_up && (p_sys->i_late_frames > 4) ) { b_drawpicture = 0; if( p_sys->i_late_frames < 12 ) { p_context->skip_frame = (p_sys->i_skip_frame <= AVDISCARD_NONREF) ? AVDISCARD_NONREF : p_sys->i_skip_frame; } else { /* picture too late, won't decode * but break picture until a new I, and for mpeg4 ...*/ p_sys->i_late_frames--; /* needed else it will never be decrease */ block_Release( p_block ); return NULL; } } else { if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) b_drawpicture = 1; else b_drawpicture = 0; } if( p_context->width <= 0 || p_context->height <= 0 ) { if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; b_null_size = true; } else if( !b_drawpicture ) { /* It creates broken picture * FIXME either our parser or ffmpeg is broken */ #if 0 if( p_sys->b_hurry_up ) p_context->skip_frame = __MAX( p_context->skip_frame, AVDISCARD_NONREF ); #endif } /* * Do the actual decoding now */ /* Don't forget that libavcodec requires a little more bytes * that the real frame size */ if( p_block->i_buffer > 0 ) { p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0; p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); if( !p_block ) return NULL; p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; *pp_block = p_block; memset( p_block->p_buffer + p_block->i_buffer, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } while( p_block->i_buffer > 0 || p_sys->b_flush ) { int i_used, b_gotpicture; picture_t *p_pic; AVPacket pkt; /* Set the PTS/DTS in the context reordered_opaque field */ if( p_block->i_pts > VLC_TS_INVALID ) p_context->reordered_opaque = (p_block->i_pts << 1) | 0; else if( p_block->i_dts > VLC_TS_INVALID ) p_context->reordered_opaque = (p_block->i_dts << 1) | 1; else p_context->reordered_opaque = INT64_MIN; p_sys->p_ff_pic->reordered_opaque = p_context->reordered_opaque; /* Make sure we don't reuse the same timestamps twice */ p_block->i_pts = p_block->i_dts = VLC_TS_INVALID; post_mt( p_sys ); av_init_packet( &pkt ); pkt.data = p_block->p_buffer; pkt.size = p_block->i_buffer; i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, &b_gotpicture, &pkt ); if( b_null_size && !p_sys->b_flush && p_context->width > 0 && p_context->height > 0 ) { /* Reparse it to not drop the I frame */ b_null_size = false; if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, &b_gotpicture, &pkt ); } wait_mt( p_sys ); if( p_sys->b_flush ) p_sys->b_first_frame = true; if( p_block->i_buffer <= 0 ) p_sys->b_flush = false; if( i_used < 0 ) { if( b_drawpicture ) msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); block_Release( p_block ); return NULL; } else if( i_used > p_block->i_buffer || p_context->thread_count > 1 ) { i_used = p_block->i_buffer; } /* Consumed bytes */ p_block->i_buffer -= i_used; p_block->p_buffer += i_used; /* Nothing to display */ if( !b_gotpicture ) { if( i_used == 0 ) break; continue; } /* Sanity check (seems to be needed for some streams) */ if( p_sys->p_ff_pic->pict_type == AV_PICTURE_TYPE_B) { p_sys->b_has_b_frames = true; } /* Compute the PTS */ mtime_t i_pts = VLC_TS_INVALID; if( p_sys->p_ff_pic->reordered_opaque != INT64_MIN ) { mtime_t i_ts = p_sys->p_ff_pic->reordered_opaque >> 1; bool b_dts = p_sys->p_ff_pic->reordered_opaque & 1; if( b_dts ) { if( !p_context->has_b_frames || !p_sys->b_has_b_frames || !p_sys->p_ff_pic->reference || p_sys->i_pts <= VLC_TS_INVALID ) i_pts = i_ts; /* Guess what ? The rules are different for Real Video :( */ if( (p_dec->fmt_in.i_codec == VLC_CODEC_RV30 || p_dec->fmt_in.i_codec == VLC_CODEC_RV40) && p_sys->b_has_b_frames ) { i_pts = VLC_TS_INVALID; if(p_sys->p_ff_pic->reference) i_pts = i_ts; } } else { i_pts = i_ts; } } if( i_pts <= VLC_TS_INVALID ) i_pts = p_sys->i_pts; /* Interpolate the next PTS */ if( i_pts > VLC_TS_INVALID ) p_sys->i_pts = i_pts; if( p_sys->i_pts > VLC_TS_INVALID ) { /* interpolate the next PTS */ if( p_dec->fmt_in.video.i_frame_rate > 0 && p_dec->fmt_in.video.i_frame_rate_base > 0 ) { p_sys->i_pts += INT64_C(1000000) * (2 + p_sys->p_ff_pic->repeat_pict) * p_dec->fmt_in.video.i_frame_rate_base / (2 * p_dec->fmt_in.video.i_frame_rate); } else if( p_context->time_base.den > 0 ) { int i_tick = p_context->ticks_per_frame; if( i_tick <= 0 ) i_tick = 1; p_sys->i_pts += INT64_C(1000000) * (2 + p_sys->p_ff_pic->repeat_pict) * i_tick * p_context->time_base.num / (2 * p_context->time_base.den); } } /* Update frame late count (except when doing preroll) */ mtime_t i_display_date = 0; if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) i_display_date = decoder_GetDisplayDate( p_dec, i_pts ); if( i_display_date > 0 && i_display_date <= mdate() ) { p_sys->i_late_frames++; if( p_sys->i_late_frames == 1 ) p_sys->i_late_frames_start = mdate(); } else { p_sys->i_late_frames = 0; } if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) ) continue; if( !p_sys->p_ff_pic->opaque ) { /* Get a new picture */ p_pic = ffmpeg_NewPictBuf( p_dec, p_context ); if( !p_pic ) { block_Release( p_block ); return NULL; } /* Fill p_picture_t from AVVideoFrame and do chroma conversion * if needed */ ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic ); } else { p_pic = (picture_t *)p_sys->p_ff_pic->opaque; decoder_LinkPicture( p_dec, p_pic ); } if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den ) { /* Fetch again the aspect ratio in case it changed */ p_dec->fmt_out.video.i_sar_num = p_context->sample_aspect_ratio.num; p_dec->fmt_out.video.i_sar_den = p_context->sample_aspect_ratio.den; if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den ) { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } } /* Send decoded frame to vout */ if( i_pts > VLC_TS_INVALID) { p_pic->date = i_pts; if( p_sys->b_first_frame ) { /* Hack to force display of still pictures */ p_sys->b_first_frame = false; p_pic->b_force = true; } p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict; p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame; p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first; p_pic->i_qstride = p_sys->p_ff_pic->qstride; int i_mb_h = ( p_pic->format.i_height + 15 ) / 16; p_pic->p_q = malloc( p_pic->i_qstride * i_mb_h ); memcpy( p_pic->p_q, p_sys->p_ff_pic->qscale_table, p_pic->i_qstride * i_mb_h ); switch( p_sys->p_ff_pic->qscale_type ) { case FF_QSCALE_TYPE_MPEG1: p_pic->i_qtype = QTYPE_MPEG1; break; case FF_QSCALE_TYPE_MPEG2: p_pic->i_qtype = QTYPE_MPEG2; break; case FF_QSCALE_TYPE_H264: p_pic->i_qtype = QTYPE_H264; break; } return p_pic; } else { decoder_DeletePicture( p_dec, p_pic ); } }