예제 #1
0
/**
 * 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;
}
예제 #2
0
//---------------------------------------------------------------------------
// 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;
}
예제 #3
0
파일: wayland.c 프로젝트: 0xheart0/vlc
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, &registry_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;
}
예제 #4
0
/*****************************************************************************
 * 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;
}
예제 #5
0
/*****************************************************************************
 * 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;
}
예제 #6
0
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;
}
예제 #7
0
파일: packet.c 프로젝트: ryanli/vlc
/**
 * 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;
}
예제 #8
0
/*****************************************************************************
 * 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;
}
예제 #9
0
/*****************************************************************************
 * 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;
}
예제 #10
0
파일: croppadd.c 프로젝트: Kafay/vlc
/*****************************************************************************
 * 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;
}
예제 #11
0
파일: aa.c 프로젝트: qdk0901/vlc
/**
 * 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;
}
예제 #12
0
파일: vda.c 프로젝트: 371816210/vlc_vlc
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;
}
예제 #13
0
파일: x11.c 프로젝트: paa/vlc
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;
    }
}
예제 #14
0
파일: x11.c 프로젝트: paa/vlc
/**
 * 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;
}
예제 #15
0
파일: cdrom.c 프로젝트: Ackhuman/vlc
/****************************************************************************
 * 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 );
}
예제 #16
0
파일: dirac.c 프로젝트: RicoP/vlcfork
/*****************************************************************************
 * 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;
}
예제 #17
0
파일: filter_chain.c 프로젝트: paa/vlc
/* 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;
}
예제 #18
0
파일: output.c 프로젝트: mahaserver/MHSVLC
/*****************************************************************************
 * 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;
}
예제 #19
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 ) );
    }
예제 #20
0
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
    {
예제 #21
0
파일: goom.c 프로젝트: asdlei00/vlc-2.1
/*****************************************************************************
 * 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;
}
예제 #22
0
파일: theora.c 프로젝트: cobr123/qtVlc
/*****************************************************************************
 * 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;
}
예제 #23
0
/*****************************************************************************
 * 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;
}
예제 #24
0
파일: zvbi.c 프로젝트: Flameeyes/vlc
/*****************************************************************************
 * 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;
}
예제 #25
0
/*****************************************************************************
 * 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;
}
예제 #26
0
파일: cdrom.c 프로젝트: Ackhuman/vlc
/*****************************************************************************
 * 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 ), &param_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), &param_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;
    }
}
예제 #27
0
파일: win32text.c 프로젝트: Mettbrot/vlc
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;
}
예제 #28
0
파일: cdrom.c 프로젝트: Ackhuman/vlc
/****************************************************************************
 * 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 ), &param_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 );
}
예제 #29
0
/*****************************************************************************
 * 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;
}
예제 #30
0
파일: video.c 프로젝트: jamesbates/vlc
/*****************************************************************************
 * 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 );
        }
    }