/***************************************************************************** * OpenVideo: *****************************************************************************/ static int OpenVideo( decoder_t *p_dec ) { decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) ); #ifndef WIN32 vlc_value_t lockval; 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; } 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 */ var_Get( p_dec->p_libvlc, "qt_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); #ifdef SYS_DARWIN EnterMovies(); #endif if( QTVideoInit( p_dec ) ) { msg_Err( p_dec, "cannot initialize QT"); goto exit_error; } #ifndef SYS_DARWIN 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->p_fifo, "ImageCodecInitialize->%p size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize); */ memset( &cinfo, 0, sizeof( CodecInfo ) ); cres = p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo ); msg_Dbg( p_dec, "Flags: compr: 0x%lx decomp: 0x%lx format: 0x%lx\n", cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags ); msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s\n", ((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 ) ); 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=%ld ver=%d rev=%d vendor=%ld tempQ=%d " "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d frameCount=%d clutID=%d", id->idSize, id->version, id->revisionLevel, id->vendor, (int)id->temporalQuality, (int)id->spatialQuality, id->width, id->height, (int)id->hRes, (int)id->vRes, (int)id->dataSize, id->frameCount, id->clutID ); p_sys->framedescHandle = (ImageDescriptionHandle) p_sys->NewHandleClear( id->idSize ); memcpy( *p_sys->framedescHandle, id, id->idSize ); p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 ); 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\n", 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\n", (int)cres ); p_dec->fmt_out.i_codec = VLC_FOURCC( 'Y', 'U', 'Y', '2' ); 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_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_in.video.i_width / p_dec->fmt_in.video.i_height; vlc_mutex_unlock( lockval.p_address ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( lockval.p_address ); #endif /* !WIN32 */ return VLC_EGENERIC; }
vlc_fourcc_t vlc_fourcc_GetCodecAudio( vlc_fourcc_t i_fourcc, int i_bits ) { const int i_bytes = ( i_bits + 7 ) / 8; if( i_fourcc == VLC_FOURCC( 'a', 'f', 'l', 't' ) ) { switch( i_bytes ) { case 4: return VLC_CODEC_FL32; case 8: return VLC_CODEC_FL64; default: return 0; } } else if( i_fourcc == VLC_FOURCC( 'a', 'r', 'a', 'w' ) || i_fourcc == VLC_FOURCC( 'p', 'c', 'm', ' ' ) ) { switch( i_bytes ) { case 1: return VLC_CODEC_U8; case 2: return VLC_CODEC_S16L; case 3: return VLC_CODEC_S24L; break; case 4: return VLC_CODEC_S32L; default: return 0; } } else if( i_fourcc == VLC_FOURCC( 't', 'w', 'o', 's' ) ) { switch( i_bytes ) { case 1: return VLC_CODEC_S8; case 2: return VLC_CODEC_S16B; case 3: return VLC_CODEC_S24B; case 4: return VLC_CODEC_S32B; default: return 0; } } else if( i_fourcc == VLC_FOURCC( 's', 'o', 'w', 't' ) ) { switch( i_bytes ) { case 1: return VLC_CODEC_S8; case 2: return VLC_CODEC_S16L; case 3: return VLC_CODEC_S24L; case 4: return VLC_CODEC_S32L; default: return 0; } } else { return vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc ); } }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_sys_t *p_sys; vlc_value_t val; p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) ); if( !p_stream->p_next ) { msg_Err( p_stream, "cannot create chain" ); vlc_object_release( p_sys ); return VLC_EGENERIC; } p_sys->i_master_drift = 0; config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg ); /* Audio transcoding parameters */ var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val ); p_sys->psz_aenc = NULL; p_sys->p_audio_cfg = NULL; if( val.psz_string && *val.psz_string ) { char *psz_next; psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg, val.psz_string ); free( psz_next ); } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val ); p_sys->i_acodec = 0; if( val.psz_string && *val.psz_string ) { char fcc[4] = " "; memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) ); p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] ); } free( val.psz_string ); p_sys->psz_alang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" ); var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val ); p_sys->i_abitrate = val.i_int; if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000; var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val ); p_sys->i_sample_rate = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val ); p_sys->i_channels = val.i_int; if( p_sys->i_acodec ) { if( ( p_sys->i_acodec == VLC_CODEC_MP3 || p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 ) { msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2", p_sys->i_channels ); p_sys->i_channels = 2; } msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s", (char *)&p_sys->i_acodec, p_sys->i_sample_rate, p_sys->i_channels, p_sys->i_abitrate / 1000 ); } var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val ); if( val.psz_string && *val.psz_string ) p_sys->psz_af = val.psz_string; else { free( val.psz_string ); p_sys->psz_af = NULL; } /* Video transcoding parameters */ var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val ); p_sys->psz_venc = NULL; p_sys->p_video_cfg = NULL; if( val.psz_string && *val.psz_string ) { char *psz_next; psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg, val.psz_string ); free( psz_next ); } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val ); p_sys->i_vcodec = 0; if( val.psz_string && *val.psz_string ) { char fcc[4] = " "; memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) ); p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] ); } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val ); p_sys->i_vbitrate = val.i_int; if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000; var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val ); p_sys->f_scale = val.f_float; var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val ); p_sys->f_fps = val.f_float; var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val ); p_sys->b_hurry_up = val.b_bool; var_Get( p_stream, SOUT_CFG_PREFIX "width", &val ); p_sys->i_width = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "height", &val ); p_sys->i_height = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val ); p_sys->i_maxwidth = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val ); p_sys->i_maxheight = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val ); if( val.psz_string && *val.psz_string ) p_sys->psz_vf2 = val.psz_string; else { free( val.psz_string ); p_sys->psz_vf2 = NULL; } var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val ); p_sys->b_deinterlace = val.b_bool; var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val ); p_sys->psz_deinterlace = NULL; p_sys->p_deinterlace_cfg = NULL; if( val.psz_string && *val.psz_string ) { char *psz_next; psz_next = config_ChainCreate( &p_sys->psz_deinterlace, &p_sys->p_deinterlace_cfg, val.psz_string ); free( psz_next ); } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val ); p_sys->i_threads = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val ); p_sys->b_high_priority = val.b_bool; if( p_sys->i_vcodec ) { msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s", (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height, p_sys->f_scale, p_sys->i_vbitrate / 1000 ); } /* Subpictures transcoding parameters */ p_sys->p_spu = NULL; p_sys->psz_senc = NULL; p_sys->p_spu_cfg = NULL; p_sys->i_scodec = 0; var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val ); if( val.psz_string && *val.psz_string ) { char *psz_next; psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg, val.psz_string ); free( psz_next ); } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val ); if( val.psz_string && *val.psz_string ) { char fcc[4] = " "; memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) ); p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] ); } free( val.psz_string ); if( p_sys->i_scodec ) { msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec ); } var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val ); p_sys->b_soverlay = val.b_bool; var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val ); if( val.psz_string && *val.psz_string ) { p_sys->p_spu = spu_Create( p_stream ); if( p_sys->p_spu ) spu_ChangeFilters( p_sys->p_spu, val.psz_string ); } free( val.psz_string ); /* OSD menu transcoding parameters */ p_sys->psz_osdenc = NULL; p_sys->p_osd_cfg = NULL; p_sys->i_osdcodec = 0; p_sys->b_osd = false; var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val ); if( val.b_bool ) { char *psz_next; psz_next = config_ChainCreate( &p_sys->psz_osdenc, &p_sys->p_osd_cfg, strdup( "dvbsub") ); free( psz_next ); p_sys->i_osdcodec = VLC_CODEC_YUVP; msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec ); if( !p_sys->p_spu ) { p_sys->p_spu = spu_Create( p_stream ); if( p_sys->p_spu ) spu_ChangeFilters( p_sys->p_spu, "osdmenu" ); } else { spu_ChangeFilters( p_sys->p_spu, "osdmenu" ); } } /* Audio settings */ var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val ); p_sys->b_master_sync = val.b_bool; if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true; p_stream->pf_add = Add; p_stream->pf_del = Del; p_stream->pf_send = Send; p_stream->p_sys = p_sys; return VLC_SUCCESS; }
/***************************************************************************** * Init: initialize video thread *****************************************************************************/ static int Init( vout_thread_t *p_vout ) { int i_index; picture_t *p_pic; vlc_value_t val; char* psz_chroma; int i_chroma; int i_width; int i_height; int i_datasize; i_width = config_GetInt( p_vout, "snapshot-width" ); i_height = config_GetInt( p_vout, "snapshot-height" ); psz_chroma = config_GetPsz( p_vout, "snapshot-chroma" ); if( psz_chroma ) { if( strlen( psz_chroma ) < 4 ) { msg_Err( p_vout, "snapshot-chroma should be 4 characters long." ); return VLC_EGENERIC; } i_chroma = VLC_FOURCC( psz_chroma[0], psz_chroma[1], psz_chroma[2], psz_chroma[3] ); free( psz_chroma ); } else { msg_Err( p_vout, "Cannot find chroma information." ); return VLC_EGENERIC; } I_OUTPUTPICTURES = 0; /* Initialize the output structure */ p_vout->output.i_chroma = i_chroma; p_vout->output.pf_setpalette = NULL; p_vout->output.i_width = i_width; p_vout->output.i_height = i_height; p_vout->output.i_aspect = p_vout->output.i_width * VOUT_ASPECT_FACTOR / p_vout->output.i_height; /* Define the bitmasks */ switch( i_chroma ) { case VLC_FOURCC( 'R','V','1','5' ): p_vout->output.i_rmask = 0x001f; p_vout->output.i_gmask = 0x03e0; p_vout->output.i_bmask = 0x7c00; break; case VLC_FOURCC( 'R','V','1','6' ): p_vout->output.i_rmask = 0x001f; p_vout->output.i_gmask = 0x07e0; p_vout->output.i_bmask = 0xf800; break; case VLC_FOURCC( 'R','V','2','4' ): p_vout->output.i_rmask = 0xff0000; p_vout->output.i_gmask = 0x00ff00; p_vout->output.i_bmask = 0x0000ff; break; case VLC_FOURCC( 'R','V','3','2' ): p_vout->output.i_rmask = 0xff0000; p_vout->output.i_gmask = 0x00ff00; p_vout->output.i_bmask = 0x0000ff; break; } /* Try to initialize 1 direct buffer */ p_pic = NULL; /* Find an empty picture slot */ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) { if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) { p_pic = p_vout->p_picture + i_index; break; } } /* Allocate the picture */ if( p_pic == NULL ) { return VLC_SUCCESS; } vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma, p_vout->output.i_width, p_vout->output.i_height, p_vout->output.i_aspect ); if( p_pic->i_planes == 0 ) { return VLC_EGENERIC; } p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; I_OUTPUTPICTURES++; /* Get datasize and set variables */ i_datasize = i_width * i_height * p_pic->p->i_pixel_pitch; p_vout->p_sys->i_datasize = i_datasize; p_vout->p_sys->i_index = 0; p_vout->p_sys->i_size = config_GetInt( p_vout, "snapshot-cache-size" ); if( p_vout->p_sys->i_size < 2 ) { msg_Err( p_vout, "snapshot-cache-size must be at least 1." ); return VLC_EGENERIC; } p_vout->p_sys->p_list = malloc( p_vout->p_sys->i_size * sizeof( snapshot_t * ) ); if( p_vout->p_sys->p_list == NULL ) return VLC_ENOMEM; /* Initialize the structures for the circular buffer */ for( i_index = 0; i_index < p_vout->p_sys->i_size; i_index++ ) { snapshot_t *p_snapshot = malloc( sizeof( snapshot_t ) ); if( p_snapshot == NULL ) return VLC_ENOMEM; p_snapshot->i_width = i_width; p_snapshot->i_height = i_height; p_snapshot->i_datasize = i_datasize; p_snapshot->date = 0; p_snapshot->p_data = ( char* ) malloc( i_datasize ); if( p_snapshot->p_data == NULL ) return VLC_ENOMEM; p_vout->p_sys->p_list[i_index] = p_snapshot; } val.i_int = i_width; var_Set( p_vout, "snapshot-width", val ); val.i_int = i_height; var_Set( p_vout, "snapshot-height", val ); val.i_int = i_datasize; var_Set( p_vout, "snapshot-datasize", val ); val.i_int = p_vout->p_sys->i_size; var_Set( p_vout, "snapshot-cache-size", val ); val.p_address = p_vout->p_sys->p_list; var_Set( p_vout, "snapshot-list-pointer", val ); /* Get the p_input pointer (to access video times) */ p_vout->p_sys->p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT ); if( !p_vout->p_sys->p_input ) return VLC_ENOOBJ; if( var_Create( p_vout->p_sys->p_input, "snapshot-id", VLC_VAR_INTEGER ) ) { msg_Err( p_vout, "Cannot create snapshot-id variable in p_input (%d).", p_vout->p_sys->p_input->i_object_id ); return VLC_EGENERIC; } /* Register the snapshot vout module at the input level */ val.i_int = p_vout->i_object_id; if( var_Set( p_vout->p_sys->p_input, "snapshot-id", val ) ) { msg_Err( p_vout, "Cannot register snapshot-id in p_input (%d).", p_vout->p_sys->p_input->i_object_id ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ 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_FOURCC('i','m','a', '4'): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */ break; default: return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_channels <= 0 || p_dec->fmt_in.audio.i_channels > 5 ) { msg_Err( p_dec, "invalid number of channel (not between 1 and 5): %i", p_dec->fmt_in.audio.i_channels ); return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_rate <= 0 ) { msg_Err( p_dec, "bad samplerate" ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_ENOMEM; } switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_QT; break; case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_WAV; break; case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ p_sys->codec = ADPCM_MS; break; case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ p_sys->codec = ADPCM_DK4; break; case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ p_sys->codec = ADPCM_DK3; break; case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */ p_sys->codec = ADPCM_EA; p_dec->fmt_in.p_extra = calloc( 2 * p_dec->fmt_in.audio.i_channels, sizeof( int16_t ) ); if( p_dec->fmt_in.p_extra == NULL ) { free( p_sys ); return VLC_ENOMEM; } break; } if( p_dec->fmt_in.audio.i_blockalign <= 0 ) { p_sys->i_block = (p_sys->codec == ADPCM_IMA_QT) ? 34 * p_dec->fmt_in.audio.i_channels : 1024; msg_Warn( p_dec, "block size undefined, using %d", p_sys->i_block ); } else { p_sys->i_block = p_dec->fmt_in.audio.i_blockalign; } /* calculate samples per block */ switch( p_sys->codec ) { case ADPCM_IMA_QT: p_sys->i_samplesperblock = 64; break; case ADPCM_IMA_WAV: p_sys->i_samplesperblock = 2 * ( p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels ) / p_dec->fmt_in.audio.i_channels; break; case ADPCM_MS: p_sys->i_samplesperblock = 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels + 2; break; case ADPCM_DK4: p_sys->i_samplesperblock = 2 * (p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels + 1; break; case ADPCM_DK3: p_dec->fmt_in.audio.i_channels = 2; p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3; break; case ADPCM_EA: p_sys->i_samplesperblock = 2 * (p_sys->i_block - p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels; } msg_Dbg( p_dec, "format: samplerate:%d Hz channels:%d bits/sample:%d " "blockalign:%d samplesperblock:%d", p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels, p_dec->fmt_in.audio.i_bitspersample, p_sys->i_block, p_sys->i_samplesperblock ); p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_dec->fmt_in.audio.i_channels]; aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate ); aout_DateSet( &p_sys->end_date, 0 ); p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; }
static vlc_fourcc_t GetFOURCC( const uint8_t *p_buff ) { return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] ); }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; char *psz_tmp; int pitch; if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e')) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL ) return VLC_ENOMEM; // get parameters char* chromaStr = var_CreateGetString( p_dec, "invmem-chroma" ); p_sys->i_width = var_CreateGetInteger( p_this, "invmem-width" ); p_sys->i_height = var_CreateGetInteger( p_this, "invmem-height" ); if( p_sys->i_width == 0 || p_sys->i_height == 0 ) { msg_Err( p_dec, "--invmem-width and --invmem-height must be > 0" ); goto error; } psz_tmp = var_CreateGetString( p_dec, "invmem-lock" ); p_sys->pf_lock = (void * (*) (void *))(intptr_t)atoll( psz_tmp ); free( psz_tmp ); psz_tmp = var_CreateGetString( p_dec, "invmem-unlock" ); p_sys->pf_unlock = (void (*) (void *))(intptr_t)atoll( psz_tmp ); free( psz_tmp ); psz_tmp = var_CreateGetString( p_dec, "invmem-data" ); p_sys->p_data = (void *)(intptr_t)atoll( psz_tmp ); free( psz_tmp ); if( !p_sys->pf_lock || !p_sys->pf_unlock ) { msg_Err( p_dec, "Invalid lock or unlock callbacks" ); goto error; } if ( chromaStr == NULL ) { msg_Err( p_dec, "Invalid invmem-chroma string." ); goto error; } const vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, chromaStr ); if ( !chroma ) { msg_Err( p_dec, "invmem-chroma should be 4 characters long." ); goto error; } /* Set output properties */ switch (chroma) { case VLC_CODEC_RGB15: p_dec->fmt_out.video.i_rmask = 0x001f; p_dec->fmt_out.video.i_gmask = 0x03e0; p_dec->fmt_out.video.i_bmask = 0x7c00; pitch = p_sys->i_width * 2; break; case VLC_CODEC_RGB16: p_dec->fmt_out.video.i_rmask = 0x001f; p_dec->fmt_out.video.i_gmask = 0x07e0; p_dec->fmt_out.video.i_bmask = 0xf800; pitch = p_sys->i_width * 2; break; case VLC_CODEC_RGB24: p_dec->fmt_out.video.i_rmask = 0xff0000; p_dec->fmt_out.video.i_gmask = 0x00ff00; p_dec->fmt_out.video.i_bmask = 0x0000ff; pitch = p_sys->i_width * 3; break; case VLC_CODEC_RGB32: p_dec->fmt_out.video.i_rmask = 0xff0000; p_dec->fmt_out.video.i_gmask = 0x00ff00; p_dec->fmt_out.video.i_bmask = 0x0000ff; pitch = p_sys->i_width * 4; break; default: p_dec->fmt_out.video.i_rmask = 0; p_dec->fmt_out.video.i_gmask = 0; p_dec->fmt_out.video.i_bmask = 0; pitch = 0; msg_Warn( p_dec, "Unknown chroma %s", chromaStr ); goto error; } free( chromaStr ); p_dec->fmt_out.i_codec = chroma; p_dec->fmt_out.video.i_width = p_dec->p_sys->i_width; p_dec->fmt_out.video.i_height = p_dec->p_sys->i_height; p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->p_sys->i_width / p_dec->p_sys->i_height; p_dec->fmt_out.i_cat = VIDEO_ES; p_sys->i_pitch = pitch; /* Set callbacks */ p_dec->pf_decode_video = DecodeBlock; return VLC_SUCCESS; error: free( p_sys ); free( chromaStr ); return VLC_EGENERIC; }
/* Returns a new picture buffer */ static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec, AVCodecContext *p_context ) { decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; p_dec->fmt_out.video.i_width = p_context->width; p_dec->fmt_out.video.i_height = p_context->height; p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); if( !p_context->width || !p_context->height ) { return NULL; /* invalid display size */ } if( !p_dec->fmt_out.i_codec ) { /* we make conversion if possible*/ p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); } /* If an aspect-ratio was specified in the input format then force it */ if( p_dec->fmt_in.video.i_aspect ) { p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect; } else { #if LIBAVCODEC_BUILD >= 4687 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) * p_context->width / p_context->height ); #else p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio; #endif if( p_dec->fmt_out.video.i_aspect == 0 ) { p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_context->width / p_context->height; } } if( p_context->frame_rate > 0 && p_context->frame_rate_base > 0 ) { p_dec->fmt_out.video.i_frame_rate = p_context->frame_rate; p_dec->fmt_out.video.i_frame_rate_base = p_context->frame_rate_base; } p_pic = p_dec->pf_vout_buffer_new( p_dec ); #ifdef LIBAVCODEC_PP if( p_sys->p_pp && p_sys->b_pp && !p_sys->b_pp_init ) { E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width, p_context->height, p_context->pix_fmt ); p_sys->b_pp_init = VLC_TRUE; } #endif return p_pic; }
/***************************************************************************** * InitVideo: initialize the video decoder ***************************************************************************** * the ffmpeg codec will be opened, some memory allocated. The vout is not yet * opened (done after the first decoded frame). *****************************************************************************/ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, char *psz_namecodec ) { decoder_sys_t *p_sys; vlc_value_t lockval; vlc_value_t val; var_Get( p_dec->p_libvlc, "avcodec", &lockval ); /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } p_dec->p_sys->p_context = p_context; p_dec->p_sys->p_codec = p_codec; p_dec->p_sys->i_codec_id = i_codec_id; p_dec->p_sys->psz_namecodec = psz_namecodec; p_sys->p_ff_pic = avcodec_alloc_frame(); /* ***** Fill p_context with init values ***** */ /* FIXME: remove when ffmpeg deals properly with avc1 */ if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','v','c','1') ) /* End FIXME */ p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec ); p_sys->p_context->width = p_dec->fmt_in.video.i_width; p_sys->p_context->height = p_dec->fmt_in.video.i_height; p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel; /* ***** Get configuration of ffmpeg plugin ***** */ p_sys->p_context->workaround_bugs = config_GetInt( p_dec, "ffmpeg-workaround-bugs" ); p_sys->p_context->error_resilience = config_GetInt( p_dec, "ffmpeg-error-resilience" ); var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "grayscale", &val ); if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY; var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-vismv", &val ); #if LIBAVCODEC_BUILD >= 4698 if( val.i_int ) p_sys->p_context->debug_mv = val.i_int; #endif var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-lowres", &val ); #if LIBAVCODEC_BUILD >= 4723 if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int; #endif /* ***** ffmpeg frame skipping ***** */ var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-hurry-up", &val ); p_sys->b_hurry_up = val.b_bool; /* ***** ffmpeg direct rendering ***** */ p_sys->b_direct_rendering = 0; var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-dr", &val ); if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) && ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) && /* Apparently direct rendering doesn't work with YUV422P */ p_sys->p_context->pix_fmt != PIX_FMT_YUV422P && /* H264 uses too many reference frames */ p_sys->i_codec_id != CODEC_ID_H264 && !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) && #if LIBAVCODEC_BUILD >= 4698 !p_sys->p_context->debug_mv ) #else 1 ) #endif { /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to do another check in ffmpeg_GetFrameBuf() */ p_sys->b_direct_rendering = 1; } #ifdef LIBAVCODEC_PP p_sys->p_pp = NULL; p_sys->b_pp = p_sys->b_pp_async = p_sys->b_pp_init = VLC_FALSE; p_sys->p_pp = E_(OpenPostproc)( p_dec, &p_sys->b_pp_async ); #endif /* ffmpeg doesn't properly release old pictures when frames are skipped */ //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0; if( p_sys->b_direct_rendering ) { msg_Dbg( p_dec, "using direct rendering" ); p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE; } /* Always use our get_buffer wrapper so we can calculate the * PTS correctly */ p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf; p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf; p_sys->p_context->opaque = p_dec; /* ***** init this codec with special data ***** */ if( p_dec->fmt_in.i_extra ) { int i_size = p_dec->fmt_in.i_extra; if( p_sys->i_codec_id == CODEC_ID_SVQ3 ) { uint8_t *p; p_sys->p_context->extradata_size = i_size + 12; p = p_sys->p_context->extradata = malloc( p_sys->p_context->extradata_size ); memcpy( &p[0], "SVQ3", 4 ); memset( &p[4], 0, 8 ); memcpy( &p[12], p_dec->fmt_in.p_extra, i_size ); /* Now remove all atoms before the SMI one */ if( p_sys->p_context->extradata_size > 0x5a && strncmp( &p[0x56], "SMI ", 4 ) ) { uint8_t *psz = &p[0x52]; while( psz < &p[p_sys->p_context->extradata_size - 8] ) { int i_size = GetDWBE( psz ); if( i_size <= 1 ) { /* FIXME handle 1 as long size */ break; } if( !strncmp( &psz[4], "SMI ", 4 ) ) { memmove( &p[0x52], psz, &p[p_sys->p_context->extradata_size] - psz ); break; } psz += i_size; } } } else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '0' ) || p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '3' ) || p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '2', '0' ) ) { if( p_dec->fmt_in.i_extra == 8 ) { p_sys->p_context->extradata_size = 8; p_sys->p_context->extradata = malloc( 8 ); memcpy( p_sys->p_context->extradata, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); p_sys->p_context->sub_id= ((uint32_t*)p_dec->fmt_in.p_extra)[1]; msg_Warn( p_dec, "using extra data for RV codec sub_id=%08x", p_sys->p_context->sub_id ); } } /* FIXME: remove when ffmpeg deals properly with avc1 */ else if( p_dec->fmt_in.i_codec == VLC_FOURCC('a','v','c','1') ) { ; } /* End FIXME */ else { p_sys->p_context->extradata_size = i_size; p_sys->p_context->extradata = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); memcpy( p_sys->p_context->extradata, p_dec->fmt_in.p_extra, i_size ); memset( &((uint8_t*)p_sys->p_context->extradata)[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); } } /* ***** misc init ***** */ p_sys->input_pts = p_sys->input_dts = 0; p_sys->i_pts = 0; p_sys->b_has_b_frames = VLC_FALSE; p_sys->b_first_frame = VLC_TRUE; p_sys->i_late_frames = 0; p_sys->i_buffer = 0; p_sys->i_buffer_orig = 1; p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig ); /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); /* Setup palette */ #if LIBAVCODEC_BUILD >= 4688 if( p_dec->fmt_in.video.p_palette ) p_sys->p_context->palctrl = (AVPaletteControl *)p_dec->fmt_in.video.p_palette; else p_sys->p_context->palctrl = &palette_control; #endif /* ***** Open the codec ***** */ vlc_mutex_lock( lockval.p_address ); if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 ) { vlc_mutex_unlock( lockval.p_address ); msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); free( p_sys ); return VLC_EGENERIC; } vlc_mutex_unlock( lockval.p_address ); msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); return VLC_SUCCESS; }
/***************************************************************************** * WaveOutThread: this thread will capture play notification events. ***************************************************************************** * We use this thread to feed new audio samples to the sound card because * we are not authorized to use waveOutWrite() directly in the waveout * callback. *****************************************************************************/ static void WaveOutThread( notification_thread_t *p_notif ) { aout_instance_t *p_aout = p_notif->p_aout; aout_sys_t *p_sys = p_aout->output.p_sys; aout_buffer_t *p_buffer = NULL; WAVEHDR *p_waveheader = p_sys->waveheader; int i, i_queued_frames; vlc_bool_t b_sleek; /* We don't want any resampling when using S/PDIF */ b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i'); while( 1 ) { WaitForSingleObject( p_sys->event, INFINITE ); /* Cleanup and find out the current latency */ i_queued_frames = 0; for( i = 0; i < FRAMES_NUM; i++ ) { if( (p_waveheader[i].dwFlags & WHDR_DONE) && p_waveheader[i].dwUser ) { /* Unprepare and free the buffers which has just been played */ waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i], sizeof(WAVEHDR) ); if( p_waveheader[i].dwUser != 1 ) aout_BufferFree( (aout_buffer_t *)p_waveheader[i].dwUser ); p_waveheader[i].dwUser = 0; } /* Check if frame buf is available */ if( !(p_waveheader[i].dwFlags & WHDR_DONE) ) { i_queued_frames++; } } if( p_aout->b_die ) return; /* Try to fill in as many frame buffers as possible */ for( i = 0; i < FRAMES_NUM; i++ ) { /* Check if frame buf is available */ if( p_waveheader[i].dwFlags & WHDR_DONE ) { /* Take into account the latency */ p_buffer = aout_OutputNextBuffer( p_aout, mdate() + 1000000 * i_queued_frames / p_aout->output.output.i_rate * p_aout->output.i_nb_samples, b_sleek ); if( !p_buffer && i_queued_frames ) { /* We aren't late so no need to play a blank sample */ break; } /* Do the channel reordering */ if( p_buffer && p_sys->b_chan_reorder ) { aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes, p_sys->waveformat.Format.nChannels, p_sys->pi_chan_table, p_sys->waveformat.Format.wBitsPerSample ); } PlayWaveOut( p_aout, p_sys->h_waveout, &p_waveheader[i], p_buffer ); i_queued_frames++; } } } }
static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig ) { /* First update information based on i_objectTypeIndication */ switch( p_decconfig->i_objectProfileIndication ) { case( 0x20 ): /* MPEG4 VIDEO */ p_track->fmt.i_codec = VLC_CODEC_MP4V; break; case( 0x21 ): /* H.264 */ p_track->fmt.i_codec = VLC_CODEC_H264; break; case( 0x40): p_track->fmt.i_codec = VLC_CODEC_MP4A; if( p_decconfig->i_decoder_specific_info_len >= 2 && p_decconfig->p_decoder_specific_info[0] == 0xF8 && (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 ) { p_track->fmt.i_codec = VLC_CODEC_ALS; } break; case( 0x60): case( 0x61): case( 0x62): case( 0x63): case( 0x64): case( 0x65): /* MPEG2 video */ p_track->fmt.i_codec = VLC_CODEC_MPGV; break; /* Theses are MPEG2-AAC */ case( 0x66): /* main profile */ case( 0x67): /* Low complexity profile */ case( 0x68): /* Scaleable Sampling rate profile */ p_track->fmt.i_codec = VLC_CODEC_MP4A; break; /* True MPEG 2 audio */ case( 0x69): p_track->fmt.i_codec = VLC_CODEC_MPGA; break; case( 0x6a): /* MPEG1 video */ p_track->fmt.i_codec = VLC_CODEC_MPGV; break; case( 0x6b): /* MPEG1 audio */ p_track->fmt.i_codec = VLC_CODEC_MPGA; break; case( 0x6c ): /* jpeg */ p_track->fmt.i_codec = VLC_CODEC_JPEG; break; case( 0x6d ): /* png */ p_track->fmt.i_codec = VLC_CODEC_PNG; break; case( 0x6e ): /* jpeg2000 */ p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' ); break; case( 0xa3 ): /* vc1 */ p_track->fmt.i_codec = VLC_CODEC_VC1; break; case( 0xa4 ): p_track->fmt.i_codec = VLC_CODEC_DIRAC; break; case( 0xa5 ): p_track->fmt.i_codec = VLC_CODEC_A52; break; case( 0xa6 ): p_track->fmt.i_codec = VLC_CODEC_EAC3; break; case( 0xa9 ): /* dts */ case( 0xaa ): /* DTS-HD HRA */ case( 0xab ): /* DTS-HD Master Audio */ p_track->fmt.i_codec = VLC_CODEC_DTS; break; case( 0xDD ): p_track->fmt.i_codec = VLC_CODEC_VORBIS; break; /* Private ID */ case( 0xe0 ): /* NeroDigital: dvd subs */ if( p_track->fmt.i_cat == SPU_ES ) { p_track->fmt.i_codec = VLC_CODEC_SPU; if( p_track->i_width > 0 ) p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width; if( p_track->i_height > 0 ) p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height; break; } case( 0xe1 ): /* QCelp for 3gp */ if( p_track->fmt.i_cat == AUDIO_ES ) { p_track->fmt.i_codec = VLC_CODEC_QCELP; } break; /* Fallback */ default: /* Unknown entry, but don't touch i_fourcc */ msg_Warn( p_demux, "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])", p_decconfig->i_objectProfileIndication, p_track->i_track_ID ); break; } p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len; if( p_track->fmt.i_extra > 0 ) { p_track->fmt.p_extra = malloc( p_track->fmt.i_extra ); memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info, p_track->fmt.i_extra ); } if( p_track->fmt.i_codec == VLC_CODEC_SPU && p_track->fmt.i_extra >= 16 * 4 ) { for( int i = 0; i < 16; i++ ) { p_track->fmt.subs.spu.palette[1 + i] = GetDWBE((char*)p_track->fmt.p_extra + i * 4); } p_track->fmt.subs.spu.palette[0] = 0xBeef; } }
/***************************************************************************** * OpenWaveOut: open the waveout sound device ****************************************************************************/ static int OpenWaveOut( aout_instance_t *p_aout, int i_format, int i_channels, int i_nb_channels, int i_rate, vlc_bool_t b_probe ) { MMRESULT result; unsigned int i; /* Set sound format */ #define waveformat p_aout->output.p_sys->waveformat waveformat.dwChannelMask = 0; for( i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ ) { if( i_channels & pi_channels_src[i] ) waveformat.dwChannelMask |= pi_channels_in[i]; } switch( i_format ) { case VLC_FOURCC('s','p','d','i'): i_nb_channels = 2; /* To prevent channel re-ordering */ waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; waveformat.Format.wBitsPerSample = 16; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF; break; case VLC_FOURCC('f','l','3','2'): waveformat.Format.wBitsPerSample = sizeof(float) * 8; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; case VLC_FOURCC('s','1','6','l'): waveformat.Format.wBitsPerSample = 16; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_PCM; waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_PCM; break; } waveformat.Format.nChannels = i_nb_channels; waveformat.Format.nSamplesPerSec = i_rate; waveformat.Format.nBlockAlign = waveformat.Format.wBitsPerSample / 8 * i_nb_channels; waveformat.Format.nAvgBytesPerSec = waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign; /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */ if( i_nb_channels <= 2 ) { waveformat.Format.cbSize = 0; } else { waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; waveformat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); } /* Open the device */ result = waveOutOpen( &p_aout->output.p_sys->h_waveout, WAVE_MAPPER, (WAVEFORMATEX *)&waveformat, (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout, CALLBACK_FUNCTION | (b_probe?WAVE_FORMAT_QUERY:0) ); if( result == WAVERR_BADFORMAT ) { msg_Warn( p_aout, "waveOutOpen failed WAVERR_BADFORMAT" ); return VLC_EGENERIC; } if( result == MMSYSERR_ALLOCATED ) { msg_Warn( p_aout, "waveOutOpen failed WAVERR_ALLOCATED" ); return VLC_EGENERIC; } if( result != MMSYSERR_NOERROR ) { msg_Warn( p_aout, "waveOutOpen failed" ); return VLC_EGENERIC; } p_aout->output.p_sys->b_chan_reorder = aout_CheckChannelReorder( pi_channels_in, pi_channels_out, waveformat.dwChannelMask, i_nb_channels, p_aout->output.p_sys->pi_chan_table ); if( p_aout->output.p_sys->b_chan_reorder ) { msg_Dbg( p_aout, "channel reordering needed" ); } return VLC_SUCCESS; #undef waveformat }
/***************************************************************************** * Probe: probe the audio device for available formats and channels *****************************************************************************/ static void Probe( aout_instance_t * p_aout ) { vlc_value_t val, text; int i_format; unsigned int i_physical_channels; var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = _("Audio Device"); var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL ); /* Test for 5.1 support */ i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; if( p_aout->output.output.i_physical_channels == i_physical_channels ) { if( OpenWaveOutPCM( p_aout, &i_format, i_physical_channels, 6, p_aout->output.output.i_rate, VLC_TRUE ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_5_1; text.psz_string = N_("5.1"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5.1 channels" ); } } /* Test for 2 Front 2 Rear support */ i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; if( ( p_aout->output.output.i_physical_channels & i_physical_channels ) == i_physical_channels ) { if( OpenWaveOutPCM( p_aout, &i_format, i_physical_channels, 4, p_aout->output.output.i_rate, VLC_TRUE ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_2F2R; text.psz_string = N_("2 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 4 channels" ); } } /* Test for stereo support */ i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; if( OpenWaveOutPCM( p_aout, &i_format, i_physical_channels, 2, p_aout->output.output.i_rate, VLC_TRUE ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_STEREO; text.psz_string = N_("Stereo"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 2 channels" ); } /* Test for mono support */ i_physical_channels = AOUT_CHAN_CENTER; if( OpenWaveOutPCM( p_aout, &i_format, i_physical_channels, 1, p_aout->output.output.i_rate, VLC_TRUE ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_MONO; text.psz_string = N_("Mono"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 1 channel" ); } /* Test for SPDIF support */ if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) ) { if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'), p_aout->output.output.i_physical_channels, aout_FormatNbChannels( &p_aout->output.output ), p_aout->output.output.i_rate, VLC_TRUE ) == VLC_SUCCESS ) { msg_Dbg( p_aout, "device supports A/52 over S/PDIF" ); val.i_int = AOUT_VAR_SPDIF; text.psz_string = N_("A/52 over S/PDIF"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if( config_GetInt( p_aout, "spdif" ) ) var_Set( p_aout, "audio-device", val ); } } var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL ); if( val.i_int <= 0 ) { /* Probe() has failed. */ var_Destroy( p_aout, "audio-device" ); return; } var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); val.b_bool = VLC_TRUE; var_Set( p_aout, "intf-change", val ); }
/***************************************************************************** * Open: open the audio device ***************************************************************************** * This function opens and setups Win32 waveOut *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; vlc_value_t val; int i; /* Allocate structure */ p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) ); if( p_aout->output.p_sys == NULL ) { msg_Err( p_aout, "out of memory" ); return VLC_EGENERIC; } p_aout->output.pf_play = Play; p_aout->b_die = VLC_FALSE; if( var_Type( p_aout, "audio-device" ) == 0 ) { Probe( p_aout ); } if( var_Get( p_aout, "audio-device", &val ) < 0 ) { /* Probe() has failed. */ free( p_aout->output.p_sys ); return VLC_EGENERIC; } var_Create( p_aout, "waveout-float32", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); /* Open the device */ if( val.i_int == AOUT_VAR_SPDIF ) { p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i'); if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'), p_aout->output.output.i_physical_channels, aout_FormatNbChannels( &p_aout->output.output ), p_aout->output.output.i_rate, VLC_FALSE ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); free( p_aout->output.p_sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ p_aout->output.i_nb_samples = A52_FRAME_NB; p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->output.output.i_frame_length = A52_FRAME_NB; p_aout->output.p_sys->i_buffer_size = p_aout->output.output.i_bytes_per_frame; aout_VolumeNoneInit( p_aout ); } else { if( val.i_int == AOUT_VAR_5_1 ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; } else if( val.i_int == AOUT_VAR_2F2R ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; } else if( val.i_int == AOUT_VAR_MONO ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; } else { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } if( OpenWaveOutPCM( p_aout, &p_aout->output.output.i_format, p_aout->output.output.i_physical_channels, aout_FormatNbChannels( &p_aout->output.output ), p_aout->output.output.i_rate, VLC_FALSE ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); free( p_aout->output.p_sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ p_aout->output.i_nb_samples = FRAME_SIZE; aout_FormatPrepare( &p_aout->output.output ); p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * p_aout->output.output.i_bytes_per_frame; aout_VolumeSoftInit( p_aout ); } waveOutReset( p_aout->output.p_sys->h_waveout ); /* Allocate silence buffer */ p_aout->output.p_sys->p_silence_buffer = malloc( p_aout->output.p_sys->i_buffer_size ); if( p_aout->output.p_sys->p_silence_buffer == NULL ) { free( p_aout->output.p_sys ); msg_Err( p_aout, "out of memory" ); return 1; } /* Zero the buffer. WinCE doesn't have calloc(). */ memset( p_aout->output.p_sys->p_silence_buffer, 0, p_aout->output.p_sys->i_buffer_size ); /* Now we need to setup our waveOut play notification structure */ p_aout->output.p_sys->p_notif = vlc_object_create( p_aout, sizeof(notification_thread_t) ); p_aout->output.p_sys->p_notif->p_aout = p_aout; p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL ); /* Then launch the notification thread */ if( vlc_thread_create( p_aout->output.p_sys->p_notif, "waveOut Notification Thread", WaveOutThread, VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) ) { msg_Err( p_aout, "cannot create WaveOutThread" ); } /* We need to kick off the playback in order to have the callback properly * working */ for( i = 0; i < FRAMES_NUM; i++ ) { p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE; p_aout->output.p_sys->waveheader[i].dwUser = 0; } PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout, &p_aout->output.p_sys->waveheader[0], NULL ); return 0; }
/***************************************************************************** * Open: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; switch( p_dec->fmt_in.i_codec ) { case VLC_CODEC_COOK: case VLC_CODEC_ATRAC3: case VLC_FOURCC('s','i','p','r'): break; default: return VLC_EGENERIC; } /* Channel detection */ if( p_dec->fmt_in.audio.i_channels <= 0 || p_dec->fmt_in.audio.i_channels > 6 ) { msg_Err( p_dec, "invalid number of channels (not between 1 and 6): %i", p_dec->fmt_in.audio.i_channels ); return VLC_EGENERIC; } p_dec->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) ); if( !p_sys ) return VLC_ENOMEM; /* Flavor for SIPR codecs */ p_sys->i_codec_flavor = -1; if( p_dec->fmt_in.i_codec == VLC_FOURCC('s','i','p','r') ) { p_sys->i_codec_flavor = p_dec->fmt_in.audio.i_flavor; msg_Dbg( p_dec, "Got sipr flavor %d", p_sys->i_codec_flavor ); } if( OpenDll( p_dec ) != VLC_SUCCESS ) { free( p_sys ); return VLC_EGENERIC; } #ifdef LOADER if( p_sys->win32_dll ) Close( p_this ); #endif es_format_Init( &p_dec->fmt_out, AUDIO_ES, VLC_CODEC_S16N ); p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; p_dec->fmt_out.audio.i_bitspersample = p_dec->fmt_in.audio.i_bitspersample; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels]; date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); date_Set( &p_sys->end_date, 0 ); p_dec->pf_decode_audio = Decode; p_sys->p_out = malloc( 4096 * 10 ); if( !p_sys->p_out ) { free( p_sys ); return VLC_ENOMEM; } p_sys->i_out = 0; return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; int i; const bool b_avc = (p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' )); if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 ) return VLC_EGENERIC; if( b_avc && p_dec->fmt_in.i_extra < 7 ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { return VLC_ENOMEM; } p_sys->p_ccs = cc_storage_new(); if( unlikely(!p_sys->p_ccs) ) { free( p_dec->p_sys ); return VLC_ENOMEM; } packetizer_Init( &p_sys->packetizer, p_h264_startcode, sizeof(p_h264_startcode), startcode_FindAnnexB, p_h264_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_slice = false; p_sys->p_frame = NULL; p_sys->pp_frame_last = &p_sys->p_frame; p_sys->b_frame_sps = false; p_sys->b_frame_pps = false; p_sys->b_header= false; p_sys->b_sps = false; p_sys->b_pps = false; for( i = 0; i <= H264_SPS_ID_MAX; i++ ) p_sys->pp_sps[i] = NULL; for( i = 0; i <= H264_PPS_ID_MAX; i++ ) p_sys->pp_pps[i] = NULL; p_sys->i_recovery_frames = -1; p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_idr_pic_id = -1; p_sys->slice.i_frame_num = -1; p_sys->slice.i_frame_type = 0; p_sys->slice.i_pic_parameter_set_id = -1; p_sys->slice.i_field_pic_flag = 0; p_sys->slice.i_bottom_field_flag = -1; p_sys->slice.i_pic_order_cnt_lsb = -1; p_sys->slice.i_delta_pic_order_cnt_bottom = -1; p_sys->b_timing_info_present_flag = false; p_sys->b_pic_struct_present_flag = false; p_sys->b_cpb_dpb_delays_present_flag = false; p_sys->i_cpb_removal_delay_length_minus1 = 0; p_sys->i_dpb_output_delay_length_minus1 = 0; p_sys->b_even_frame = false; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->i_prev_dts = VLC_TS_INVALID; p_sys->i_prev_pts = VLC_TS_INVALID; p_sys->i_dpb_output_delay = 0; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_H264; p_dec->fmt_out.b_packetized = true; if( b_avc ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ if( h264_isavcC( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) ) { free( p_dec->fmt_out.p_extra ); size_t i_size; p_dec->fmt_out.p_extra = h264_avcC_to_AnnexB_NAL( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_size, &p_sys->i_avcC_length_size ); p_dec->fmt_out.i_extra = i_size; p_sys->b_header = !!p_dec->fmt_out.i_extra; if(!p_dec->fmt_out.p_extra) { msg_Err( p_dec, "Invalid AVC extradata"); Close( p_this ); return VLC_EGENERIC; } } else { msg_Err( p_dec, "Invalid or missing AVC extradata"); Close( p_this ); return VLC_EGENERIC; } /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; } /* */ if( p_dec->fmt_out.i_extra > 0 ) { packetizer_Header( &p_sys->packetizer, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); } if( b_avc ) { if( !p_sys->b_sps || !p_sys->b_pps ) { msg_Err( p_dec, "Invalid or missing SPS %d or PPS %d in AVC extradata", p_sys->b_sps, p_sys->b_pps ); Close( p_this ); return VLC_EGENERIC; } msg_Dbg( p_dec, "Packetizer fed with AVC, nal length size=%d", p_sys->i_avcC_length_size ); } /* CC are the same for H264/AVC in T35 sections (ETSI TS 101 154) */ p_dec->pf_get_cc = GetCc; p_dec->pf_flush = PacketizeFlush; return VLC_SUCCESS; }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 53, 15, 0 ) { VLC_CODEC_PRORES, CODEC_ID_PRORES, VIDEO_ES }, #endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 53, 32, 0 ) { VLC_CODEC_INDEO4, CODEC_ID_INDEO4, VIDEO_ES }, #endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 53, 17, 0 ) { VLC_CODEC_BMVVIDEO, CODEC_ID_BMV_VIDEO, VIDEO_ES }, #endif #if 0 /* UNTESTED VideoGames*/ { VLC_FOURCC('W','C','3','V'), CODEC_ID_XAN_WC3, VIDEO_ES, "XAN wc3 Video" }, { VLC_FOURCC('W','C','4','V'), CODEC_ID_XAN_WC4, VIDEO_ES, "XAN wc4 Video" }, { VLC_FOURCC('S','T','3','C'), CODEC_ID_TXD, VIDEO_ES, "Renderware TeXture Dictionary" }, { VLC_FOURCC('V','Q','A','V'), CODEC_ID_WS_VQA, VIDEO_ES, "WestWood Vector Quantized Animation" }, { VLC_FOURCC('T','S','E','Q'), CODEC_ID_TIERTEXSEQVIDEO, VIDEO_ES, "Tiertex SEQ Video" }, { VLC_FOURCC('D','X','A','1'), CODEC_ID_DXA, VIDEO_ES, "Feeble DXA Video" }, { VLC_FOURCC('D','C','I','V'), CODEC_ID_DSICINVIDEO, VIDEO_ES, "Delphine CIN Video" }, { VLC_FOURCC('T','H','P','V'), CODEC_ID_THP, VIDEO_ES, "THP Video" },
/***************************************************************************** * Open *****************************************************************************/ static int Open( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; ModPlug_Settings settings; /* We accept file based on extension match */ if( !p_demux->obj.force ) { const char *psz_ext = p_demux->psz_filepath ? strrchr( p_demux->psz_filepath, '.' ) : NULL; if( psz_ext ) psz_ext++; if( Validate( p_demux, psz_ext ) ) { msg_Dbg( p_demux, "MOD validation failed (ext=%s)", psz_ext ? psz_ext : ""); return VLC_EGENERIC; } } const int64_t i_size = stream_Size( p_demux->s ); if( i_size <= 0 || i_size >= MOD_MAX_FILE_SIZE ) return VLC_EGENERIC; p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) ); if( !p_sys ) return VLC_ENOMEM; msg_Dbg( p_demux, "loading complete file (could be long)" ); p_sys->i_data = i_size; p_sys->p_data = vlc_obj_malloc( p_this, p_sys->i_data ); if( unlikely(p_sys->p_data == NULL) ) return VLC_ENOMEM; p_sys->i_data = vlc_stream_Read( p_demux->s, p_sys->p_data, p_sys->i_data ); if( p_sys->i_data <= 0 ) { msg_Err( p_demux, "failed to read the complete file" ); return VLC_EGENERIC; } /* Configure modplug before loading the file */ vlc_mutex_lock( &libmodplug_lock ); ModPlug_GetSettings( &settings ); settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING; settings.mChannels = 2; settings.mBits = 16; settings.mFrequency = 44100; settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; if( var_InheritBool( p_demux, "mod-noisereduction" ) ) settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION; if( var_InheritBool( p_demux, "mod-reverb" ) ) settings.mFlags |= MODPLUG_ENABLE_REVERB; settings.mReverbDepth = var_InheritInteger( p_demux, "mod-reverb-level" ); settings.mReverbDelay = var_InheritInteger( p_demux, "mod-reverb-delay" ); if( var_InheritBool( p_demux, "mod-megabass" ) ) settings.mFlags |= MODPLUG_ENABLE_MEGABASS; settings.mBassAmount = var_InheritInteger( p_demux, "mod-megabass-level" ); settings.mBassRange = var_InheritInteger( p_demux, "mod-megabass-range" ); if( var_InheritBool( p_demux, "mod-surround" ) ) settings.mFlags |= MODPLUG_ENABLE_SURROUND; settings.mSurroundDepth = var_InheritInteger( p_demux, "mod-surround-level" ); settings.mSurroundDelay = var_InheritInteger( p_demux, "mod-surround-delay" ); ModPlug_SetSettings( &settings ); p_sys->f = ModPlug_Load( p_sys->p_data, p_sys->i_data ); vlc_mutex_unlock( &libmodplug_lock ); if( !p_sys->f ) { msg_Err( p_demux, "failed to understand the file" ); return VLC_EGENERIC; } /* init time */ date_Init( &p_sys->pts, settings.mFrequency, 1 ); date_Set( &p_sys->pts, VLC_TICK_0 ); p_sys->i_length = VLC_TICK_FROM_MS( ModPlug_GetLength( p_sys->f ) ); msg_Dbg( p_demux, "MOD loaded name=%s length=%"PRId64"ms", ModPlug_GetName( p_sys->f ), MS_FROM_VLC_TICK( p_sys->i_length ) ); #ifdef WORDS_BIGENDIAN es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 't', 'w', 'o', 's' ) ); #else es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) ); #endif p_sys->fmt.audio.i_rate = settings.mFrequency; p_sys->fmt.audio.i_channels = settings.mChannels; p_sys->fmt.audio.i_bitspersample = settings.mBits; p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt ); if( unlikely(p_sys->es == NULL) ) return VLC_ENOMEM; /* Fill p_demux field */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys; return VLC_SUCCESS; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with a complete compressed frame. ****************************************************************************/ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; picture_t *p_pic = 0; png_uint_32 i_width, i_height; int i_color_type, i_interlace_type, i_compression_type, i_filter_type; int i_bit_depth, i; png_structp p_png; png_infop p_info, p_end_info; png_bytep *p_row_pointers = NULL; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; p_sys->b_error = VLC_FALSE; p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); if( p_png == NULL ) { block_Release( p_block ); *pp_block = NULL; return NULL; } p_info = png_create_info_struct( p_png ); if( p_info == NULL ) { png_destroy_read_struct( &p_png, png_infopp_NULL, png_infopp_NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } p_end_info = png_create_info_struct( p_png ); if( p_end_info == NULL ) { png_destroy_read_struct( &p_png, &p_info, png_infopp_NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } /* libpng longjmp's there in case of error */ if( setjmp( png_jmpbuf( p_png ) ) ) goto error; png_set_read_fn( p_png, (void *)p_block, user_read ); png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning ); png_read_info( p_png, p_info ); if( p_sys->b_error ) goto error; png_get_IHDR( p_png, p_info, &i_width, &i_height, &i_bit_depth, &i_color_type, &i_interlace_type, &i_compression_type, &i_filter_type); if( p_sys->b_error ) goto error; /* Set output properties */ p_dec->fmt_out.i_codec = VLC_FOURCC('R','V','3','2'); p_dec->fmt_out.video.i_width = i_width; p_dec->fmt_out.video.i_height = i_height; p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height; if( i_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( p_png ); if( i_color_type == PNG_COLOR_TYPE_GRAY || i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( p_png ); /* Strip to 8 bits per channel */ if( i_bit_depth == 16 ) png_set_strip_16( p_png ); if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) ) { png_set_tRNS_to_alpha( p_png ); } else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) ) { p_dec->fmt_out.i_codec = VLC_FOURCC('R','V','2','4'); } if( i_color_type & PNG_COLOR_MASK_COLOR && p_dec->fmt_out.i_codec != VLC_FOURCC('R','V','2','4') ) { /* Invert colors */ png_set_bgr( p_png ); } /* Get a new picture */ p_pic = p_dec->pf_vout_buffer_new( p_dec ); if( !p_pic ) goto error; /* Decode picture */ p_row_pointers = malloc( sizeof(png_bytep) * i_height ); for( i = 0; i < (int)i_height; i++ ) p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i; png_read_image( p_png, p_row_pointers ); if( p_sys->b_error ) goto error; png_read_end( p_png, p_end_info ); if( p_sys->b_error ) goto error; png_destroy_read_struct( &p_png, &p_info, &p_end_info ); free( p_row_pointers ); p_pic->date = p_block->i_pts > 0 ? p_block->i_pts : p_block->i_dts; block_Release( p_block ); *pp_block = NULL; return p_pic; error: if( p_row_pointers ) free( p_row_pointers ); png_destroy_read_struct( &p_png, &p_info, &p_end_info ); block_Release( p_block ); *pp_block = NULL; return NULL; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; uint32_t i_accel = 0; if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV ) return VLC_EGENERIC; /* Select onl recognized original format (standard mpeg video) */ switch( p_dec->fmt_in.i_original_fourcc ) { case VLC_FOURCC('m','p','g','1'): case VLC_FOURCC('m','p','g','2'): case VLC_FOURCC('m','p','g','v'): case VLC_FOURCC('P','I','M','1'): case VLC_FOURCC('h','d','v','2'): break; default: if( p_dec->fmt_in.i_original_fourcc ) return VLC_EGENERIC; break; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL ) return VLC_ENOMEM; /* Initialize the thread properties */ p_sys->p_mpeg2dec = NULL; p_sys->p_synchro = NULL; p_sys->p_info = NULL; p_sys->i_current_pts = 0; p_sys->i_previous_pts = 0; p_sys->i_current_dts = 0; p_sys->i_previous_dts = 0; p_sys->i_sar_num = 0; p_sys->i_sar_den = 0; p_sys->b_garbage_pic = false; p_sys->b_slice_i = false; p_sys->b_second_field = false; p_sys->b_skip = false; p_sys->b_preroll = false; DpbInit( p_dec ); p_sys->i_cc_pts = 0; p_sys->i_cc_dts = 0; p_sys->i_cc_flags = 0; #if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0) p_dec->pf_get_cc = GetCc; cc_Init( &p_sys->cc ); #endif p_sys->p_gop_user_data = NULL; p_sys->i_gop_user_data = 0; #if defined( __i386__ ) || defined( __x86_64__ ) if( vlc_CPU_MMX() ) i_accel |= MPEG2_ACCEL_X86_MMX; if( vlc_CPU_3dNOW() ) i_accel |= MPEG2_ACCEL_X86_3DNOW; if( vlc_CPU_MMXEXT() ) i_accel |= MPEG2_ACCEL_X86_MMXEXT; #elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ ) if( vlc_CPU_ALTIVEC() ) i_accel |= MPEG2_ACCEL_PPC_ALTIVEC; #elif defined(__arm__) # ifdef MPEG2_ACCEL_ARM i_accel |= MPEG2_ACCEL_ARM; # endif # ifdef MPEG2_ACCEL_ARM_NEON if( vlc_CPU_ARM_NEON() ) i_accel |= MPEG2_ACCEL_ARM_NEON; # endif /* TODO: sparc */ #else /* If we do not know this CPU, trust libmpeg2's feature detection */ i_accel = MPEG2_ACCEL_DETECT; #endif /* Set CPU acceleration features */ mpeg2_accel( i_accel ); /* Initialize decoder */ p_sys->p_mpeg2dec = mpeg2_init(); if( p_sys->p_mpeg2dec == NULL) { msg_Err( p_dec, "mpeg2_init() failed" ); free( p_sys ); return VLC_EGENERIC; } p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec ); p_dec->pf_decode_video = DecodeBlock; p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = 0; return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ 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 ) { /* Planar YUV */ case VLC_FOURCC('I','4','4','4'): case VLC_FOURCC('I','4','2','2'): case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('Y','V','1','2'): case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('I','4','1','1'): case VLC_FOURCC('I','4','1','0'): case VLC_FOURCC('Y','V','U','9'): /* Packed YUV */ case VLC_FOURCC('Y','U','Y','2'): case VLC_FOURCC('U','Y','V','Y'): /* RGB */ case VLC_FOURCC('R','V','3','2'): case VLC_FOURCC('R','V','2','4'): case VLC_FOURCC('R','V','1','6'): case VLC_FOURCC('R','V','1','5'): break; default: return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } /* Misc init */ p_dec->p_sys->b_packetizer = VLC_FALSE; p_sys->i_pts = 0; p_sys->b_invert = 0; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = VLC_TRUE; } if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } /* Find out p_vdec->i_raw_size */ vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height, p_dec->fmt_in.video.i_aspect ); p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel * p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8; /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec; if( !p_dec->fmt_in.video.i_aspect ) { p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; } else p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect; if( p_dec->fmt_in.video.i_rmask ) p_dec->fmt_out.video.i_rmask = p_dec->fmt_in.video.i_rmask; if( p_dec->fmt_in.video.i_gmask ) p_dec->fmt_out.video.i_gmask = p_dec->fmt_in.video.i_gmask; if( p_dec->fmt_in.video.i_bmask ) p_dec->fmt_out.video.i_bmask = p_dec->fmt_in.video.i_bmask; /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; return VLC_SUCCESS; }
/***************************************************************************** * Thread: *****************************************************************************/ static void Thread( vlc_object_t *p_this ) { galaktos_thread_t *p_thread = (galaktos_thread_t*)p_this; int count=0; double realfps=0,fpsstart=0; int timed=0; int timestart=0; int mspf=0; /* Get on OpenGL provider */ p_thread->p_opengl = (vout_thread_t *)vlc_object_create( p_this, VLC_OBJECT_OPENGL ); if( p_thread->p_opengl == NULL ) { msg_Err( p_thread, "out of memory" ); return; } vlc_object_attach( p_thread->p_opengl, p_this ); /* Initialize vout parameters */ vout_InitFormat( &p_thread->p_opengl->fmt_in, VLC_FOURCC('R','V','3','2'), p_thread->i_width, p_thread->i_height, 1 ); p_thread->p_opengl->i_window_width = p_thread->i_width; p_thread->p_opengl->i_window_height = p_thread->i_height; p_thread->p_opengl->render.i_width = p_thread->i_width; p_thread->p_opengl->render.i_height = p_thread->i_width; p_thread->p_opengl->render.i_aspect = VOUT_ASPECT_FACTOR; p_thread->p_opengl->b_scale = VLC_TRUE; p_thread->p_opengl->b_fullscreen = VLC_FALSE; p_thread->p_opengl->i_alignment = 0; p_thread->p_opengl->fmt_in.i_sar_num = 1; p_thread->p_opengl->fmt_in.i_sar_den = 1; p_thread->p_opengl->fmt_render = p_thread->p_opengl->fmt_in; p_thread->p_module = module_Need( p_thread->p_opengl, "opengl provider", NULL, 0 ); if( p_thread->p_module == NULL ) { msg_Err( p_thread, "unable to initialize OpenGL" ); vlc_object_detach( p_thread->p_opengl ); vlc_object_destroy( p_thread->p_opengl ); return; } p_thread->p_opengl->pf_init( p_thread->p_opengl ); setup_opengl( p_thread->i_width, p_thread->i_height ); CreateRenderTarget(512, &RenderTargetTextureID, NULL); timestart=mdate()/1000; while( !p_thread->b_die ) { mspf = 1000 / 60; if( galaktos_update( p_thread ) == 1 ) { p_thread->b_die = 1; } if( p_thread->psz_title ) { free( p_thread->psz_title ); p_thread->psz_title = NULL; } if (++count%100==0) { realfps=100/((mdate()/1000-fpsstart)/1000); // printf("%f\n",realfps); fpsstart=mdate()/1000; } //framerate limiter timed=mspf-(mdate()/1000-timestart); // printf("%d,%d\n",time,mspf); if (timed>0) msleep(1000*timed); // printf("Limiter %d\n",(mdate()/1000-timestart)); timestart=mdate()/1000; } /* Free the openGL provider */ module_Unneed( p_thread->p_opengl, p_thread->p_module ); vlc_object_detach( p_thread->p_opengl ); vlc_object_destroy( p_thread->p_opengl ); }
set_description( N_("SDL_image video decoder") ) set_capability( "decoder", 60 ) set_callbacks( OpenDecoder, CloseDecoder ) add_shortcut( "sdl_image" ) vlc_module_end () static const struct supported_fmt_t { vlc_fourcc_t i_fourcc; const char *psz_sdl_type; } p_supported_fmt[] = { { VLC_CODEC_TARGA, "TGA" }, { VLC_CODEC_BMP, "BMP" }, { VLC_CODEC_PNM, "PNM" }, { VLC_FOURCC('x','p','m',' '), "XPM" }, { VLC_FOURCC('x','c','f',' '), "XCF" }, { VLC_CODEC_PCX, "PCX" }, { VLC_CODEC_GIF, "GIF" }, { VLC_CODEC_JPEG, "JPG" }, { VLC_CODEC_TIFF, "TIF" }, { VLC_FOURCC('l','b','m',' '), "LBM" }, { VLC_CODEC_PNG, "PNG" } }; /***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *)p_this;
} chroma_table[] = { /* Planar YUV formats */ {VLC_CODEC_I444, PIX_FMT_YUV444P, 0, 0, 0 }, {VLC_CODEC_J444, PIX_FMT_YUVJ444P, 0, 0, 0 }, {VLC_CODEC_I440, PIX_FMT_YUV440P, 0, 0, 0 }, {VLC_CODEC_J440, PIX_FMT_YUVJ440P, 0, 0, 0 }, {VLC_CODEC_I422, PIX_FMT_YUV422P, 0, 0, 0 }, {VLC_CODEC_J422, PIX_FMT_YUVJ422P, 0, 0, 0 }, {VLC_CODEC_I420, PIX_FMT_YUV420P, 0, 0, 0 }, {VLC_CODEC_YV12, PIX_FMT_YUV420P, 0, 0, 0 }, {VLC_FOURCC('I','Y','U','V'), PIX_FMT_YUV420P, 0, 0, 0 }, {VLC_CODEC_J420, PIX_FMT_YUVJ420P, 0, 0, 0 }, {VLC_CODEC_I411, PIX_FMT_YUV411P, 0, 0, 0 }, {VLC_CODEC_I410, PIX_FMT_YUV410P, 0, 0, 0 }, {VLC_FOURCC('Y','V','U','9'), PIX_FMT_YUV410P, 0, 0, 0 }, {VLC_FOURCC('N','V','1','2'), PIX_FMT_NV12, 0, 0, 0 }, {VLC_FOURCC('N','V','2','1'), PIX_FMT_NV21, 0, 0, 0 }, {VLC_CODEC_I420_9L, PIX_FMT_YUV420P9LE, 0, 0, 0 }, {VLC_CODEC_I420_9B, PIX_FMT_YUV420P9BE, 0, 0, 0 }, {VLC_CODEC_I420_10L, PIX_FMT_YUV420P10LE, 0, 0, 0 }, {VLC_CODEC_I420_10B, PIX_FMT_YUV420P10BE, 0, 0, 0 }, #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,13,0) {VLC_CODEC_I422_9L, PIX_FMT_YUV422P9LE, 0, 0, 0 }, {VLC_CODEC_I422_9B, PIX_FMT_YUV422P9BE, 0, 0, 0 },
/* Create a fourcc from a string. * XXX it assumes that the string is at least four bytes */ static inline vlc_fourcc_t CreateFourcc( const char *psz_fourcc ) { return VLC_FOURCC( psz_fourcc[0], psz_fourcc[1], psz_fourcc[2], psz_fourcc[3] ); }
/***************************************************************************** * Open: initializes ES structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; byte_t *p_peek; int i_peek = 0; vlc_bool_t b_big_endian = 0; /* Arbitrary initialisation */ /* Check if we are dealing with a WAV file */ if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 && !memcmp( p_peek, "RIFF", 4 ) && !memcmp( p_peek + 8, "WAVE", 4 ) ) { int i_size; /* Skip the wave header */ i_peek = 12 + 8; while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek && memcmp( p_peek + i_peek - 8, "data", 4 ) ) { i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8; } /* TODO: should check wave format and sample_rate */ /* Some A52 wav files don't begin with a sync code so we do a more * extensive search */ i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2); i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE); while( i_peek < i_size ) { if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS ) /* The data is stored in 16 bits words */ i_peek += 2; else { /* Check following sync code */ if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE, &b_big_endian ) != VLC_SUCCESS ) { i_peek += 2; continue; } break; } } } /* Have a peep at the show. */ if( stream_Peek( p_demux->s, &p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 ) < i_peek + A52_MAX_HEADER_SIZE * 2 ) { /* Stream too short */ msg_Warn( p_demux, "cannot peek()" ); return VLC_EGENERIC; } if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS ) { if( strncmp( p_demux->psz_demux, "a52", 3 ) ) { return VLC_EGENERIC; } /* User forced */ msg_Err( p_demux, "this doesn't look like a A52 audio stream, " "continuing anyway" ); } /* Fill p_demux fields */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->b_start = VLC_TRUE; p_sys->i_mux_rate = 0; p_sys->b_big_endian = b_big_endian; /* * Load the A52 packetizer */ p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER ); p_sys->p_packetizer->pf_decode_audio = 0; p_sys->p_packetizer->pf_decode_video = 0; p_sys->p_packetizer->pf_decode_sub = 0; p_sys->p_packetizer->pf_packetize = 0; /* Initialization of decoder structure */ es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) ); p_sys->p_packetizer->p_module = module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 ); if( !p_sys->p_packetizer->p_module ) { msg_Err( p_demux, "cannot find A52 packetizer" ); return VLC_EGENERIC; } /* Create one program */ p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in ); return VLC_SUCCESS; }
static int parse_Manifest( stream_t *s ) { stream_sys_t *p_sys = s->p_sys; xml_t *vlc_xml = NULL; xml_reader_t *vlc_reader = NULL; int type = UNKNOWN_ES; const char *name, *value; stream_t *st = s->p_source; msg_Dbg( s, "Manifest parsing\n" ); vlc_xml = xml_Create( st ); if( !vlc_xml ) { msg_Err( s, "Failed to open XML parser" ); return VLC_EGENERIC; } vlc_reader = xml_ReaderCreate( vlc_xml, st ); if( !vlc_reader ) { msg_Err( s, "Failed to open source for parsing" ); xml_Delete( vlc_xml ); return VLC_EGENERIC; } const char *node; uint8_t *WaveFormatEx; sms_stream_t *sms = NULL; quality_level_t *ql = NULL; int64_t start_time = 0, duration = 0; int64_t computed_start_time = 0, computed_duration = 0; unsigned next_track_id = 1; unsigned next_qid = 1; int loop_count = 0; bool b_weird = false; #define TIMESCALE 10000000 while( (type = xml_ReaderNextNode( vlc_reader, &node )) > 0 ) { switch( type ) { case XML_READER_STARTELEM: if( !strcmp( node, "SmoothStreamingMedia" ) ) { while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Duration" ) ) p_sys->vod_duration = strtoull( value, NULL, 10 ); if( !strcmp( name, "TimeScale" ) ) p_sys->timescale = strtoull( value, NULL, 10 ); } if( !p_sys->timescale ) p_sys->timescale = TIMESCALE; } if( !strcmp( node, "StreamIndex" ) ) { sms = sms_New(); if( unlikely( !sms ) ) return VLC_ENOMEM; sms->id = next_track_id; next_track_id++; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Type" ) ) { if( !strcmp( value, "video" ) ) sms->type = VIDEO_ES; else if( !strcmp( value, "audio" ) ) sms->type = AUDIO_ES; else if( !strcmp( value, "text" ) ) sms->type = SPU_ES; } if( !strcmp( name, "Name" ) ) sms->name = strdup( value ); if( !strcmp( name, "TimeScale" ) ) sms->timescale = strtoull( value, NULL, 10 ); if( !strcmp( name, "FourCC" ) ) sms->default_FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); if( !strcmp( name, "Chunks" ) ) { sms->vod_chunks_nb = strtol( value, NULL, 10 ); if( sms->vod_chunks_nb == 0 ) /* live */ sms->vod_chunks_nb = UINT32_MAX; } if( !strcmp( name, "QualityLevels" ) ) sms->qlevel_nb = strtoul( value, NULL, 10 ); if( !strcmp( name, "Url" ) ) sms->url_template = strdup(value); } if( sms && !sms->timescale ) sms->timescale = TIMESCALE; if( !sms->name ) { if( sms->type == VIDEO_ES ) sms->name = strdup( "video" ); else if( sms->type == AUDIO_ES ) sms->name = strdup( "audio" ); else if( sms->type == SPU_ES ) sms->name = strdup( "text" ); } vlc_array_append( p_sys->sms_streams, sms ); } if( !strcmp( node, "QualityLevel" ) ) { ql = ql_New(); if( !ql ) return VLC_ENOMEM; ql->id = next_qid; next_qid++; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Index" ) ) ql->Index = strtol( value, NULL, 10 ); if( !strcmp( name, "Bitrate" ) ) ql->Bitrate = strtoull( value, NULL, 10 ); if( !strcmp( name, "PacketSize" ) ) ql->nBlockAlign = strtoull( value, NULL, 10 ); if( !strcmp( name, "FourCC" ) ) ql->FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); if( !strcmp( name, "CodecPrivateData" ) ) ql->CodecPrivateData = strdup( value ); if( !strcmp( name, "WaveFormatEx" ) ) { WaveFormatEx = decode_string_hex_to_binary( value ); uint16_t data_len = ((uint16_t *)WaveFormatEx)[8]; ql->CodecPrivateData = strndup( value + 36, data_len * 2 ); uint16_t wf_tag = ((uint16_t *)WaveFormatEx)[0]; wf_tag_to_fourcc( wf_tag, &ql->FourCC, NULL ); ql->Channels = ((uint16_t *)WaveFormatEx)[1]; ql->SamplingRate = ((uint32_t *)WaveFormatEx)[1]; ql->nBlockAlign = ((uint16_t *)WaveFormatEx)[6]; ql->BitsPerSample = ((uint16_t *)WaveFormatEx)[7]; free( WaveFormatEx ); } if( !strcmp( name, "MaxWidth" ) || !strcmp( name, "Width" ) ) ql->MaxWidth = strtoul( value, NULL, 10 ); if( !strcmp( name, "MaxHeight" ) || !strcmp( name, "Height" ) ) ql->MaxHeight = strtoul( value, NULL, 10 ); if( !strcmp( name, "Channels" ) ) ql->Channels = strtoul( value, NULL, 10 ); if( !strcmp( name, "SamplingRate" ) ) ql->SamplingRate = strtoul( value, NULL, 10 ); if( !strcmp( name, "BitsPerSample" ) ) ql->BitsPerSample = strtoul( value, NULL, 10 ); } vlc_array_append( sms->qlevels, ql ); } if( !strcmp( node, "c" ) ) { loop_count++; start_time = duration = -1; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "t" ) ) start_time = strtoull( value, NULL, 10 ); if( !strcmp( name, "d" ) ) duration = strtoull( value, NULL, 10 ); } if( start_time == -1 ) { assert( duration != -1 ); computed_start_time += computed_duration; computed_duration = duration; } else if( duration == -1 ) { assert( start_time != -1 ); /* Handle weird Manifests which give only the start time * of the first segment. In those cases, we have to look * at the start time of the second segment to compute * the duration of the first one. */ if( loop_count == 1 ) { b_weird = true; computed_start_time = start_time; continue; } computed_duration = start_time - computed_start_time; if( !b_weird ) computed_start_time = start_time; } else { if( b_weird ) computed_duration = start_time - computed_start_time; else { computed_start_time = start_time; computed_duration = duration; } } if( unlikely( chunk_New( sms, computed_duration, computed_start_time ) == NULL ) ) { return VLC_ENOMEM; } if( b_weird && start_time != -1 ) computed_start_time = start_time; } break; case XML_READER_ENDELEM: if( strcmp( node, "StreamIndex" ) ) break; computed_start_time = 0; computed_duration = 0; loop_count = 0; if( b_weird && !chunk_New( sms, computed_duration, computed_start_time ) ) return VLC_ENOMEM; b_weird = false; next_qid = 1; if( sms->qlevel_nb == 0 ) sms->qlevel_nb = vlc_array_count( sms->qlevels ); break; case XML_READER_NONE: break; case XML_READER_TEXT: break; default: return VLC_EGENERIC; } } #undef TIMESCALE xml_ReaderDelete( vlc_reader ); xml_Delete( vlc_xml ); return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; /* Codec specifics */ uint32_t i_bcm_codec_subtype = 0; switch ( p_dec->fmt_in.i_codec ) { case VLC_CODEC_H264: if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) ) i_bcm_codec_subtype = BC_MSUBTYPE_AVC1; else i_bcm_codec_subtype = BC_MSUBTYPE_H264; break; case VLC_CODEC_VC1: i_bcm_codec_subtype = BC_MSUBTYPE_VC1; break; case VLC_CODEC_WMV3: i_bcm_codec_subtype = BC_MSUBTYPE_WMV3; break; case VLC_CODEC_WMVA: i_bcm_codec_subtype = BC_MSUBTYPE_WMVA; break; case VLC_CODEC_MPGV: i_bcm_codec_subtype = BC_MSUBTYPE_MPEG2VIDEO; break; /* Not ready for production yet case VLC_CODEC_MP4V: i_bcm_codec_subtype = BC_MSUBTYPE_DIVX; break; case VLC_CODEC_DIV3: i_bcm_codec_subtype = BC_MSUBTYPE_DIVX311; break; */ default: return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ p_sys = malloc( sizeof(*p_sys) ); if( !p_sys ) return VLC_ENOMEM; /* Fill decoder_sys_t */ p_dec->p_sys = p_sys; p_sys->i_nal_size = 4; // assume 4 byte start codes p_sys->i_sps_pps_size = 0; p_sys->p_sps_pps_buf = NULL; p_dec->p_sys->p_pic = NULL; p_dec->p_sys->proc_out = NULL; /* Win32 code * * We cannot link and ship BCM dll, even with LGPL license (too big) * and if we don't ship it, the plugin would not work depending on the * installation order => DLopen */ #ifdef USE_DL_OPENING # define DLL_NAME "bcmDIL.dll" # define PATHS_NB 3 static const char *psz_paths[PATHS_NB] = { DLL_NAME, "C:\\Program Files\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME, "C:\\Program Files (x86)\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME, }; for( int i = 0; i < PATHS_NB; i++ ) { HINSTANCE p_bcm_dll = LoadLibraryA( psz_paths[i] ); if( p_bcm_dll ) { p_sys->p_bcm_dll = p_bcm_dll; break; } } if( !p_sys->p_bcm_dll ) { msg_Dbg( p_dec, "Couldn't load the CrystalHD dll"); return VLC_EGENERIC; } #define LOAD_SYM( a ) \ BC_FUNC( a ) = (void *)GetProcAddress( p_sys->p_bcm_dll, ( #a ) ); \ if( !BC_FUNC( a ) ) { \ msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; } #define LOAD_SYM_PSYS( a ) \ p_sys->BC_FUNC( a ) = (void *)GetProcAddress( p_sys->p_bcm_dll, #a ); \ if( !p_sys->BC_FUNC( a ) ) { \ msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; } BC_STATUS (WINAPI *OurDtsDeviceOpen)( HANDLE *hDevice, U32 mode ); LOAD_SYM( DtsDeviceOpen ); BC_STATUS (WINAPI *OurDtsCrystalHDVersion)( HANDLE hDevice, PBC_INFO_CRYSTAL bCrystalInfo ); LOAD_SYM( DtsCrystalHDVersion ); BC_STATUS (WINAPI *OurDtsSetColorSpace)( HANDLE hDevice, BC_OUTPUT_FORMAT Mode422 ); LOAD_SYM( DtsSetColorSpace ); BC_STATUS (WINAPI *OurDtsSetInputFormat)( HANDLE hDevice, BC_INPUT_FORMAT *pInputFormat ); LOAD_SYM( DtsSetInputFormat ); BC_STATUS (WINAPI *OurDtsOpenDecoder)( HANDLE hDevice, U32 StreamType ); LOAD_SYM( DtsOpenDecoder ); BC_STATUS (WINAPI *OurDtsStartDecoder)( HANDLE hDevice ); LOAD_SYM( DtsStartDecoder ); BC_STATUS (WINAPI *OurDtsStartCapture)( HANDLE hDevice ); LOAD_SYM( DtsStartCapture ); LOAD_SYM_PSYS( DtsCloseDecoder ); LOAD_SYM_PSYS( DtsDeviceClose ); LOAD_SYM_PSYS( DtsFlushInput ); LOAD_SYM_PSYS( DtsStopDecoder ); LOAD_SYM_PSYS( DtsGetDriverStatus ); LOAD_SYM_PSYS( DtsProcInput ); LOAD_SYM_PSYS( DtsProcOutput ); LOAD_SYM_PSYS( DtsIsEndOfStream ); #undef LOAD_SYM #undef LOAD_SYM_PSYS #endif /* USE_DL_OPENING */ #ifdef DEBUG_CRYSTALHD msg_Dbg( p_dec, "Trying to open CrystalHD HW"); #endif /* Get the handle for the device */ if( BC_FUNC(DtsDeviceOpen)( &p_sys->bcm_handle, (DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW | DTS_SKIP_TX_CHK_CPB) ) // | DTS_DFLT_RESOLUTION(vdecRESOLUTION_720p29_97) ) ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't find and open the BCM CrystalHD device" ); free( p_sys ); return VLC_EGENERIC; } #ifdef DEBUG_CRYSTALHD BC_INFO_CRYSTAL info; if( BC_FUNC(DtsCrystalHDVersion)( p_sys->bcm_handle, &info ) == BC_STS_SUCCESS ) { msg_Dbg( p_dec, "Using CrystalHD Driver version: %i.%i.%i, " "Library version: %i.%i.%i, Firmware version: %i.%i.%i", info.drvVersion.drvRelease, info.drvVersion.drvMajor, info.drvVersion.drvMinor, info.dilVersion.dilRelease, info.dilVersion.dilMajor, info.dilVersion.dilMinor, info.fwVersion.fwRelease, info.fwVersion.fwMajor, info.fwVersion.fwMinor ); } #endif /* Special case for AVC1 */ if( i_bcm_codec_subtype == BC_MSUBTYPE_AVC1 ) { if( p_dec->fmt_in.i_extra > 0 ) { msg_Dbg( p_dec, "Parsing extra infos for avc1" ); if( crystal_insert_sps_pps( p_dec, (uint8_t*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) != VLC_SUCCESS ) goto error; } else { msg_Err( p_dec, "Missing extra infos for avc1" ); goto error; } } /* Always use YUY2 color */ if( BC_FUNC(DtsSetColorSpace)( p_sys->bcm_handle, OUTPUT_MODE422_YUY2 ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't set the color space. Please report this!" ); goto error; } /* Prepare Input for the device */ BC_INPUT_FORMAT p_in; memset( &p_in, 0, sizeof(BC_INPUT_FORMAT) ); p_in.OptFlags = 0x51; /* 0b 0 1 01 0001 */ p_in.mSubtype = i_bcm_codec_subtype; p_in.startCodeSz = p_sys->i_nal_size; p_in.pMetaData = p_sys->p_sps_pps_buf; p_in.metaDataSz = p_sys->i_sps_pps_size; p_in.width = p_dec->fmt_in.video.i_width; p_in.height = p_dec->fmt_in.video.i_height; p_in.Progressive = true; if( BC_FUNC(DtsSetInputFormat)( p_sys->bcm_handle, &p_in ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't set the color space. Please report this!" ); goto error; } /* Open a decoder */ if( BC_FUNC(DtsOpenDecoder)( p_sys->bcm_handle, BC_STREAM_TYPE_ES ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't open the CrystalHD decoder" ); goto error; } /* Start it */ if( BC_FUNC(DtsStartDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't start the decoder" ); goto error; } if( BC_FUNC(DtsStartCapture)( p_sys->bcm_handle ) != BC_STS_SUCCESS ) { msg_Err( p_dec, "Couldn't start the capture" ); goto error_complete; } /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = 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; /* Set callbacks */ p_dec->pf_decode_video = DecodeBlock; msg_Info( p_dec, "Opened CrystalHD hardware with success" ); return VLC_SUCCESS; error_complete: BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle ); error: BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Media handling *****************************************************************************/ static vod_media_t *MediaNew( vod_t *p_vod, const char *psz_name, input_item_t *p_item ) { vod_media_t *p_media = calloc( 1, sizeof(vod_media_t) ); if( !p_media ) return NULL; p_media->p_vod = p_vod; p_media->rtsp = NULL; TAB_INIT( p_media->i_es, p_media->es ); p_media->psz_mux = NULL; p_media->i_length = input_item_GetDuration( p_item ); vlc_mutex_lock( &p_item->lock ); msg_Dbg( p_vod, "media '%s' has %i declared ES", psz_name, p_item->i_es ); for( int i = 0; i < p_item->i_es; i++ ) { es_format_t *p_fmt = p_item->es[i]; switch( p_fmt->i_codec ) { case VLC_FOURCC( 'm', 'p', '2', 't' ): p_media->psz_mux = "ts"; break; case VLC_FOURCC( 'm', 'p', '2', 'p' ): p_media->psz_mux = "ps"; break; } assert(p_media->psz_mux == NULL || p_item->i_es == 1); media_es_t *p_es = calloc( 1, sizeof(media_es_t) ); if( !p_es ) continue; p_es->es_id = p_fmt->i_id; p_es->rtsp_id = NULL; if (rtp_get_fmt(VLC_OBJECT(p_vod), p_fmt, p_media->psz_mux, &p_es->rtp_fmt) != VLC_SUCCESS) { free(p_es); continue; } TAB_APPEND( p_media->i_es, p_media->es, p_es ); msg_Dbg(p_vod, " - added ES %u %s (%4.4s)", p_es->rtp_fmt.payload_type, p_es->rtp_fmt.ptname, (char *)&p_fmt->i_codec); } vlc_mutex_unlock( &p_item->lock ); if (p_media->i_es == 0) { msg_Err(p_vod, "no ES was added to the media, aborting"); goto error; } msg_Dbg(p_vod, "adding media '%s'", psz_name); CommandPush( p_vod, RTSP_CMD_TYPE_ADD, p_media, psz_name ); return p_media; error: MediaDel(p_vod, p_media); return NULL; }
/***************************************************************************** * Open: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('S','V','Q','3'): /* Sorenson v3 */ /* case VLC_FOURCC('S','V','Q','1'): Sorenson v1 case VLC_FOURCC('Z','y','G','o'): case VLC_FOURCC('V','P','3','1'): case VLC_FOURCC('3','I','V','1'): */ case VLC_FOURCC('r','l','e',' '): /* QuickTime animation (RLE) */ case VLC_FOURCC('r','p','z','a'): /* QuickTime Apple Video */ case VLC_FOURCC('a','z','p','r'): /* QuickTime animation (RLE) */ #ifdef LOADER p_dec->p_sys = NULL; p_dec->pf_decode_video = DecodeVideo; return VLC_SUCCESS; #else return OpenVideo( p_dec ); #endif case VLC_FOURCC('s','a','m','r'): /* 3GPP AMR audio */ case VLC_FOURCC('m','p','4','a'): /* MPEG-4 audio */ case VLC_FOURCC('Q','D','M','C'): /* QDesign */ case VLC_FOURCC('Q','D','M','2'): /* QDesign* 2 */ case VLC_FOURCC('Q','c','l','p'): /* Qualcomm Purevoice Codec */ case VLC_FOURCC('Q','C','L','P'): /* Qualcomm Purevoice Codec */ case VLC_FOURCC('M','A','C','3'): /* MACE3 audio decoder */ case VLC_FOURCC('M','A','C','6'): /* MACE6 audio decoder */ case VLC_FOURCC('d','v','c','a'): /* DV Audio */ case VLC_FOURCC('s','o','w','t'): /* 16-bit Little Endian */ case VLC_FOURCC('t','w','o','s'): /* 16-bit Big Endian */ case VLC_FOURCC('a','l','a','w'): /* ALaw 2:1 */ case VLC_FOURCC('u','l','a','w'): /* mu-Law 2:1 */ case VLC_FOURCC('r','a','w',' '): /* 8-bit offset binaries */ case VLC_FOURCC('f','l','3','2'): /* 32-bit Floating Point */ case VLC_FOURCC('f','l','6','4'): /* 64-bit Floating Point */ case VLC_FOURCC('i','n','2','4'): /* 24-bit Interger */ case VLC_FOURCC('i','n','3','2'): /* 32-bit Integer */ case 0x0011: /* DVI IMA */ case 0x6D730002: /* Microsoft ADPCM-ACM */ case 0x6D730011: /* DVI Intel IMAADPCM-ACM */ #ifdef LOADER p_dec->p_sys = NULL; p_dec->pf_decode_audio = DecodeAudio; return VLC_SUCCESS; #else return OpenAudio( p_dec ); #endif default: return VLC_EGENERIC; } }