static int AVI_ChunkRead_indx( stream_t *s, avi_chunk_t *p_chk ) { unsigned int i_count, i; int32_t i_dummy; avi_chunk_indx_t *p_indx = (avi_chunk_indx_t*)p_chk; AVI_READCHUNK_ENTER; AVI_READ2BYTES( p_indx->i_longsperentry ); AVI_READ1BYTE ( p_indx->i_indexsubtype ); AVI_READ1BYTE ( p_indx->i_indextype ); AVI_READ4BYTES( p_indx->i_entriesinuse ); AVI_READ4BYTES( p_indx->i_id ); p_indx->idx.std = NULL; p_indx->idx.field = NULL; p_indx->idx.super = NULL; if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == 0 ) { AVI_READ8BYTES( p_indx->i_baseoffset ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 8 ); p_indx->i_entriesinuse = i_count; p_indx->idx.std = xcalloc( i_count, sizeof( indx_std_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ4BYTES( p_indx->idx.std[i].i_offset ); AVI_READ4BYTES( p_indx->idx.std[i].i_size ); } } else if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == AVI_INDEX_2FIELD ) { AVI_READ8BYTES( p_indx->i_baseoffset ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 12 ); p_indx->i_entriesinuse = i_count; p_indx->idx.field = xcalloc( i_count, sizeof( indx_field_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ4BYTES( p_indx->idx.field[i].i_offset ); AVI_READ4BYTES( p_indx->idx.field[i].i_size ); AVI_READ4BYTES( p_indx->idx.field[i].i_offsetfield2 ); } } else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES ) { p_indx->i_baseoffset = 0; AVI_READ4BYTES( i_dummy ); AVI_READ4BYTES( i_dummy ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 16 ); p_indx->i_entriesinuse = i_count; p_indx->idx.super = xcalloc( i_count, sizeof( indx_super_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ8BYTES( p_indx->idx.super[i].i_offset ); AVI_READ4BYTES( p_indx->idx.super[i].i_size ); AVI_READ4BYTES( p_indx->idx.super[i].i_duration ); } } else { msg_Warn( (vlc_object_t*)s, "unknown type/subtype index" ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "indx: type=%d subtype=%d entry=%d", p_indx->i_indextype, p_indx->i_indexsubtype, p_indx->i_entriesinuse ); #endif AVI_READCHUNK_EXIT( VLC_SUCCESS ); }
/***************************************************************************** * ffmpeg_OpenCodec: *****************************************************************************/ int ffmpeg_OpenCodec( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_sys->p_context->extradata_size <= 0 ) { if( p_sys->i_codec_id == CODEC_ID_VC1 || p_sys->i_codec_id == CODEC_ID_VORBIS || p_sys->i_codec_id == CODEC_ID_THEORA || p_sys->i_codec_id == CODEC_ID_AAC ) { msg_Warn( p_dec, "waiting for extra data for codec %s", p_sys->psz_namecodec ); return 1; } } if( p_dec->fmt_in.i_cat == VIDEO_ES ) { 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_coded_sample = p_dec->fmt_in.video.i_bits_per_pixel; } else if( p_dec->fmt_in.i_cat == AUDIO_ES ) { p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate; p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels; p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign; p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate; p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.audio.i_bitspersample; } int ret; vlc_avcodec_lock(); ret = avcodec_open( p_sys->p_context, p_sys->p_codec ); vlc_avcodec_unlock(); if( ret < 0 ) return VLC_EGENERIC; msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); #ifdef HAVE_AVCODEC_MT if( p_dec->fmt_in.i_cat == VIDEO_ES ) { switch( p_sys->p_context->active_thread_type ) { case FF_THREAD_FRAME: msg_Dbg( p_dec, "using frame thread mode with %d threads", p_sys->p_context->thread_count ); break; case FF_THREAD_SLICE: msg_Dbg( p_dec, "using slice thread mode with %d threads", p_sys->p_context->thread_count ); break; case 0: if( p_sys->p_context->thread_count > 1 ) msg_Warn( p_dec, "failed to enable threaded decoding" ); break; default: msg_Warn( p_dec, "using unknown thread mode with %d threads", p_sys->p_context->thread_count ); break; } } #endif p_sys->b_delayed_open = false; return VLC_SUCCESS; }
static void OutputFrame( sout_stream_sys_t *p_sys, picture_t *p_pic, bool b_need_duplicate, sout_stream_t *p_stream, sout_stream_id_t *id, block_t **out ) { picture_t *p_pic2 = NULL; /* * Encoding */ /* Check if we have a subpicture to overlay */ if( p_sys->p_spu ) { video_format_t fmt = id->p_encoder->fmt_in.video; if( fmt.i_visible_width <= 0 || fmt.i_visible_height <= 0 ) { fmt.i_visible_width = fmt.i_width; fmt.i_visible_height = fmt.i_height; fmt.i_x_offset = 0; fmt.i_y_offset = 0; } subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt, p_pic->date, p_pic->date, false ); /* Overlay subpicture */ if( p_subpic ) { if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) ) { /* We can't modify the picture, we need to duplicate it, * in this point the picture is already p_encoder->fmt.in format*/ picture_t *p_tmp = video_new_buffer_encoder( id->p_encoder ); if( likely( p_tmp ) ) { picture_Copy( p_tmp, p_pic ); picture_Release( p_pic ); p_pic = p_tmp; } } if( unlikely( !p_sys->p_spu_blend ) ) p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt ); if( likely( p_sys->p_spu_blend ) ) picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic ); subpicture_Delete( p_subpic ); } } if( p_sys->i_threads == 0 ) { block_t *p_block; p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic ); block_ChainAppend( out, p_block ); } if( p_sys->b_master_sync ) { mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1; mtime_t i_video_drift = p_pic->date - i_pts; if (unlikely ( i_video_drift > MASTER_SYNC_MAX_DRIFT || i_video_drift < -MASTER_SYNC_MAX_DRIFT ) ) { msg_Dbg( p_stream, "video drift is too high (%"PRId64"), resetting master sync", i_video_drift ); date_Set( &id->interpolated_pts, p_pic->date ); i_pts = p_pic->date + 1; } date_Increment( &id->interpolated_pts, 1 ); if( unlikely( b_need_duplicate ) ) { if( p_sys->i_threads >= 1 ) { /* We can't modify the picture, we need to duplicate it */ p_pic2 = video_new_buffer_encoder( id->p_encoder ); if( likely( p_pic2 != NULL ) ) { picture_Copy( p_pic2, p_pic ); p_pic2->date = i_pts; } } else { block_t *p_block; p_pic->date = i_pts; p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic); block_ChainAppend( out, p_block ); } } } if( p_sys->i_threads == 0 ) { picture_Release( p_pic ); } else { vlc_mutex_lock( &p_sys->lock_out ); picture_fifo_Push( p_sys->pp_pics, p_pic ); if( p_pic2 != NULL ) { picture_fifo_Push( p_sys->pp_pics, p_pic2 ); } vlc_cond_signal( &p_sys->cond ); vlc_mutex_unlock( &p_sys->lock_out ); } }
/***************************************************************************** * Open: Initialize module's data structures and libdsm *****************************************************************************/ static int Open( vlc_object_t *p_this ) { access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; smb_stat st; /* Init p_access */ access_InitFields( p_access ); p_sys = p_access->p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) ); if( p_access->p_sys == NULL ) return VLC_ENOMEM; p_sys->p_ns = netbios_ns_new(); if( p_sys->p_ns == NULL ) goto error; p_sys->p_session = smb_session_new(); if( p_sys->p_session == NULL ) goto error; vlc_UrlParse( &p_sys->url, p_access->psz_location, 0 ); get_credentials( p_access ); if( get_address( p_access ) != VLC_SUCCESS ) goto error; msg_Dbg( p_access, "Creds: username = %s, domain = %s", p_sys->creds.login, p_sys->creds.domain ); msg_Dbg( p_access, "Session: Host name = %s, ip = %s", p_sys->netbios_name, inet_ntoa( p_sys->addr ) ); /* Now that we have the required data, let's establish a session */ if( !smb_session_connect( p_sys->p_session, p_sys->netbios_name, p_sys->addr.s_addr, SMB_TRANSPORT_TCP ) ) { msg_Err( p_access, "Unable to connect/negotiate SMB session"); goto error; } get_path( p_access ); if( login( p_access ) != VLC_SUCCESS ) { msg_Err( p_access, "Unable to connect to share %s", p_sys->psz_share ); goto error; } /* If there is no shares, browse them */ if( !p_sys->psz_share ) return BrowserInit( p_access ); msg_Dbg( p_access, "Path: Share name = %s, path = %s", p_sys->psz_share, p_sys->psz_path ); /* Let's finally ask a handle to the file we wanna read ! */ p_sys->i_fd = smb_fopen( p_sys->p_session, p_sys->i_tid, p_sys->psz_path, SMB_MOD_RO ); if( !p_sys->i_fd ) { msg_Err( p_access, "Unable to open file with path %s (in share %s)", p_sys->psz_path, p_sys->psz_share ); goto error; } st = smb_stat_fd( p_sys->p_session, p_sys->i_fd ); if( smb_stat_get( st, SMB_STAT_ISDIR ) ) { smb_fclose( p_sys->p_session, p_sys->i_fd ); return BrowserInit( p_access ); } msg_Dbg( p_access, "Successfully opened smb://%s", p_access->psz_location ); ACCESS_SET_CALLBACKS( Read, NULL, Control, Seek ); return VLC_SUCCESS; error: Close( p_this ); return VLC_EGENERIC; }
/***************************************************************************** * Open: open the rtsp connection *****************************************************************************/ static int Open( vlc_object_t *p_this ) { access_t *p_access = (access_t *)p_this; access_sys_t *p_sys; char* psz_server = NULL; int i_result; if( !p_access->psz_access || ( strncmp( p_access->psz_access, "rtsp", 4 ) && strncmp( p_access->psz_access, "pnm", 3 ) && strncmp( p_access->psz_access, "realrtsp", 8 ) )) { return VLC_EGENERIC; } p_access->pf_read = NULL; p_access->pf_block = BlockRead; p_access->pf_seek = Seek; p_access->pf_control = Control; p_access->info.i_update = 0; p_access->info.i_size = 0; p_access->info.i_pos = 0; p_access->info.b_eof = false; p_access->info.i_title = 0; p_access->info.i_seekpoint = 0; p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) ); if( !p_sys->p_rtsp ) { free( p_sys ); return VLC_ENOMEM; } p_sys->p_header = NULL; p_sys->p_rtsp->p_userdata = p_access; p_sys->p_rtsp->pf_connect = RtspConnect; p_sys->p_rtsp->pf_disconnect = RtspDisconnect; p_sys->p_rtsp->pf_read = RtspRead; p_sys->p_rtsp->pf_read_line = RtspReadLine; p_sys->p_rtsp->pf_write = RtspWrite; i_result = rtsp_connect( p_sys->p_rtsp, p_access->psz_path, 0 ); if( i_result ) { msg_Dbg( p_access, "could not connect to: %s", p_access->psz_path ); free( p_sys->p_rtsp ); p_sys->p_rtsp = NULL; goto error; } msg_Dbg( p_access, "rtsp connected" ); /* looking for server type */ if( rtsp_search_answers( p_sys->p_rtsp, "Server" ) ) psz_server = strdup( rtsp_search_answers( p_sys->p_rtsp, "Server" ) ); else { if( rtsp_search_answers( p_sys->p_rtsp, "RealChallenge1" ) ) psz_server = strdup("Real"); else psz_server = strdup("unknown"); } if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) ) { uint32_t bandwidth = 10485800; rmff_header_t *h; msg_Dbg( p_access, "found a real/helix rtsp server" ); if( !(h = real_setup_and_get_header( p_sys->p_rtsp, bandwidth )) ) { /* Check if we got a redirect */ if( rtsp_search_answers( p_sys->p_rtsp, "Location" ) ) { msg_Dbg( p_access, "redirect: %s", rtsp_search_answers(p_sys->p_rtsp, "Location") ); msg_Warn( p_access, "redirect not supported" ); goto error; } msg_Err( p_access, "rtsp session can not be established" ); dialog_Fatal( p_access, _("Session failed"), "%s", _("The requested RTSP session could not be established.") ); goto error; } p_sys->p_header = block_New( p_access, 4096 ); p_sys->p_header->i_buffer = rmff_dump_header( h, (char *)p_sys->p_header->p_buffer, 1024 ); rmff_free_header( h ); } else { msg_Warn( p_access, "only real/helix rtsp servers supported for now" ); goto error; } /* Update default_pts to a suitable value for file access */ var_Create( p_access, "realrtsp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); free( psz_server ); return VLC_SUCCESS; error: free( psz_server ); Close( p_this ); return VLC_EGENERIC; }
static chunk_t *get_chunk( stream_t *s, const bool wait, bool *pb_isinit ) { stream_sys_t *p_sys = s->p_sys; bool b_foo; if ( !pb_isinit ) pb_isinit = &b_foo; *pb_isinit = false; vlc_mutex_lock( &p_sys->lock ); assert(p_sys->p_current_stream); chunk_t *p_chunk = p_sys->p_current_stream->p_playback; /* init chunk handling, overrides the current one */ vlc_mutex_lock( &p_sys->playback.lock ); if ( p_sys->playback.init.p_datachunk ) { if ( p_sys->playback.init.p_startchunk == NULL || p_sys->playback.init.p_startchunk == p_chunk ) { /* Override current chunk and pass init chunk instead */ p_chunk = p_sys->playback.init.p_datachunk; *pb_isinit = true; setChunkOffset( p_sys, p_chunk ); #ifndef NDEBUG if ( !p_chunk->read_pos ) msg_Dbg( s, "Sending init chunk from offset %"PRId64, p_chunk->offset ); #endif vlc_mutex_unlock( &p_sys->playback.lock ); vlc_mutex_unlock( &p_sys->lock ); return p_chunk; } } vlc_mutex_unlock( &p_sys->playback.lock ); /* !init chunk handling */ vlc_mutex_lock( &p_sys->p_current_stream->chunks_lock ); vlc_mutex_unlock( &p_sys->lock ); while( p_chunk && !p_chunk->data ) { /* Yes I know, checking for p_sys->b_die is not reliable, * that's why vlc_object_alive() has been deprecated. But if I * understood well, there is no good solution with a stream_filter * module anyaway. */ if( !wait || p_sys->b_error ) { msg_Warn( s, "get_chunk failed! (starttime %"PRId64")", p_chunk->start_time ); vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock ); return NULL; } if( no_more_chunks( p_sys ) ) { msg_Info( s, "No more chunks, end of the VOD" ); vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock ); return NULL; } msg_Dbg( s, "get_chunk is waiting for chunk %"PRId64"!!!", p_chunk->start_time ); vlc_mutex_lock( &p_sys->playback.lock ); p_sys->playback.b_underrun = true; vlc_mutex_unlock( &p_sys->playback.lock ); vlc_cond_timedwait( &p_sys->playback.wait, &p_sys->p_current_stream->chunks_lock, mdate() + CLOCK_FREQ/2 ); } if ( p_chunk ) { setChunkOffset( p_sys, p_chunk ); #ifndef NDEBUG if ( !p_chunk->read_pos ) msg_Dbg( s, "Sending chunk %"PRId64" from offset %"PRId64, p_chunk->start_time, p_chunk->offset ); #endif } vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock ); return p_chunk; }
static void config_ReadFile( char *psz_file ) { FILE *p_file; char psz_line[2048]; int i; if ( psz_file == NULL ) { msg_Err( NULL, "no config file" ); return; } if ( (p_file = fopen( psz_file, "r" )) == NULL ) { msg_Err( NULL, "can't fopen config file %s", psz_file ); return; } while ( fgets( psz_line, sizeof(psz_line), p_file ) != NULL ) { output_config_t config; output_t *p_output; char *psz_token, *psz_parser; psz_parser = strchr( psz_line, '#' ); if ( psz_parser != NULL ) *psz_parser-- = '\0'; while ( psz_parser >= psz_line && isblank( *psz_parser ) ) *psz_parser-- = '\0'; if ( psz_line[0] == '\0' ) continue; config_Defaults( &config ); psz_token = strtok_r( psz_line, "\t\n ", &psz_parser ); if ( psz_token == NULL || !config_ParseHost( &config, psz_token )) { config_Free( &config ); continue; } psz_token = strtok_r( NULL, "\t\n ", &psz_parser ); if ( psz_token == NULL ) { config_Free( &config ); continue; } if( atoi( psz_token ) == 1 ) config.i_config |= OUTPUT_WATCH; else config.i_config &= ~OUTPUT_WATCH; psz_token = strtok_r( NULL, "\t\n ", &psz_parser ); if ( psz_token == NULL ) { config_Free( &config ); continue; } config.i_sid = strtol(psz_token, NULL, 0); psz_token = strtok_r( NULL, "\t\n ", &psz_parser ); if ( psz_token != NULL ) { psz_parser = NULL; for ( ; ; ) { psz_token = strtok_r( psz_token, ",", &psz_parser ); if ( psz_token == NULL ) break; config.pi_pids = realloc( config.pi_pids, (config.i_nb_pids + 1) * sizeof(uint16_t) ); config.pi_pids[config.i_nb_pids++] = strtol(psz_token, NULL, 0); psz_token = NULL; } } config_Print( &config ); p_output = output_Find( &config ); if ( p_output == NULL ) p_output = output_Create( &config ); if ( p_output != NULL ) { free( p_output->config.psz_displayname ); p_output->config.psz_displayname = strdup( config.psz_displayname ); config.i_config |= OUTPUT_VALID | OUTPUT_STILL_PRESENT; output_Change( p_output, &config ); demux_Change( p_output, &config ); } config_Free( &config ); } fclose( p_file ); for ( i = 0; i < i_nb_outputs; i++ ) { output_t *p_output = pp_outputs[i]; output_config_t config; config_Init( &config ); if ( (p_output->config.i_config & OUTPUT_VALID) && !(p_output->config.i_config & OUTPUT_STILL_PRESENT) ) { msg_Dbg( NULL, "closing %s", p_output->config.psz_displayname ); demux_Change( p_output, &config ); output_Close( p_output ); } p_output->config.i_config &= ~OUTPUT_STILL_PRESENT; config_Free( &config ); } }
/** * It loads the logo images into memory. * * Read the logo-file input switch, obtaining a list of images and * associated durations and transparencies. Store the image(s), and * times. An image without a stated time or opacity will use the * logo-delay and logo-opacity values. */ static void LogoListLoad( vlc_object_t *p_this, logo_list_t *p_logo_list, const char *psz_filename ) { char *psz_list; /* the list: <logo>[,[<delay>[,[<alpha>]]]][;...] */ char *psz_original; unsigned int i; logo_t *p_logo; /* the parsing's result */ p_logo_list->i_counter = 0; p_logo_list->i_next_pic = 0; psz_original = psz_list = strdup( psz_filename ); if( !psz_list ) abort(); /* Count the number logos == number of ';' + 1 */ p_logo_list->i_count = 1; for( i = 0; i < strlen( psz_list ); i++ ) { if( psz_list[i] == ';' ) p_logo_list->i_count++; } p_logo_list->p_logo = p_logo = (logo_t *)calloc( p_logo_list->i_count, sizeof(*p_logo) ); // sunqueen modify if( !p_logo ) abort(); /* Fill the data */ for( i = 0; i < p_logo_list->i_count; i++ ) { char *p_c = strchr( psz_list, ';' ); char *p_c2 = strchr( psz_list, ',' ); p_logo[i].i_alpha = -1; /* use default settings */ p_logo[i].i_delay = -1; /* use default settings */ if( p_c2 && ( p_c2 < p_c || !p_c ) ) { /* <logo>,<delay>[,<alpha>] type */ if( p_c2[1] != ',' && p_c2[1] != ';' && p_c2[1] != '\0' ) p_logo[i].i_delay = atoi( p_c2+1 ); *p_c2 = '\0'; if( ( p_c2 = strchr( p_c2+1, ',' ) ) && ( p_c2 < p_c || !p_c ) && p_c2[1] != ';' && p_c2[1] != '\0' ) p_logo[i].i_alpha = atoi( p_c2 + 1 ); } else { /* <logo> type */ if( p_c ) *p_c = '\0'; } msg_Dbg( p_this, "logo file name %s, delay %d, alpha %d", psz_list, p_logo[i].i_delay, p_logo[i].i_alpha ); p_logo[i].p_pic = LoadImage( p_this, psz_list ); if( !p_logo[i].p_pic ) { msg_Warn( p_this, "error while loading logo %s, will be skipped", psz_list ); } if( p_c ) psz_list = &p_c[1]; } /* initialize so that on the first update it will wrap back to 0 */ p_logo_list->i_counter = p_logo_list->i_count - 1; free( psz_original ); }
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context, const enum PixelFormat *pi_fmt ) { decoder_t *p_dec = p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; vlc_va_t *p_va = p_sys->p_va; if( p_va != NULL ) vlc_va_Delete( p_va ); /* Enumerate available formats */ bool can_hwaccel = false; for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ ) { const AVPixFmtDescriptor *dsc = av_pix_fmt_desc_get(pi_fmt[i]); if (dsc == NULL) continue; bool hwaccel = (dsc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0; msg_Dbg( p_dec, "available %sware decoder output format %d (%s)", hwaccel ? "hard" : "soft", pi_fmt[i], dsc->name ); if (hwaccel) can_hwaccel = true; } if (!can_hwaccel) goto end; /* Profile and level information is needed now. * TODO: avoid code duplication with avcodec.c */ if( p_context->profile != FF_PROFILE_UNKNOWN) p_dec->fmt_in.i_profile = p_context->profile; if( p_context->level != FF_LEVEL_UNKNOWN) p_dec->fmt_in.i_level = p_context->level; p_va = vlc_va_New( VLC_OBJECT(p_dec), p_sys->i_codec_id, &p_dec->fmt_in ); if( p_va == NULL ) goto end; for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ ) { if( p_va->pix_fmt != pi_fmt[i] ) continue; /* We try to call vlc_va_Setup when possible to detect errors when * possible (later is too late) */ if( p_context->width > 0 && p_context->height > 0 && vlc_va_Setup( p_va, &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, p_context->width, p_context->height ) ) { msg_Err( p_dec, "acceleration setup failure" ); break; } if( p_va->description ) msg_Info( p_dec, "Using %s for hardware decoding.", p_va->description ); /* FIXME this will disable direct rendering * even if a new pixel format is renegotiated */ p_sys->b_direct_rendering = false; p_sys->p_va = p_va; p_context->draw_horiz_band = NULL; return pi_fmt[i]; } vlc_va_Delete( p_va ); end: /* Fallback to default behaviour */ p_sys->p_va = NULL; return avcodec_default_get_format( p_context, pi_fmt ); }
static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts, int input_rate) { aout_owner_t *owner = aout_owner (aout); mtime_t drift; /** * Depending on the drift between the actual and intended playback times, * the audio core may ignore the drift, trigger upsampling or downsampling, * insert silence or even discard samples. * Future VLC versions may instead adjust the input rate. * * The audio output plugin is responsible for estimating its actual * playback time, or rather the estimated time when the next sample will * be played. (The actual playback time is always the current time, that is * to say mdate(). It is not an useful statistic.) * * Most audio output plugins can estimate the delay until playback of * the next sample to be written to the buffer, or equally the time until * all samples in the buffer will have been played. Then: * pts = mdate() + delay */ if (aout_OutputTimeGet (aout, &drift) != 0) return; /* nothing can be done if timing is unknown */ drift += mdate () - dec_pts; /* Late audio output. * This can happen due to insufficient caching, scheduling jitter * or bug in the decoder. Ideally, the output would seek backward. But that * is not portable, not supported by some hardware and often unsafe/buggy * where supported. The other alternative is to flush the buffers * completely. */ if (drift > (owner->sync.discontinuity ? 0 : +3 * input_rate * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT)) { if (!owner->sync.discontinuity) msg_Warn (aout, "playback way too late (%"PRId64"): " "flushing buffers", drift); else msg_Dbg (aout, "playback too late (%"PRId64"): " "flushing buffers", drift); aout_OutputFlush (aout, false); aout_StopResampling (aout); owner->sync.end = VLC_TS_INVALID; owner->sync.discontinuity = true; /* Now the output might be too early... Recheck. */ if (aout_OutputTimeGet (aout, &drift) != 0) return; /* nothing can be done if timing is unknown */ drift += mdate () - dec_pts; } /* Early audio output. * This is rare except at startup when the buffers are still empty. */ if (drift < (owner->sync.discontinuity ? 0 : -3 * input_rate * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT)) { if (!owner->sync.discontinuity) msg_Warn (aout, "playback way too early (%"PRId64"): " "playing silence", drift); aout_DecSilence (aout, -drift, dec_pts); aout_StopResampling (aout); owner->sync.discontinuity = true; drift = 0; } /* Resampling */ if (drift > +AOUT_MAX_PTS_DELAY && owner->sync.resamp_type != AOUT_RESAMPLING_UP) { msg_Warn (aout, "playback too late (%"PRId64"): up-sampling", drift); owner->sync.resamp_type = AOUT_RESAMPLING_UP; owner->sync.resamp_start_drift = +drift; } if (drift < -AOUT_MAX_PTS_ADVANCE && owner->sync.resamp_type != AOUT_RESAMPLING_DOWN) { msg_Warn (aout, "playback too early (%"PRId64"): down-sampling", drift); owner->sync.resamp_type = AOUT_RESAMPLING_DOWN; owner->sync.resamp_start_drift = -drift; } if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE) return; /* Everything is fine. Nothing to do. */ if (llabs (drift) > 2 * owner->sync.resamp_start_drift) { /* If the drift is ever increasing, then something is seriously wrong. * Cease resampling and hope for the best. */ msg_Warn (aout, "timing screwed (drift: %"PRId64" us): " "stopping resampling", drift); aout_StopResampling (aout); return; } /* Resampling has been triggered earlier. This checks if it needs to be * increased or decreased. Resampling rate changes must be kept slow for * the comfort of listeners. */ int adj = (owner->sync.resamp_type == AOUT_RESAMPLING_UP) ? +2 : -2; if (2 * llabs (drift) <= owner->sync.resamp_start_drift) /* If the drift has been reduced from more than half its initial * value, then it is time to switch back the resampling direction. */ adj *= -1; if (!aout_FiltersAdjustResampling (owner->filters, adj)) { /* Everything is back to normal: stop resampling. */ owner->sync.resamp_type = AOUT_RESAMPLING_NONE; msg_Dbg (aout, "resampling stopped (drift: %"PRId64" us)", drift); } }
/* see http://www.iana.org/assignments/rtp-parameters */ void rtp_autodetect (demux_t *demux, rtp_session_t *session, const block_t *block) { uint8_t ptype = rtp_ptype (block); rtp_pt_t pt = { .init = NULL, .destroy = codec_destroy, .decode = codec_decode, .frequency = 0, .number = ptype, }; /* Remember to keep this in sync with modules/services_discovery/sap.c */ switch (ptype) { case 0: msg_Dbg (demux, "detected G.711 mu-law"); pt.init = pcmu_init; pt.frequency = 8000; break; case 3: msg_Dbg (demux, "detected GSM"); pt.init = gsm_init; pt.frequency = 8000; break; case 8: msg_Dbg (demux, "detected G.711 A-law"); pt.init = pcma_init; pt.frequency = 8000; break; case 10: msg_Dbg (demux, "detected stereo PCM"); pt.init = l16s_init; pt.frequency = 44100; break; case 11: msg_Dbg (demux, "detected mono PCM"); pt.init = l16m_init; pt.frequency = 44100; break; case 12: msg_Dbg (demux, "detected QCELP"); pt.init = qcelp_init; pt.frequency = 8000; break; case 14: msg_Dbg (demux, "detected MPEG Audio"); pt.init = mpa_init; pt.decode = mpa_decode; pt.frequency = 90000; break; case 32: msg_Dbg (demux, "detected MPEG Video"); pt.init = mpv_init; pt.decode = mpv_decode; pt.frequency = 90000; break; case 33: msg_Dbg (demux, "detected MPEG2 TS"); pt.init = ts_init; pt.destroy = stream_destroy; pt.decode = stream_decode; pt.frequency = 90000; break; default: /* * If the rtp payload type is unknown then check demux if it is specified */ if (!strcmp(demux->psz_demux, "h264") || !strcmp(demux->psz_demux, "ts")) { msg_Dbg (demux, "dynamic payload format %s specified by demux", demux->psz_demux); pt.init = demux_init; pt.destroy = stream_destroy; pt.decode = stream_decode; pt.frequency = 90000; break; } if (ptype >= 96) { char *dynamic = var_InheritString(demux, "rtp-dynamic-pt"); if (dynamic == NULL) ; else if (!strcmp(dynamic, "theora")) { msg_Dbg (demux, "assuming Theora Encoded Video"); pt.init = theora_init; pt.destroy = xiph_destroy; pt.decode = xiph_decode; pt.frequency = 90000; } else msg_Err (demux, "unknown dynamic payload format `%s' " "specified", dynamic); free (dynamic); } msg_Err (demux, "unspecified payload format (type %"PRIu8")", ptype); msg_Info (demux, "A valid SDP is needed to parse this RTP stream."); dialog_Fatal (demux, N_("SDP required"), N_("A description in SDP format is required to receive the RTP " "stream. Note that rtp:// URIs cannot work with dynamic " "RTP payload format (%"PRIu8")."), ptype); return; } rtp_add_type (demux, session, &pt); }
/** * Marks the audio output for restart, to update any parameter of the output * plug-in (e.g. output device or channel mapping). */ void aout_RequestRestart (audio_output_t *aout, unsigned mode) { aout_owner_t *owner = aout_owner (aout); atomic_fetch_or (&owner->restart, mode); msg_Dbg (aout, "restart requested (%u)", mode); }
/***************************************************************************** * Open: initializes raw audio demuxer *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; char *psz_fourcc = var_CreateGetString( p_demux, "rawaud-fourcc" ); es_format_Init( &p_sys->fmt, AUDIO_ES, vlc_fourcc_GetCodecFromString( AUDIO_ES, psz_fourcc ) ); free( psz_fourcc ); if( !p_sys->fmt.i_codec ) { msg_Err( p_demux, "rawaud-fourcc must be a 4 character string"); es_format_Clean( &p_sys->fmt ); free( p_sys ); return VLC_EGENERIC; } // get the bits per sample ratio based on codec switch( p_sys->fmt.i_codec ) { case VLC_CODEC_FL64: p_sys->fmt.audio.i_bitspersample = 64; break; case VLC_CODEC_FL32: case VLC_CODEC_S32L: case VLC_CODEC_S32B: p_sys->fmt.audio.i_bitspersample = 32; break; case VLC_CODEC_S24L: case VLC_CODEC_S24B: p_sys->fmt.audio.i_bitspersample = 24; break; case VLC_CODEC_S16L: case VLC_CODEC_S16B: p_sys->fmt.audio.i_bitspersample = 16; break; case VLC_CODEC_S8: case VLC_CODEC_U8: p_sys->fmt.audio.i_bitspersample = 8; break; default: msg_Err( p_demux, "unknown fourcc format %4.4s", (char *)&p_sys->fmt.i_codec); es_format_Clean( &p_sys->fmt ); free( p_sys ); return VLC_EGENERIC; } p_sys->fmt.psz_language = var_CreateGetString( p_demux, "rawaud-lang" ); p_sys->fmt.audio.i_channels = var_CreateGetInteger( p_demux, "rawaud-channels" ); p_sys->fmt.audio.i_rate = var_CreateGetInteger( p_demux, "rawaud-samplerate" ); if( p_sys->fmt.audio.i_rate == 0 || p_sys->fmt.audio.i_rate > 384000 ) { msg_Err( p_demux, "invalid sample rate"); es_format_Clean( &p_sys->fmt ); free( p_sys ); return VLC_EGENERIC; } if( p_sys->fmt.audio.i_channels == 0 || p_sys->fmt.audio.i_channels > 32 ) { msg_Err( p_demux, "invalid number of channels"); es_format_Clean( &p_sys->fmt ); free( p_sys ); return VLC_EGENERIC; } p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate * p_sys->fmt.audio.i_channels * p_sys->fmt.audio.i_bitspersample; if( p_sys->fmt.i_bitrate > 50000000) { msg_Err( p_demux, "invalid bitrate"); es_format_Clean( &p_sys->fmt ); free( p_sys ); return VLC_EGENERIC; } msg_Dbg( p_demux, "format initialized: channels=%d , samplerate=%d Hz, fourcc=%4.4s, bits per sample = %d, bitrate = %d bit/s", p_sys->fmt.audio.i_channels, p_sys->fmt.audio.i_rate, (char*)&p_sys->fmt.i_codec, p_sys->fmt.audio.i_bitspersample, p_sys->fmt.i_bitrate); /* add the es */ p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt ); msg_Dbg( p_demux, "elementary stream added"); /* initialize timing */ date_Init( &p_sys->pts, p_sys->fmt.audio.i_rate, 1 ); date_Set( &p_sys->pts, VLC_TICK_0 ); /* calculate 50ms frame size/time */ p_sys->i_frame_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 ); p_sys->i_seek_step = p_sys->fmt.audio.i_channels * ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 ); p_sys->i_frame_size = p_sys->i_frame_samples * p_sys->i_seek_step; msg_Dbg( p_demux, "frame size is %d bytes ", p_sys->i_frame_size); p_demux->pf_demux = Demux; p_demux->pf_control = Control; return VLC_SUCCESS; }
CtrlGeneric *TopWindow::findHitControl( int xPos, int yPos ) { if( m_pActiveLayout == NULL ) { return NULL; } // Get the controls in the active layout const list<LayeredControl> &ctrlList = m_pActiveLayout->getControlList(); list<LayeredControl>::const_reverse_iterator iter; // New control hit by the mouse CtrlGeneric *pNewHitControl = NULL; // Loop on the control list to find the uppest hit control for( iter = ctrlList.rbegin(); iter != ctrlList.rend(); iter++ ) { // Get the position of the control in the layout const Position *pos = (*iter).m_pControl->getPosition(); if( pos != NULL ) { // Compute the coordinates of the mouse relative to the control int xRel = xPos - pos->getLeft(); int yRel = yPos - pos->getTop(); CtrlGeneric *pCtrl = (*iter).m_pControl; // Control hit ? if( pCtrl->isVisible() && pCtrl->mouseOver( xRel, yRel ) ) { pNewHitControl = (*iter).m_pControl; break; } } else { msg_Dbg( getIntf(), "control at NULL position" ); } } // If the hit control has just been entered, send it an enter event if( pNewHitControl && (pNewHitControl != m_pLastHitControl) ) { // Don't send the event if another control captured the mouse if( !m_pCapturingControl || (m_pCapturingControl == pNewHitControl ) ) { EvtEnter evt( getIntf() ); pNewHitControl->handleEvent( evt ); if( !m_pCapturingControl ) { // Show the tooltip m_rWindowManager.hideTooltip(); UString tipText = pNewHitControl->getTooltipText(); if( tipText.length() > 0 ) { // Set the tooltip text variable VarManager *pVarManager = VarManager::instance( getIntf() ); pVarManager->getTooltipText().set( tipText ); m_rWindowManager.showTooltip(); } } } } return pNewHitControl; }
static int SendIn( sout_stream_t *p_stream, sout_stream_id_sys_t *id, block_t *p_buffer ) { in_sout_stream_sys_t *p_sys = (in_sout_stream_sys_t *)p_stream->p_sys; bridge_t *p_bridge; bool b_no_es = true; int i; int i_date = mdate(); /* First forward the packet for our own ES */ if( !p_sys->b_placeholder ) p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer ); /* Then check all bridged streams */ vlc_mutex_lock( &lock ); p_bridge = var_GetAddress( p_stream->p_libvlc, p_sys->psz_name ); if( p_bridge ) { for ( i = 0; i < p_bridge->i_es_num; i++ ) { if ( !p_bridge->pp_es[i]->b_empty ) b_no_es = false; while ( p_bridge->pp_es[i]->p_block != NULL && (p_bridge->pp_es[i]->p_block->i_dts + p_sys->i_delay < i_date || p_bridge->pp_es[i]->p_block->i_dts + p_sys->i_delay < p_bridge->pp_es[i]->i_last) ) { block_t *p_block = p_bridge->pp_es[i]->p_block; msg_Dbg( p_stream, "dropping a packet (%"PRId64 ")", i_date - p_block->i_dts - p_sys->i_delay ); p_bridge->pp_es[i]->p_block = p_bridge->pp_es[i]->p_block->p_next; block_Release( p_block ); } if ( p_bridge->pp_es[i]->p_block == NULL ) { p_bridge->pp_es[i]->pp_last = &p_bridge->pp_es[i]->p_block; } if ( p_bridge->pp_es[i]->b_changed ) { if ( p_bridge->pp_es[i]->b_empty && p_bridge->pp_es[i]->id != NULL ) { p_stream->p_next->pf_del( p_stream->p_next, p_bridge->pp_es[i]->id ); } else { /* We need at least two packets to enter the mux. */ if ( p_bridge->pp_es[i]->p_block == NULL || p_bridge->pp_es[i]->p_block->p_next == NULL ) { continue; } p_bridge->pp_es[i]->fmt.i_id += p_sys->i_id_offset; if( !p_sys->b_placeholder ) { p_bridge->pp_es[i]->id = p_stream->p_next->pf_add( p_stream->p_next, &p_bridge->pp_es[i]->fmt ); if ( p_bridge->pp_es[i]->id == NULL ) { msg_Warn( p_stream, "couldn't create chain for id %d", p_bridge->pp_es[i]->fmt.i_id ); } } msg_Dbg( p_stream, "bridging in input codec=%4.4s id=%d pos=%d", (char*)&p_bridge->pp_es[i]->fmt.i_codec, p_bridge->pp_es[i]->fmt.i_id, i ); } } p_bridge->pp_es[i]->b_changed = false; if ( p_bridge->pp_es[i]->b_empty ) continue; if ( p_bridge->pp_es[i]->p_block == NULL ) { if ( p_bridge->pp_es[i]->id != NULL && p_bridge->pp_es[i]->i_last < i_date ) { if( !p_sys->b_placeholder ) p_stream->p_next->pf_del( p_stream->p_next, p_bridge->pp_es[i]->id ); p_bridge->pp_es[i]->fmt.i_id -= p_sys->i_id_offset; p_bridge->pp_es[i]->b_changed = true; p_bridge->pp_es[i]->id = NULL; } continue; } if ( p_bridge->pp_es[i]->id != NULL || p_sys->b_placeholder) { block_t *p_block = p_bridge->pp_es[i]->p_block; while ( p_block != NULL ) { p_bridge->pp_es[i]->i_last = p_block->i_dts; p_block->i_pts += p_sys->i_delay; p_block->i_dts += p_sys->i_delay; p_block = p_block->p_next; } sout_stream_id_sys_t *newid = NULL; if( p_sys->b_placeholder ) { switch( p_bridge->pp_es[i]->fmt.i_cat ) { case VIDEO_ES: p_sys->i_last_video = i_date; newid = p_sys->id_video; if( !newid ) break; if( !p_sys->b_switch_on_iframe || p_sys->i_state == placeholder_off || ( p_bridge->pp_es[i]->fmt.i_cat == VIDEO_ES && p_bridge->pp_es[i]->p_block->i_flags & BLOCK_FLAG_TYPE_I ) ) { p_stream->p_next->pf_send( p_stream->p_next, newid, p_bridge->pp_es[i]->p_block ); p_sys->i_state = placeholder_off; } break; case AUDIO_ES: newid = p_sys->id_audio; if( !newid ) break; p_sys->i_last_audio = i_date; default: p_stream->p_next->pf_send( p_stream->p_next, newid?newid:p_bridge->pp_es[i]->id, p_bridge->pp_es[i]->p_block ); break; } } else /* !b_placeholder */ p_stream->p_next->pf_send( p_stream->p_next, p_bridge->pp_es[i]->id, p_bridge->pp_es[i]->p_block ); } else { block_ChainRelease( p_bridge->pp_es[i]->p_block ); } p_bridge->pp_es[i]->p_block = NULL; p_bridge->pp_es[i]->pp_last = &p_bridge->pp_es[i]->p_block; } if( b_no_es ) { for ( i = 0; i < p_bridge->i_es_num; i++ ) free( p_bridge->pp_es[i] ); free( p_bridge->pp_es ); free( p_bridge ); var_Destroy( p_stream->p_libvlc, p_sys->psz_name ); } } if( p_sys->b_placeholder ) { switch( id->i_cat ) { case VIDEO_ES: if( ( p_sys->i_last_video + p_sys->i_placeholder_delay < i_date && ( !p_sys->b_switch_on_iframe || p_buffer->i_flags & BLOCK_FLAG_TYPE_I ) ) || p_sys->i_state == placeholder_on ) { p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer ); p_sys->i_state = placeholder_on; } else block_Release( p_buffer ); break; case AUDIO_ES: if( p_sys->i_last_audio + p_sys->i_placeholder_delay < i_date ) p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer ); else block_Release( p_buffer ); break; default: block_Release( p_buffer ); /* FIXME: placeholder subs anyone? */ break; } } vlc_mutex_unlock( &lock ); return VLC_SUCCESS; }
/***************************************************************************** * 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 InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, const char *psz_namecodec ) { decoder_sys_t *p_sys; int i_val; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(decoder_sys_t) ) ) == NULL ) return VLC_ENOMEM; p_codec->type = AVMEDIA_TYPE_VIDEO; p_context->codec_type = AVMEDIA_TYPE_VIDEO; p_context->codec_id = i_codec_id; p_sys->p_context = p_context; p_sys->p_codec = p_codec; p_sys->i_codec_id = i_codec_id; p_sys->psz_namecodec = psz_namecodec; p_sys->p_ff_pic = avcodec_alloc_frame(); p_sys->b_delayed_open = true; p_sys->p_va = NULL; vlc_sem_init( &p_sys->sem_mt, 0 ); /* ***** Fill p_context with init values ***** */ p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_original_fourcc ?: p_dec->fmt_in.i_codec ); /* ***** Get configuration of ffmpeg plugin ***** */ p_sys->p_context->workaround_bugs = var_InheritInteger( p_dec, "avcodec-workaround-bugs" ); p_sys->p_context->err_recognition = var_InheritInteger( p_dec, "avcodec-error-resilience" ); if( var_CreateGetBool( p_dec, "grayscale" ) ) p_sys->p_context->flags |= CODEC_FLAG_GRAY; /* ***** Output always the frames ***** */ #if LIBAVCODEC_VERSION_CHECK(55, 23, 1, 40, 101) p_sys->p_context->flags |= CODEC_FLAG_OUTPUT_CORRUPT; #endif i_val = var_CreateGetInteger( p_dec, "avcodec-vismv" ); if( i_val ) p_sys->p_context->debug_mv = i_val; i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" ); if( i_val >= 4 ) p_sys->p_context->skip_loop_filter = AVDISCARD_ALL; else if( i_val == 3 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONKEY; else if( i_val == 2 ) p_sys->p_context->skip_loop_filter = AVDISCARD_BIDIR; else if( i_val == 1 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONREF; if( var_CreateGetBool( p_dec, "avcodec-fast" ) ) p_sys->p_context->flags2 |= CODEC_FLAG2_FAST; /* ***** libavcodec frame skipping ***** */ p_sys->b_hurry_up = var_CreateGetBool( p_dec, "avcodec-hurry-up" ); i_val = var_CreateGetInteger( p_dec, "avcodec-skip-frame" ); if( i_val >= 4 ) p_sys->p_context->skip_frame = AVDISCARD_ALL; else if( i_val == 3 ) p_sys->p_context->skip_frame = AVDISCARD_NONKEY; else if( i_val == 2 ) p_sys->p_context->skip_frame = AVDISCARD_BIDIR; else if( i_val == 1 ) p_sys->p_context->skip_frame = AVDISCARD_NONREF; else if( i_val == -1 ) p_sys->p_context->skip_frame = AVDISCARD_NONE; else p_sys->p_context->skip_frame = AVDISCARD_DEFAULT; p_sys->i_skip_frame = p_sys->p_context->skip_frame; i_val = var_CreateGetInteger( p_dec, "avcodec-skip-idct" ); if( i_val >= 4 ) p_sys->p_context->skip_idct = AVDISCARD_ALL; else if( i_val == 3 ) p_sys->p_context->skip_idct = AVDISCARD_NONKEY; else if( i_val == 2 ) p_sys->p_context->skip_idct = AVDISCARD_BIDIR; else if( i_val == 1 ) p_sys->p_context->skip_idct = AVDISCARD_NONREF; else if( i_val == -1 ) p_sys->p_context->skip_idct = AVDISCARD_NONE; else p_sys->p_context->skip_idct = AVDISCARD_DEFAULT; p_sys->i_skip_idct = p_sys->p_context->skip_idct; /* ***** libavcodec direct rendering ***** */ p_sys->b_direct_rendering = false; p_sys->i_direct_rendering_used = -1; if( var_CreateGetBool( p_dec, "avcodec-dr" ) && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) && /* No idea why ... but this fixes flickering on some TSCC streams */ p_sys->i_codec_id != AV_CODEC_ID_TSCC && p_sys->i_codec_id != AV_CODEC_ID_CSCD && p_sys->i_codec_id != AV_CODEC_ID_CINEPAK && !p_sys->p_context->debug_mv ) { /* 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 = true; } /* libavcodec doesn't properly release old pictures when frames are skipped */ //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = false; if( p_sys->b_direct_rendering ) { msg_Dbg( p_dec, "trying to use direct rendering" ); p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE; } else { msg_Dbg( p_dec, "direct rendering is disabled" ); } p_sys->p_context->get_format = ffmpeg_GetFormat; /* Always use our get_buffer wrapper so we can calculate the * PTS correctly */ #if LIBAVCODEC_VERSION_MAJOR >= 55 p_sys->p_context->get_buffer2 = lavc_GetFrame; #else p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf; p_sys->p_context->reget_buffer = avcodec_default_reget_buffer; p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf; #endif p_sys->p_context->opaque = p_dec; #ifdef HAVE_AVCODEC_MT int i_thread_count = var_InheritInteger( p_dec, "avcodec-threads" ); if( i_thread_count <= 0 ) { i_thread_count = vlc_GetCPUCount(); if( i_thread_count > 1 ) i_thread_count++; //FIXME: take in count the decoding time i_thread_count = __MIN( i_thread_count, 4 ); } i_thread_count = __MIN( i_thread_count, 16 ); msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count ); p_sys->p_context->thread_count = i_thread_count; p_sys->p_context->thread_safe_callbacks = true; switch( i_codec_id ) { case AV_CODEC_ID_MPEG4: case AV_CODEC_ID_H263: p_sys->p_context->thread_type = 0; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: p_sys->p_context->thread_type &= ~FF_THREAD_SLICE; /* fall through */ # if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0)) case AV_CODEC_ID_H264: case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: p_sys->p_context->thread_type &= ~FF_THREAD_FRAME; # endif } if( p_sys->p_context->thread_type & FF_THREAD_FRAME ) p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count; #endif /* ***** misc init ***** */ p_sys->i_pts = VLC_TS_INVALID; p_sys->b_has_b_frames = false; p_sys->b_first_frame = true; p_sys->b_flush = false; p_sys->i_late_frames = 0; /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS ) { /* we are doomed. but not really, because most codecs set their pix_fmt later on */ p_dec->fmt_out.i_codec = VLC_CODEC_I420; } p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma; p_dec->fmt_out.video.orientation = p_dec->fmt_in.video.orientation; #if LIBAVCODEC_VERSION_MAJOR < 54 /* Setup palette */ memset( &p_sys->palette, 0, sizeof(p_sys->palette) ); if( p_dec->fmt_in.video.p_palette ) { p_sys->palette.palette_changed = 1; for( int i = 0; i < __MIN( AVPALETTE_COUNT, p_dec->fmt_in.video.p_palette->i_entries ); i++ ) { union { uint32_t u; uint8_t a[4]; } c; c.a[0] = p_dec->fmt_in.video.p_palette->palette[i][0]; c.a[1] = p_dec->fmt_in.video.p_palette->palette[i][1]; c.a[2] = p_dec->fmt_in.video.p_palette->palette[i][2]; c.a[3] = p_dec->fmt_in.video.p_palette->palette[i][3]; p_sys->palette.palette[i] = c.u; } p_sys->p_context->palctrl = &p_sys->palette; p_dec->fmt_out.video.p_palette = malloc( sizeof(video_palette_t) ); if( p_dec->fmt_out.video.p_palette ) *p_dec->fmt_out.video.p_palette = *p_dec->fmt_in.video.p_palette; } else if( p_sys->i_codec_id != CODEC_ID_MSVIDEO1 && p_sys->i_codec_id != CODEC_ID_CINEPAK ) { p_sys->p_context->palctrl = &p_sys->palette; } #else if( p_dec->fmt_in.video.p_palette ) { p_sys->palette_sent = false; p_dec->fmt_out.video.p_palette = malloc( sizeof(video_palette_t) ); if( p_dec->fmt_out.video.p_palette ) *p_dec->fmt_out.video.p_palette = *p_dec->fmt_in.video.p_palette; } else p_sys->palette_sent = true; #endif /* ***** init this codec with special data ***** */ ffmpeg_InitCodec( p_dec ); /* ***** Open the codec ***** */ if( ffmpeg_OpenCodec( p_dec ) < 0 ) { msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); av_free( p_sys->p_ff_pic ); vlc_sem_destroy( &p_sys->sem_mt ); free( p_sys ); return VLC_EGENERIC; } 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; custom_attrs_t *cp = NULL; int64_t start_time = 0, duration = 0; int64_t computed_start_time = 0, computed_duration = 0; unsigned next_track_id = 1; int loop_count = 0; bool b_weird = false; int ret = VLC_SUCCESS; #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 ); else if( !strcmp( name, "TimeScale" ) ) p_sys->timescale = strtoul( value, NULL, 10 ); else if ( !strcmp( name, "LookAheadFragmentCount" ) ) p_sys->download.lookahead_count = strtoul( value, NULL, 10 ); } if( !p_sys->timescale ) p_sys->timescale = TIMESCALE; } else if( !strcmp( node, "StreamIndex" ) ) { sms_Free( sms ); sms = sms_New(); if( unlikely( !sms ) ) { ret = VLC_ENOMEM; goto cleanup; } 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; } else if( !strcmp( name, "Name" ) ) sms->name = strdup( value ); else if( !strcmp( name, "TimeScale" ) ) sms->timescale = strtoull( value, NULL, 10 ); else if( !strcmp( name, "FourCC" ) ) sms->default_FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); else if( !strcmp( name, "Chunks" ) ) { sms->vod_chunks_nb = strtoul( value, NULL, 10 ); if( sms->vod_chunks_nb == 0 ) /* live */ sms->vod_chunks_nb = UINT32_MAX; } else if( !strcmp( name, "QualityLevels" ) ) sms->qlevel_nb = strtoul( value, NULL, 10 ); else if( !strcmp( name, "Url" ) ) sms->url_template = strdup(value); } if( !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" ); } } else if ( !strcmp( node, "CustomAttributes" ) ) { if (!sms || !ql || cp) break; cp = (custom_attrs_t *) calloc( 1, sizeof(*cp) ); if( unlikely( !cp ) ) { ret = VLC_ENOMEM; goto cleanup; } } else if ( !strcmp( node, "Attribute" ) ) { if (!sms || !ql || !cp) break; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Name" ) && !cp->psz_key ) cp->psz_key = strdup( value ); else if( !strcmp( name, "Value" ) && !cp->psz_value ) cp->psz_value = strdup( value ); } } else if( !strcmp( node, "QualityLevel" ) ) { if ( !sms ) break; ql = ql_New(); if( !ql ) { ret = VLC_ENOMEM; goto cleanup; } while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Index" ) ) ql->Index = strtol( value, NULL, 10 ); else if( !strcmp( name, "Bitrate" ) ) ql->Bitrate = strtoul( value, NULL, 10 ); else if( !strcmp( name, "PacketSize" ) ) ql->nBlockAlign = strtoul( value, NULL, 10 ); else if( !strcmp( name, "FourCC" ) ) ql->FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); else if( !strcmp( name, "CodecPrivateData" ) ) ql->CodecPrivateData = strdup( value ); else 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 ); } else if( !strcmp( name, "MaxWidth" ) || !strcmp( name, "Width" ) ) ql->MaxWidth = strtoul( value, NULL, 10 ); else if( !strcmp( name, "MaxHeight" ) || !strcmp( name, "Height" ) ) ql->MaxHeight = strtoul( value, NULL, 10 ); else if( !strcmp( name, "Channels" ) ) ql->Channels = strtoul( value, NULL, 10 ); else if( !strcmp( name, "SamplingRate" ) ) ql->SamplingRate = strtoul( value, NULL, 10 ); else if( !strcmp( name, "BitsPerSample" ) ) ql->BitsPerSample = strtoul( value, NULL, 10 ); } ARRAY_APPEND( sms->qlevels, ql ); } else if ( !strcmp( node, "Content" ) && sms && !sms->url_template ) { /* empty(@Url) && ./Content == manifest embedded content */ sms_Free( sms ); sms = NULL; } else if( !strcmp( node, "c" ) ) { if ( !sms ) break; loop_count++; start_time = duration = -1; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "t" ) ) start_time = strtoll( value, NULL, 10 ); if( !strcmp( name, "d" ) ) duration = strtoll( 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_AppendNew( sms, computed_duration, computed_start_time ) == NULL ) ) { ret = VLC_ENOMEM; goto cleanup; } if( b_weird && start_time != -1 ) computed_start_time = start_time; } break; case XML_READER_ENDELEM: if ( !strcmp( node, "CustomAttributes" ) ) { if ( cp ) { ARRAY_APPEND(ql->custom_attrs, cp); cp = NULL; } } else if ( !strcmp( node, "Attribute" ) ) { if( !cp->psz_key || !cp->psz_value ) { cleanup_attributes( &cp ); } } else if( strcmp( node, "StreamIndex" ) ) break; else if ( sms ) { ARRAY_APPEND( p_sys->sms, sms ); computed_start_time = 0; computed_duration = 0; loop_count = 0; if( b_weird && !chunk_AppendNew( sms, computed_duration, computed_start_time ) ) { ret = VLC_ENOMEM; goto cleanup; } b_weird = false; if( sms->qlevel_nb == 0 ) sms->qlevel_nb = sms->qlevels.i_size; sms = NULL; } break; case XML_READER_TEXT: break; default: ret = VLC_EGENERIC; goto cleanup; } } #undef TIMESCALE cleanup: cleanup_attributes( &cp ); sms_Free( sms ); xml_ReaderDelete( vlc_reader ); xml_Delete( vlc_xml ); return ret; }
static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags) { decoder_t *dec = (decoder_t *)ctx->opaque; decoder_sys_t *sys = dec->p_sys; if (GetVlcChroma(&dec->fmt_out.video, ctx->pix_fmt) != VLC_SUCCESS) return NULL; dec->fmt_out.i_codec = dec->fmt_out.video.i_chroma; if (ctx->pix_fmt == PIX_FMT_PAL8) return NULL; int width = frame->width; int height = frame->height; int aligns[AV_NUM_DATA_POINTERS]; avcodec_align_dimensions2(ctx, &width, &height, aligns); picture_t *pic = ffmpeg_NewPictBuf(dec, ctx); if (pic == NULL) return NULL; /* Check that the picture is suitable for libavcodec */ if (pic->p[0].i_pitch < width * pic->p[0].i_pixel_pitch) { if (sys->i_direct_rendering_used != 0) msg_Dbg(dec, "plane 0: pitch too small (%d/%d*%d)", pic->p[0].i_pitch, width, pic->p[0].i_pixel_pitch); goto no_dr; } if (pic->p[0].i_lines < height) { if (sys->i_direct_rendering_used != 0) msg_Dbg(dec, "plane 0: lines too few (%d/%d)", pic->p[0].i_lines, height); goto no_dr; } for (int i = 0; i < pic->i_planes; i++) { if (pic->p[i].i_pitch % aligns[i]) { if (sys->i_direct_rendering_used != 0) msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)", i, pic->p[i].i_pitch, aligns[i]); goto no_dr; } if (((uintptr_t)pic->p[i].p_pixels) % aligns[i]) { if (sys->i_direct_rendering_used != 0) msg_Warn(dec, "plane %d not aligned", i); goto no_dr; } } /* Allocate buffer references */ for (int i = 0; i < pic->i_planes; i++) { lavc_pic_ref_t *ref = malloc(sizeof (*ref)); if (ref == NULL) goto error; ref->decoder = dec; ref->picture = pic; decoder_LinkPicture(dec, pic); uint8_t *data = pic->p[i].p_pixels; int size = pic->p[i].i_pitch * pic->p[i].i_lines; frame->buf[i] = av_buffer_create(data, size, lavc_dr_ReleaseFrame, ref, 0); if (unlikely(frame->buf[i] == NULL)) { lavc_dr_ReleaseFrame(ref, data); goto error; } } decoder_UnlinkPicture(dec, pic); (void) flags; return pic; error: for (unsigned i = 0; frame->buf[i] != NULL; i++) av_buffer_unref(&frame->buf[i]); no_dr: decoder_DeletePicture(dec, pic); return NULL; }
static unsigned int sms_Read( stream_t *s, uint8_t *p_read, unsigned int i_read ) { stream_sys_t *p_sys = s->p_sys; unsigned int copied = 0; chunk_t *chunk = NULL; do { bool b_isinitchunk = false; chunk = get_chunk( s, true, &b_isinitchunk ); /* chunk here won't be processed further */ // msg_Dbg( s, "chunk %"PRIu64" init %d", (uint64_t) chunk, b_isinitchunk ); if( !chunk ) return copied; if( chunk->read_pos >= chunk->size ) { if( chunk->type == VIDEO_ES || ( !SMS_GET_SELECTED_ST( VIDEO_ES ) && chunk->type == AUDIO_ES ) ) { p_sys->playback.toffset += chunk->duration; vlc_cond_signal( &p_sys->download.wait ); } if ( b_isinitchunk ) { assert( chunk->read_pos == chunk->size ); vlc_mutex_lock( &p_sys->playback.lock ); p_sys->playback.init.p_startchunk = NULL; p_sys->playback.init.p_datachunk = NULL; chunk_Free( chunk ); vlc_mutex_unlock( &p_sys->playback.lock ); } else { vlc_mutex_lock( &p_sys->lock ); if( gotoNextChunk( p_sys ) == NULL ) { vlc_mutex_unlock( &p_sys->lock ); return 0; } vlc_mutex_unlock( &p_sys->lock ); } continue; } if( chunk->read_pos == 0 ) { const char *verb = p_read == NULL ? "skipping" : "reading"; msg_Dbg( s, "%s chunk time %"PRIu64" (%u bytes), type %i", verb, chunk->start_time, i_read, chunk->type ); } uint64_t len = 0; uint8_t *src = chunk->data + chunk->read_pos; if( i_read <= chunk->size - chunk->read_pos ) len = i_read; else len = chunk->size - chunk->read_pos; if( len > 0 ) { if( p_read ) /* otherwise caller skips data */ memcpy( p_read + copied, src, len ); chunk->read_pos += len; copied += len; i_read -= len; p_sys->playback.boffset += len; } } while ( i_read > 0 ); return copied; }
/***************************************************************************** * Init: initialize Crop video thread output method *****************************************************************************/ static int Init( vout_thread_t *p_vout ) { char *psz_var; video_format_t fmt; I_OUTPUTPICTURES = 0; memset( &fmt, 0, sizeof(video_format_t) ); p_vout->p_sys->i_lastchange = 0; p_vout->p_sys->b_changed = false; /* Initialize the output structure */ p_vout->output.i_chroma = p_vout->render.i_chroma; p_vout->output.i_width = p_vout->render.i_width; p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->fmt_out = p_vout->fmt_in; /* Shall we use autocrop ? */ p_vout->p_sys->b_autocrop = var_InheritBool( p_vout, "autocrop" ); #ifdef BEST_AUTOCROP p_vout->p_sys->i_ratio_max = var_InheritInteger( p_vout, "autocrop-ratio-max" ); p_vout->p_sys->i_threshold = var_InheritInteger( p_vout, "autocrop-luminance-threshold" ); p_vout->p_sys->i_skipPercent = var_InheritInteger( p_vout, "autocrop-skip-percent" ); p_vout->p_sys->i_nonBlackPixel = var_InheritInteger( p_vout, "autocrop-non-black-pixels" ); p_vout->p_sys->i_diff = var_InheritInteger( p_vout, "autocrop-diff" ); p_vout->p_sys->i_time = var_InheritInteger( p_vout, "autocrop-time" ); var_SetString( p_vout, "ratio-crop", "0" ); if (p_vout->p_sys->b_autocrop) p_vout->p_sys->i_ratio = 0; else { p_vout->p_sys->i_ratio = var_InheritInteger( p_vout, "crop-ratio" ); // ratio < width / height => ratio = 0 (unchange ratio) if (p_vout->p_sys->i_ratio < (p_vout->output.i_width * 1000) / p_vout->output.i_height) p_vout->p_sys->i_ratio = 0; } #endif /* Get geometry value from the user */ psz_var = var_InheritString( p_vout, "crop-geometry" ); if( psz_var ) { char *psz_parser, *psz_tmp; psz_parser = psz_tmp = psz_var; while( *psz_tmp && *psz_tmp != 'x' ) psz_tmp++; if( *psz_tmp ) { psz_tmp[0] = '\0'; p_vout->p_sys->i_width = atoi( psz_parser ); psz_parser = ++psz_tmp; while( *psz_tmp && *psz_tmp != '+' ) psz_tmp++; if( *psz_tmp ) { psz_tmp[0] = '\0'; p_vout->p_sys->i_height = atoi( psz_parser ); psz_parser = ++psz_tmp; while( *psz_tmp && *psz_tmp != '+' ) psz_tmp++; if( *psz_tmp ) { psz_tmp[0] = '\0'; p_vout->p_sys->i_x = atoi( psz_parser ); p_vout->p_sys->i_y = atoi( ++psz_tmp ); } else { p_vout->p_sys->i_x = atoi( psz_parser ); p_vout->p_sys->i_y = ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2; } } else { p_vout->p_sys->i_height = atoi( psz_parser ); p_vout->p_sys->i_x = ( p_vout->output.i_width - p_vout->p_sys->i_width ) / 2; p_vout->p_sys->i_y = ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2; } } else { p_vout->p_sys->i_width = atoi( psz_parser ); p_vout->p_sys->i_height = p_vout->output.i_height; p_vout->p_sys->i_x = ( p_vout->output.i_width - p_vout->p_sys->i_width ) / 2; p_vout->p_sys->i_y = ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2; } /* Check for validity */ if( p_vout->p_sys->i_x + p_vout->p_sys->i_width > p_vout->output.i_width ) { p_vout->p_sys->i_x = 0; if( p_vout->p_sys->i_width > p_vout->output.i_width ) { p_vout->p_sys->i_width = p_vout->output.i_width; } } if( p_vout->p_sys->i_y + p_vout->p_sys->i_height > p_vout->output.i_height ) { p_vout->p_sys->i_y = 0; if( p_vout->p_sys->i_height > p_vout->output.i_height ) { p_vout->p_sys->i_height = p_vout->output.i_height; } } free( psz_var ); } else #ifdef BEST_AUTOCROP if (p_vout->p_sys->i_ratio) { p_vout->p_sys->i_aspect = p_vout->p_sys->i_ratio * 432; p_vout->p_sys->i_width = p_vout->fmt_out.i_visible_width; p_vout->p_sys->i_height = p_vout->output.i_aspect * p_vout->output.i_height / p_vout->p_sys->i_aspect * p_vout->p_sys->i_width / p_vout->output.i_width; p_vout->p_sys->i_height += p_vout->p_sys->i_height % 2; p_vout->p_sys->i_x = p_vout->fmt_out.i_x_offset; p_vout->p_sys->i_y = (p_vout->output.i_height - p_vout->p_sys->i_height) / 2; } else #endif { p_vout->p_sys->i_width = p_vout->fmt_out.i_visible_width; p_vout->p_sys->i_height = p_vout->fmt_out.i_visible_height; p_vout->p_sys->i_x = p_vout->fmt_out.i_x_offset; p_vout->p_sys->i_y = p_vout->fmt_out.i_y_offset; } /* Pheeew. Parsing done. */ msg_Dbg( p_vout, "cropping at %ix%i+%i+%i, %sautocropping", p_vout->p_sys->i_width, p_vout->p_sys->i_height, p_vout->p_sys->i_x, p_vout->p_sys->i_y, p_vout->p_sys->b_autocrop ? "" : "not " ); /* Set current output image properties */ p_vout->p_sys->i_aspect = (int64_t)VOUT_ASPECT_FACTOR * p_vout->fmt_out.i_sar_num * p_vout->p_sys->i_width / (p_vout->fmt_out.i_sar_den * p_vout->p_sys->i_height); #ifdef BEST_AUTOCROP msg_Info( p_vout, "ratio %d", p_vout->p_sys->i_aspect / 432); #endif fmt.i_width = fmt.i_visible_width = p_vout->p_sys->i_width; fmt.i_height = fmt.i_visible_height = p_vout->p_sys->i_height; fmt.i_x_offset = fmt.i_y_offset = 0; fmt.i_chroma = p_vout->render.i_chroma; fmt.i_sar_num = p_vout->p_sys->i_aspect * fmt.i_height; fmt.i_sar_den = VOUT_ASPECT_FACTOR * fmt.i_width; /* Try to open the real video output */ p_vout->p_sys->p_vout = vout_Create( p_vout, &fmt ); if( p_vout->p_sys->p_vout == NULL ) { msg_Err( p_vout, "failed to create vout" ); dialog_Fatal( p_vout, _("Cropping failed"), "%s", _("VLC could not open the video output module.") ); return VLC_EGENERIC; } vlc_mutex_init( &p_vout->p_sys->lock ); #ifdef BEST_AUTOCROP var_AddCallback( p_vout, "ratio-crop", FilterCallback, NULL ); #endif vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES ); vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent ); return VLC_SUCCESS; }
int main( int i_argc, char **pp_argv ) { const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html"; char *p_network_name_tmp = NULL; size_t i_network_name_tmp_size; char *psz_dup_config = NULL; mtime_t i_poll_timeout = MAX_POLL_TIMEOUT; struct sched_param param; int i_error; int c; struct sigaction sa; sigset_t set; int b_enable_syslog = 0; if ( i_argc == 1 ) usage(); /* * The only short options left are: 346789 * Use them wisely. */ static const struct option long_options[] = { { "config-file", required_argument, NULL, 'c' }, { "remote-socket", required_argument, NULL, 'r' }, { "ttl", required_argument, NULL, 't' }, { "rtp-output", required_argument, NULL, 'o' }, { "priority", required_argument, NULL, 'i' }, { "adapter", required_argument, NULL, 'a' }, { "frontend-number", required_argument, NULL, 'n' }, { "delsys", required_argument, NULL, '5' }, { "frequency", required_argument, NULL, 'f' }, { "fec-inner", required_argument, NULL, 'F' }, { "rolloff", required_argument, NULL, 'R' }, { "symbol-rate", required_argument, NULL, 's' }, { "diseqc", required_argument, NULL, 'S' }, { "uncommitted", required_argument, NULL, 'k' }, { "voltage", required_argument, NULL, 'v' }, { "force-pulse", no_argument, NULL, 'p' }, { "bandwidth", required_argument, NULL, 'b' }, { "inversion", required_argument, NULL, 'I' }, { "modulation", required_argument, NULL, 'm' }, { "pilot", required_argument, NULL, 'P' }, { "multistream-id", required_argument, NULL, '1' }, { "fec-lp", required_argument, NULL, 'K' }, { "guard", required_argument, NULL, 'G' }, { "hierarchy", required_argument, NULL, 'H' }, { "transmission", required_argument, NULL, 'X' }, { "lock-timeout", required_argument, NULL, 'O' }, { "budget-mode", no_argument, NULL, 'u' }, { "select-pmts", no_argument, NULL, 'w' }, { "udp", no_argument, NULL, 'U' }, { "unique-ts-id", no_argument, NULL, 'T' }, { "latency", required_argument, NULL, 'L' }, { "retention", required_argument, NULL, 'E' }, { "duplicate", required_argument, NULL, 'd' }, { "rtp-input", required_argument, NULL, 'D' }, { "asi-adapter", required_argument, NULL, 'A' }, { "any-type", no_argument, NULL, 'z' }, { "dvb-compliance", no_argument, NULL, 'C' }, { "emm-passthrough", no_argument, NULL, 'W' }, { "ecm-passthrough", no_argument, NULL, 'Y' }, { "epg-passthrough", no_argument, NULL, 'e' }, { "network-name", no_argument, NULL, 'M' }, { "network-id", no_argument, NULL, 'N' }, { "system-charset", required_argument, NULL, 'j' }, { "dvb-charset", required_argument, NULL, 'J' }, { "provider-name", required_argument, NULL, 'B' }, { "logger", no_argument, NULL, 'l' }, { "logger-ident", required_argument, NULL, 'g' }, { "print", required_argument, NULL, 'x' }, { "quit-timeout", required_argument, NULL, 'Q' }, { "quiet", no_argument, NULL, 'q' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "mrtg-file", required_argument, NULL, 'Z' }, { "ca-number", required_argument, NULL, 'y' }, { "pidmap", required_argument, NULL, '0' }, { "dvr-buf-size", required_argument, NULL, '2' }, { 0, 0, 0, 0 } }; while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:5:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:y:0:1:2:", long_options, NULL)) != -1 ) { switch ( c ) { case 'q': if ( optarg ) { if ( *optarg == 'q' ) /* e.g. -qqq */ { i_verbose--; while ( *optarg == 'q' ) { i_verbose--; optarg++; } } else { i_verbose -= atoi( optarg ); /* e.g. -q2 */ } } else { i_verbose--; /* -q */ } break; case 'c': psz_conf_file = optarg; /* * When configuration file is used it is reasonable to assume that * services may be added/removed. If b_select_pmts is not set dvblast * is unable to start streaming newly added services in the config. */ b_select_pmts = 1; break; case 'r': psz_srv_socket = optarg; break; case 't': i_ttl_global = strtol( optarg, NULL, 0 ); break; case 'o': { struct in_addr maddr; if ( !inet_aton( optarg, &maddr ) ) usage(); memcpy( pi_ssrc_global, &maddr.s_addr, 4 * sizeof(uint8_t) ); break; } case 'i': i_priority = strtol( optarg, NULL, 0 ); break; case 'a': i_adapter = strtol( optarg, NULL, 0 ); break; case 'n': i_fenum = strtol( optarg, NULL, 0 ); break; case 'y': i_canum = strtol( optarg, NULL, 0 ); break; case '5': psz_delsys = optarg; break; case 'f': if (optarg && optarg[0] != '-') i_frequency = strtol( optarg, NULL, 0 ); if ( pf_Open != NULL ) usage(); #ifdef HAVE_DVB_SUPPORT pf_Open = dvb_Open; pf_Read = dvb_Read; pf_Reset = dvb_Reset; pf_SetFilter = dvb_SetFilter; pf_UnsetFilter = dvb_UnsetFilter; #else msg_Err( NULL, "DVBlast is compiled without DVB support."); exit(1); #endif break; case 'F': i_fec = strtol( optarg, NULL, 0 ); break; case 'R': i_rolloff = strtol( optarg, NULL, 0 ); break; case 's': i_srate = strtol( optarg, NULL, 0 ); break; case 'S': i_satnum = strtol( optarg, NULL, 16 ); break; case 'k': i_uncommitted = strtol( optarg, NULL, 16 ); break; case 'v': i_voltage = strtol( optarg, NULL, 0 ); break; case 'p': b_tone = 1; break; case 'b': i_bandwidth = strtol( optarg, NULL, 0 ); break; case 'I': i_inversion = strtol( optarg, NULL, 0 ); break; case 'm': psz_modulation = optarg; break; case 'P': i_pilot = strtol( optarg, NULL, 0 ); break; case '1': i_mis = strtol( optarg, NULL, 0 ); break; case 'K': i_fec_lp = strtol( optarg, NULL, 0 ); break; case 'G': i_guard = strtol( optarg, NULL, 0 ); break; case 'X': i_transmission = strtol( optarg, NULL, 0 ); break; case 'O': i_frontend_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000; break; case 'H': i_hierarchy = strtol( optarg, NULL, 0 ); break; case 'u': b_budget_mode = 1; break; case 'w': b_select_pmts = 1; //!b_select_pmts; break; case 'U': b_udp_global = true; break; case 'L': i_latency_global = strtoll( optarg, NULL, 0 ) * 1000; break; case 'E': i_retention_global = strtoll( optarg, NULL, 0 ) * 1000; break; case 'd': psz_dup_config = optarg; break; case 'D': psz_udp_src = optarg; if ( pf_Open != NULL ) usage(); pf_Open = udp_Open; pf_Read = udp_Read; pf_Reset = udp_Reset; pf_SetFilter = udp_SetFilter; pf_UnsetFilter = udp_UnsetFilter; break; case 'A': #ifdef HAVE_ASI_SUPPORT if ( pf_Open != NULL ) usage(); if ( strncmp(optarg, "deltacast:", 10) == 0) { #ifdef HAVE_ASI_DELTACAST_SUPPORT i_asi_adapter = strtol( optarg+10, NULL, 0 ); pf_Open = asi_deltacast_Open; pf_Read = asi_deltacast_Read; pf_Reset = asi_deltacast_Reset; pf_SetFilter = asi_deltacast_SetFilter; pf_UnsetFilter = asi_deltacast_UnsetFilter; #else msg_Err( NULL, "DVBlast is compiled without Deltacast ASI support."); exit(1); #endif } else { i_asi_adapter = strtol( optarg, NULL, 0 ); pf_Open = asi_Open; pf_Read = asi_Read; pf_Reset = asi_Reset; pf_SetFilter = asi_SetFilter; pf_UnsetFilter = asi_UnsetFilter; } #else msg_Err( NULL, "DVBlast is compiled without ASI support."); exit(1); #endif break; case 'z': b_any_type = 1; break; case 'C': b_dvb_global = true; break; case 'W': b_enable_emm = true; break; case 'Y': b_enable_ecm = true; break; case 'e': b_epg_global = true; break; case 'M': psz_network_name = optarg; break; case 'N': i_network_id = strtoul( optarg, NULL, 0 ); break; case 'T': b_random_tsid = 1; break; case 'j': psz_native_charset = optarg; break; case 'J': psz_dvb_charset = optarg; break; case 'B': psz_provider_name = optarg; break; case 'l': b_enable_syslog = 1; break; case 'g': psz_syslog_ident = optarg; break; case 'x': b_print_enabled = true; if ( !strcmp(optarg, "text") ) i_print_type = PRINT_TEXT; else if ( !strcmp(optarg, "xml") ) i_print_type = PRINT_XML; else { b_print_enabled = false; msg_Warn( NULL, "unrecognized print type %s", optarg ); } /* Make stdout line-buffered */ setvbuf(stdout, NULL, _IOLBF, 0); break; case 'Q': i_quit_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000; break; case 'V': DisplayVersion(); exit(0); break; case 'Z': psz_mrtg_file = optarg; break; case '0': { /* We expect a comma separated list of numbers. Put them into the pi_newpids array as they appear */ char *str1; char *saveptr = NULL; char *tok = NULL; int i, i_newpid; for (i = 0, str1 = optarg; i < N_MAP_PIDS; i++, str1 = NULL) { tok = strtok_r(str1, ",", &saveptr); if ( !tok ) break; i_newpid = strtoul(tok, NULL, 0); if ( !i_newpid ) { msg_Err( NULL, "Invalid pidmap string" ); usage(); } pi_newpids[i] = i_newpid; } b_do_remap = true; break; } #ifdef HAVE_DVB_SUPPORT case '2': i_dvr_buffer_size = strtol( optarg, NULL, 0 ); if (!i_dvr_buffer_size) usage(); // it exits /* roundup to packet size */ i_dvr_buffer_size += TS_SIZE - 1; i_dvr_buffer_size /= TS_SIZE; i_dvr_buffer_size *= TS_SIZE; break; #endif case 'h': default: usage(); } } if ( optind < i_argc || pf_Open == NULL ) usage(); if ( b_enable_syslog ) msg_Connect( psz_syslog_ident ? psz_syslog_ident : pp_argv[0] ); if ( i_verbose ) DisplayVersion(); msg_Warn( NULL, "restarting" ); switch (i_print_type) { case PRINT_XML: printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); printf("<TS>\n"); break; default: break; } if ( b_udp_global ) { msg_Warn( NULL, "raw UDP output is deprecated. Please consider using RTP." ); msg_Warn( NULL, "for DVB-IP compliance you should use RTP." ); } if ( b_epg_global && !b_dvb_global ) { msg_Dbg( NULL, "turning on DVB compliance, required by EPG information" ); b_dvb_global = true; } memset( &output_dup, 0, sizeof(output_dup) ); if ( psz_dup_config != NULL ) { output_config_t config; config_Defaults( &config ); if ( !config_ParseHost( &config, psz_dup_config ) ) msg_Err( NULL, "Invalid target address for -d switch" ); else { output_Init( &output_dup, &config ); output_Change( &output_dup, &config ); } config_Free( &config ); } if ( strcasecmp( psz_native_charset, psz_dvb_charset ) ) { #ifdef HAVE_ICONV iconv_t iconv_system = iconv_open( psz_dvb_charset, psz_native_charset ); if ( iconv_system != (iconv_t)-1 ) { size_t i = strlen( psz_network_name ); char *p, *psz_string; i_network_name_tmp_size = i * 6; p = psz_string = malloc(i_network_name_tmp_size); if ( iconv( iconv_system, (char **)&psz_network_name, &i, &p, &i_network_name_tmp_size ) == -1 ) free( psz_string ); else { p_network_name_tmp = psz_string; i_network_name_tmp_size = p - psz_string; } iconv_close( iconv_system ); } #else msg_Warn( NULL, "unable to convert from %s to %s (iconv is not available)", psz_native_charset, psz_dvb_charset ); #endif } if ( p_network_name_tmp == NULL ) { p_network_name_tmp = strdup(psz_network_name); i_network_name_tmp_size = strlen(psz_network_name); } p_network_name = dvb_string_set( (uint8_t *)p_network_name_tmp, i_network_name_tmp_size, psz_dvb_charset, &i_network_name_size ); free( p_network_name_tmp ); /* Set signal handlers */ memset( &sa, 0, sizeof(struct sigaction) ); sa.sa_handler = SigHandler; sigfillset( &set ); if ( sigaction( SIGHUP, &sa, NULL ) == -1 || sigaction( SIGINT, &sa, NULL ) == -1 ) { msg_Err( NULL, "couldn't set signal handler: %s", strerror(errno) ); exit(EXIT_FAILURE); } srand( time(NULL) * getpid() ); demux_Open(); // init the mrtg logfile mrtgInit(psz_mrtg_file); if ( i_priority > 0 ) { memset( ¶m, 0, sizeof(struct sched_param) ); param.sched_priority = i_priority; if ( (i_error = pthread_setschedparam( pthread_self(), SCHED_RR, ¶m )) ) { msg_Warn( NULL, "couldn't set thread priority: %s", strerror(i_error) ); } } config_ReadFile( psz_conf_file ); if ( psz_srv_socket != NULL ) comm_Open(); for ( ; ; ) { block_t *p_ts; if ( b_exit_now ) { msg_Info( NULL, "Shutdown was requested." ); break; } if ( b_conf_reload ) { b_conf_reload = 0; msg_Info( NULL, "Configuration reload was requested." ); config_ReadFile( psz_conf_file ); } if ( i_quit_timeout && i_quit_timeout <= i_wallclock ) { switch (i_print_type) { case PRINT_XML: printf("</TS>\n"); break; default: break; } exit(EXIT_SUCCESS); } p_ts = pf_Read( i_poll_timeout ); if ( p_ts != NULL ) { mrtgAnalyse(p_ts); demux_Run( p_ts ); } i_poll_timeout = output_Send(); if ( i_poll_timeout == -1 || i_poll_timeout > MAX_POLL_TIMEOUT ) i_poll_timeout = MAX_POLL_TIMEOUT; } mrtgClose(); outputs_Close( i_nb_outputs ); demux_Close(); free( p_network_name ); if ( b_enable_syslog ) msg_Disconnect(); if ( psz_srv_socket && i_comm_fd > -1 ) unlink( psz_srv_socket ); return EXIT_SUCCESS; }
/***************************************************************************** * Block: *****************************************************************************/ static block_t *Block( access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; int i_blocks = VCD_BLOCKS_ONCE; block_t *p_block; /* Check end of file */ if( p_access->info.b_eof ) return NULL; /* Check end of title */ while( p_sys->i_sector >= p_sys->p_sectors[p_sys->i_current_title + 2] ) { if( p_sys->i_current_title + 2 >= p_sys->i_titles ) { p_access->info.b_eof = true; return NULL; } p_sys->i_current_title++; p_sys->i_current_seekpoint = 0; p_sys->offset = 0; } /* Don't read after the end of a title */ if( p_sys->i_sector + i_blocks >= p_sys->p_sectors[p_sys->i_current_title + 2] ) { i_blocks = p_sys->p_sectors[p_sys->i_current_title + 2 ] - p_sys->i_sector; } /* Do the actual reading */ if( i_blocks < 0 || !( p_block = block_Alloc( i_blocks * VCD_DATA_SIZE ) ) ) { msg_Err( p_access, "cannot get a new block of size: %i", i_blocks * VCD_DATA_SIZE ); return NULL; } if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev, p_sys->i_sector, p_block->p_buffer, i_blocks, VCD_TYPE ) < 0 ) { msg_Err( p_access, "cannot read sector %i", p_sys->i_sector ); block_Release( p_block ); /* Try to skip one sector (in case of bad sectors) */ p_sys->offset += VCD_DATA_SIZE; p_sys->i_sector++; return NULL; } /* Update seekpoints */ for( int i_read = 0; i_read < i_blocks; i_read++ ) { input_title_t *t = p_sys->title[p_sys->i_current_title]; if( t->i_seekpoint > 0 && p_sys->i_current_seekpoint + 1 < t->i_seekpoint && (int64_t) /* Unlikely to go over 8192 PetaB */ (p_sys->offset + i_read * VCD_DATA_SIZE) >= t->seekpoint[p_sys->i_current_seekpoint + 1]->i_byte_offset ) { msg_Dbg( p_access, "seekpoint change" ); p_sys->i_current_seekpoint++; } } /* Update a few values */ p_sys->offset += p_block->i_buffer; p_sys->i_sector += i_blocks; return p_block; }
/***************************************************************************** * DecodeBlock: *****************************************************************************/ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { block_Release( p_block ); return NULL; } /* Remove ADTS header if we have decoder specific config */ if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 ) { if( p_block->p_buffer[0] == 0xff && ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */ { /* ADTS header present */ size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */ i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 ); /* FIXME: multiple blocks per frame */ if( p_block->i_buffer > i_header_size ) { p_block->p_buffer += i_header_size; p_block->i_buffer -= i_header_size; } } } /* Append the block to the temporary buffer */ if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer ) { size_t i_buffer_size = p_sys->i_buffer + p_block->i_buffer; uint8_t *p_buffer = realloc( p_sys->p_buffer, i_buffer_size ); if( p_buffer ) { p_sys->i_buffer_size = i_buffer_size; p_sys->p_buffer = p_buffer; } else { p_block->i_buffer = 0; } } if( p_block->i_buffer > 0 ) { vlc_memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer ); p_sys->i_buffer += p_block->i_buffer; p_block->i_buffer = 0; } if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 ) { /* We have a decoder config so init the handle */ unsigned long i_rate; unsigned char i_channels; if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_rate, &i_channels ) >= 0 ) { p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } } if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer ) { unsigned long i_rate; unsigned char i_channels; /* Init faad with the first frame */ if( faacDecInit( p_sys->hfaad, p_sys->p_buffer, p_sys->i_buffer, &i_rate, &i_channels ) < 0 ) { block_Release( p_block ); return NULL; } p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->date ) ) { date_Set( &p_sys->date, p_block->i_pts ); } else if( !date_Get( &p_sys->date ) ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); p_sys->i_buffer = 0; return NULL; } /* Decode all data */ if( p_sys->i_buffer ) { void *samples; faacDecFrameInfo frame; aout_buffer_t *p_out; int i, j; samples = faacDecDecode( p_sys->hfaad, &frame, p_sys->p_buffer, p_sys->i_buffer ); if( frame.error > 0 ) { msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) ); /* Flush the buffer */ p_sys->i_buffer = 0; block_Release( p_block ); return NULL; } if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 ) { msg_Warn( p_dec, "invalid channels count: %i", frame.channels ); /* Flush the buffer */ p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } block_Release( p_block ); return NULL; } if( frame.samples <= 0 ) { msg_Warn( p_dec, "decoded zero sample" ); /* Flush the buffer */ p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } block_Release( p_block ); return NULL; } /* We decoded a valid frame */ if( p_dec->fmt_out.audio.i_rate != frame.samplerate ) { date_Init( &p_sys->date, frame.samplerate, 1 ); date_Set( &p_sys->date, p_block->i_pts ); } p_block->i_pts = VLC_TS_INVALID; /* PTS is valid only once */ p_dec->fmt_out.audio.i_rate = frame.samplerate; p_dec->fmt_out.audio.i_channels = frame.channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[frame.channels]; /* Adjust stream info when dealing with SBR/PS */ bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2); if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps ) { const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" : b_sbr ? "SBR" : "PS"; msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)", psz_ext, frame.channels, frame.samplerate ); if( !p_dec->p_description ) p_dec->p_description = vlc_meta_New(); if( p_dec->p_description ) vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext ); p_sys->b_sbr = b_sbr; p_sys->b_ps = frame.ps; } /* Convert frame.channel_position to our own channel values */ p_dec->fmt_out.audio.i_physical_channels = 0; for( i = 0; i < frame.channels; i++ ) { /* Find the channel code */ for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ ) { if( frame.channel_position[i] == pi_channels_in[j] ) break; } if( j >= MAX_CHANNEL_POSITIONS ) { msg_Warn( p_dec, "unknown channel ordering" ); /* Invent something */ j = i; } /* */ p_sys->pi_channel_positions[i] = pi_channels_out[j]; if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] ) frame.channels--; /* We loose a duplicated channel */ else p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j]; } p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels; p_out = decoder_NewAudioBuffer(p_dec, frame.samples/frame.channels); if( p_out == NULL ) { p_sys->i_buffer = 0; block_Release( p_block ); return NULL; } p_out->i_pts = date_Get( &p_sys->date ); p_out->i_length = date_Increment( &p_sys->date, frame.samples / frame.channels ) - p_out->i_pts; DoReordering( (uint32_t *)p_out->p_buffer, samples, frame.samples / frame.channels, frame.channels, p_sys->pi_channel_positions ); p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } return p_out; } block_Release( p_block ); return NULL; }
/***************************************************************************** * VCDOpen: open vcd *****************************************************************************/ static int Open( vlc_object_t *p_this ) { access_t *p_access = (access_t *)p_this; access_sys_t *p_sys; if( p_access->psz_filepath == NULL ) return VLC_EGENERIC; char *psz_dup = ToLocaleDup( p_access->psz_filepath ); char *psz; int i_title = 0; int i_chapter = 0; vcddev_t *vcddev; /* Command line: vcd://[dev_path][#title[,chapter]] */ if( ( psz = strchr( psz_dup, '#' ) ) ) { *psz++ = '\0'; i_title = strtol( psz, &psz, 0 ); if( *psz ) i_chapter = strtol( psz+1, &psz, 0 ); } if( *psz_dup == '\0' ) { free( psz_dup ); /* Only when selected */ if( strcmp( p_access->psz_access, "vcd" ) && strcmp( p_access->psz_access, "svcd" ) ) return VLC_EGENERIC; psz_dup = var_CreateGetString( p_access, "vcd" ); if( *psz_dup == '\0' ) { free( psz_dup ); return VLC_EGENERIC; } } #if defined( _WIN32 ) || defined( __OS2__ ) if( psz_dup[0] && psz_dup[1] == ':' && psz_dup[2] == '\\' && psz_dup[3] == '\0' ) psz_dup[2] = '\0'; #endif /* Open VCD */ vcddev = ioctl_Open( p_this, psz_dup ); free( psz_dup ); if( !vcddev ) return VLC_EGENERIC; /* Set up p_access */ p_access->p_sys = p_sys = calloc( 1, sizeof( access_sys_t ) ); if( unlikely(!p_sys )) goto error; p_sys->vcddev = vcddev; p_sys->offset = 0; /* We read the Table Of Content information */ p_sys->i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access), p_sys->vcddev, &p_sys->p_sectors ); if( p_sys->i_titles < 0 ) { msg_Err( p_access, "unable to count tracks" ); goto error; } else if( p_sys->i_titles <= 1 ) { msg_Err( p_access, "no movie tracks found" ); goto error; } /* The first title isn't usable */ p_sys->i_titles--; for( int i = 0; i < p_sys->i_titles; i++ ) { p_sys->title[i] = vlc_input_title_New(); msg_Dbg( p_access, "title[%d] start=%d", i, p_sys->p_sectors[1+i] ); msg_Dbg( p_access, "title[%d] end=%d", i, p_sys->p_sectors[i+2] ); } /* Map entry points into chapters */ if( EntryPoints( p_access ) ) { msg_Warn( p_access, "could not read entry points, will not use them" ); } /* Starting title/chapter and sector */ if( i_title >= p_sys->i_titles ) i_title = 0; if( i_chapter >= p_sys->title[i_title]->i_seekpoint ) i_chapter = 0; p_sys->i_sector = p_sys->p_sectors[1+i_title]; if( i_chapter > 0 ) { p_sys->i_sector += ( p_sys->title[i_title]->seekpoint[i_chapter]->i_byte_offset / VCD_DATA_SIZE ); } /* p_access */ p_access->pf_read = NULL; p_access->pf_block = Block; p_access->pf_control = Control; p_access->pf_seek = Seek; p_access->info.b_eof = false; p_sys->i_current_title = i_title; p_sys->i_current_seekpoint = i_chapter; p_sys->offset = (uint64_t)(p_sys->i_sector - p_sys->p_sectors[1+i_title]) * VCD_DATA_SIZE; return VLC_SUCCESS; error: ioctl_Close( VLC_OBJECT(p_access), vcddev ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*) p_this; int i_cat, i_codec_id, i_result; const char *psz_namecodec; AVCodecContext *p_context = NULL; AVCodec *p_codec = NULL; /* *** determine codec type *** */ if( !GetFfmpegCodec( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id, &psz_namecodec ) ) { return VLC_EGENERIC; } /* Initialization must be done before avcodec_find_decoder() */ InitLibavcodec(p_this); /* *** ask ffmpeg for a decoder *** */ p_codec = avcodec_find_decoder( i_codec_id ); if( !p_codec ) { msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec ); return VLC_EGENERIC; } /* *** get a p_context *** */ p_context = avcodec_alloc_context(); if( !p_context ) return VLC_ENOMEM; p_context->debug = var_InheritInteger( p_dec, "ffmpeg-debug" ); p_context->opaque = (void *)p_this; /* Set CPU capabilities */ unsigned i_cpu = vlc_CPU(); p_context->dsp_mask = 0; if( !(i_cpu & CPU_CAPABILITY_MMX) ) { p_context->dsp_mask |= FF_MM_MMX; } if( !(i_cpu & CPU_CAPABILITY_MMXEXT) ) { p_context->dsp_mask |= FF_MM_MMXEXT; } if( !(i_cpu & CPU_CAPABILITY_3DNOW) ) { p_context->dsp_mask |= FF_MM_3DNOW; } if( !(i_cpu & CPU_CAPABILITY_SSE) ) { p_context->dsp_mask |= FF_MM_SSE; } if( !(i_cpu & CPU_CAPABILITY_SSE2) ) { p_context->dsp_mask |= FF_MM_SSE2; } #ifdef FF_MM_SSE3 if( !(i_cpu & CPU_CAPABILITY_SSE3) ) p_context->dsp_mask |= FF_MM_SSE3; #endif #ifdef FF_MM_SSSE3 if( !(i_cpu & CPU_CAPABILITY_SSSE3) ) p_context->dsp_mask |= FF_MM_SSSE3; #endif #ifdef FF_MM_SSE4 if( !(i_cpu & CPU_CAPABILITY_SSE4_1) ) p_context->dsp_mask |= FF_MM_SSE4; #endif #ifdef FF_MM_SSE42 if( !(i_cpu & CPU_CAPABILITY_SSE4_2) ) p_context->dsp_mask |= FF_MM_SSE42; #endif p_dec->b_need_packetized = true; switch( i_cat ) { case VIDEO_ES: p_dec->pf_decode_video = DecodeVideo; i_result = InitVideoDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case AUDIO_ES: p_dec->pf_decode_audio = DecodeAudio; i_result = InitAudioDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case SPU_ES: p_dec->pf_decode_sub = DecodeSubtitle; i_result = InitSubtitleDec( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; default: i_result = VLC_EGENERIC; } if( i_result == VLC_SUCCESS ) { p_dec->p_sys->i_cat = i_cat; if( p_context->profile != FF_PROFILE_UNKNOWN) p_dec->fmt_in.i_profile = p_context->profile; if( p_context->level != FF_LEVEL_UNKNOWN) p_dec->fmt_in.i_level = p_context->level; } return i_result; }
static int sms_Read( stream_t *s, uint8_t *p_read, int i_read ) { stream_sys_t *p_sys = s->p_sys; int copied = 0; chunk_t *chunk = NULL; do { chunk = get_chunk( s, true ); if( !chunk ) return copied; if( chunk->read_pos >= (int)chunk->size ) { if( chunk->type == VIDEO_ES || ( !SMS_GET_SELECTED_ST( VIDEO_ES ) && chunk->type == AUDIO_ES ) ) { vlc_mutex_lock( &p_sys->download.lock_wait ); p_sys->playback.toffset += chunk->duration; vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_cond_signal( &p_sys->download.wait); } if( !p_sys->b_cache || p_sys->b_live ) { FREENULL( chunk->data ); chunk->read_pos = 0; } chunk->read_pos = 0; p_sys->playback.index += 1; msg_Dbg( s, "Incrementing playback index" ); continue; } if( chunk->read_pos == 0 ) { const char *verb = p_read == NULL ? "skipping" : "reading"; msg_Dbg( s, "%s chunk %u (%u bytes), type %i", verb, chunk->sequence, i_read, chunk->type ); /* check integrity */ uint32_t type; uint8_t *slice = chunk->data; SMS_GET4BYTES( type ); SMS_GETFOURCC( type ); assert( type == ATOM_moof || type == ATOM_uuid ); } int len = -1; uint8_t *src = chunk->data + chunk->read_pos; if( i_read <= chunk->size - chunk->read_pos ) len = i_read; else len = chunk->size - chunk->read_pos; if( len > 0 ) { if( p_read ) /* otherwise caller skips data */ memcpy( p_read + copied, src, len ); chunk->read_pos += len; copied += len; i_read -= len; } } while ( i_read > 0 ); return copied; }
static void transcode_video_encoder_init( sout_stream_t *p_stream, sout_stream_id_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; const es_format_t *p_fmt_out = &id->p_decoder->fmt_out; if( id->p_f_chain ) { p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain ); } if( id->p_uf_chain ) { p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain ); } /* Calculate scaling * width/height of source */ int i_src_visible_width = p_fmt_out->video.i_visible_width; int i_src_visible_height = p_fmt_out->video.i_visible_height; if (i_src_visible_width == 0) i_src_visible_width = p_fmt_out->video.i_width; if (i_src_visible_height == 0) i_src_visible_height = p_fmt_out->video.i_height; /* with/height scaling */ float f_scale_width = 1; float f_scale_height = 1; /* aspect ratio */ float f_aspect = (double)p_fmt_out->video.i_sar_num * p_fmt_out->video.i_width / p_fmt_out->video.i_sar_den / p_fmt_out->video.i_height; msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect ); /* Change f_aspect from source frame to source pixel */ f_aspect = f_aspect * i_src_visible_height / i_src_visible_width; msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect ); /* Calculate scaling factor for specified parameters */ if( id->p_encoder->fmt_out.video.i_width <= 0 && id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale ) { /* Global scaling. Make sure width will remain a factor of 16 */ float f_real_scale; int i_new_height; int i_new_width = i_src_visible_width * p_sys->f_scale; if( i_new_width % 16 <= 7 && i_new_width >= 16 ) i_new_width -= i_new_width % 16; else i_new_width += 16 - i_new_width % 16; f_real_scale = (float)( i_new_width ) / (float) i_src_visible_width; i_new_height = __MAX( 16, i_src_visible_height * (float)f_real_scale ); f_scale_width = f_real_scale; f_scale_height = (float) i_new_height / (float) i_src_visible_height; } else if( id->p_encoder->fmt_out.video.i_width > 0 && id->p_encoder->fmt_out.video.i_height <= 0 ) { /* Only width specified */ f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_visible_width; f_scale_height = f_scale_width; } else if( id->p_encoder->fmt_out.video.i_width <= 0 && id->p_encoder->fmt_out.video.i_height > 0 ) { /* Only height specified */ f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_visible_height; f_scale_width = f_scale_height; } else if( id->p_encoder->fmt_out.video.i_width > 0 && id->p_encoder->fmt_out.video.i_height > 0 ) { /* Width and height specified */ f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_visible_width; f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_visible_height; } /* check maxwidth and maxheight */ if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth / i_src_visible_width ) { f_scale_width = (float)p_sys->i_maxwidth / i_src_visible_width; } if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight / i_src_visible_height ) { f_scale_height = (float)p_sys->i_maxheight / i_src_visible_height; } /* Change aspect ratio from source pixel to scaled pixel */ f_aspect = f_aspect * f_scale_height / f_scale_width; msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect ); /* f_scale_width and f_scale_height are now final */ /* Calculate width, height from scaling * Make sure its multiple of 2 */ /* width/height of output stream */ int i_dst_visible_width = 2 * (int)(f_scale_width*i_src_visible_width/2+0.5); int i_dst_visible_height = 2 * (int)(f_scale_height*i_src_visible_height/2+0.5); int i_dst_width = 2 * (int)(f_scale_width*p_fmt_out->video.i_width/2+0.5); int i_dst_height = 2 * (int)(f_scale_height*p_fmt_out->video.i_height/2+0.5); /* Change aspect ratio from scaled pixel to output frame */ f_aspect = f_aspect * i_dst_visible_width / i_dst_visible_height; /* Store calculated values */ id->p_encoder->fmt_out.video.i_width = i_dst_width; id->p_encoder->fmt_out.video.i_visible_width = i_dst_visible_width; id->p_encoder->fmt_out.video.i_height = i_dst_height; id->p_encoder->fmt_out.video.i_visible_height = i_dst_visible_height; id->p_encoder->fmt_in.video.i_width = i_dst_width; id->p_encoder->fmt_in.video.i_visible_width = i_dst_visible_width; id->p_encoder->fmt_in.video.i_height = i_dst_height; id->p_encoder->fmt_in.video.i_visible_height = i_dst_visible_height; msg_Dbg( p_stream, "source %ix%i, destination %ix%i", i_src_visible_width, i_src_visible_height, i_dst_visible_width, i_dst_visible_height ); /* Handle frame rate conversion */ if( !id->p_encoder->fmt_out.video.i_frame_rate || !id->p_encoder->fmt_out.video.i_frame_rate_base ) { if( p_fmt_out->video.i_frame_rate && p_fmt_out->video.i_frame_rate_base ) { id->p_encoder->fmt_out.video.i_frame_rate = p_fmt_out->video.i_frame_rate; id->p_encoder->fmt_out.video.i_frame_rate_base = p_fmt_out->video.i_frame_rate_base; } else { /* Pick a sensible default value */ id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE; id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE; } } id->p_encoder->fmt_in.video.i_frame_rate = id->p_encoder->fmt_out.video.i_frame_rate; id->p_encoder->fmt_in.video.i_frame_rate_base = id->p_encoder->fmt_out.video.i_frame_rate_base; date_Init( &id->interpolated_pts, id->p_encoder->fmt_out.video.i_frame_rate, id->p_encoder->fmt_out.video.i_frame_rate_base ); /* Check whether a particular aspect ratio was requested */ if( id->p_encoder->fmt_out.video.i_sar_num <= 0 || id->p_encoder->fmt_out.video.i_sar_den <= 0 ) { vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num, &id->p_encoder->fmt_out.video.i_sar_den, (uint64_t)p_fmt_out->video.i_sar_num * i_src_visible_width * i_dst_visible_height, (uint64_t)p_fmt_out->video.i_sar_den * i_src_visible_height * i_dst_visible_width, 0 ); } else { vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num, &id->p_encoder->fmt_out.video.i_sar_den, id->p_encoder->fmt_out.video.i_sar_num, id->p_encoder->fmt_out.video.i_sar_den, 0 ); } id->p_encoder->fmt_in.video.i_sar_num = id->p_encoder->fmt_out.video.i_sar_num; id->p_encoder->fmt_in.video.i_sar_den = id->p_encoder->fmt_out.video.i_sar_den; msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_sar_num * id->p_encoder->fmt_out.video.i_width, id->p_encoder->fmt_out.video.i_sar_den * id->p_encoder->fmt_out.video.i_height ); id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec; }
static sout_stream_id_sys_t * AddOut( sout_stream_t *p_stream, const es_format_t *p_fmt ) { out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys; bridge_t *p_bridge; bridged_es_t *p_es; int i; if ( p_sys->b_inited ) { msg_Err( p_stream, "bridge-out can only handle 1 es at a time." ); return NULL; } p_sys->b_inited = true; vlc_mutex_lock( &lock ); p_bridge = var_GetAddress( p_stream->p_libvlc, p_sys->psz_name ); if ( p_bridge == NULL ) { p_bridge = xmalloc( sizeof( bridge_t ) ); var_Create( p_stream->p_libvlc, p_sys->psz_name, VLC_VAR_ADDRESS ); var_SetAddress( p_stream->p_libvlc, p_sys->psz_name, p_bridge ); p_bridge->i_es_num = 0; p_bridge->pp_es = NULL; } for ( i = 0; i < p_bridge->i_es_num; i++ ) { if ( p_bridge->pp_es[i]->b_empty && !p_bridge->pp_es[i]->b_changed ) break; } if ( i == p_bridge->i_es_num ) { p_bridge->pp_es = xrealloc( p_bridge->pp_es, (p_bridge->i_es_num + 1) * sizeof(bridged_es_t *) ); p_bridge->i_es_num++; p_bridge->pp_es[i] = xmalloc( sizeof(bridged_es_t) ); } p_sys->p_es = p_es = p_bridge->pp_es[i]; p_es->fmt = *p_fmt; p_es->fmt.i_id = p_sys->i_id; p_es->p_block = NULL; p_es->pp_last = &p_es->p_block; p_es->b_empty = false; p_es->id = NULL; p_es->i_last = VLC_TS_INVALID; p_es->b_changed = true; msg_Dbg( p_stream, "bridging out input codec=%4.4s id=%d pos=%d", (char*)&p_es->fmt.i_codec, p_es->fmt.i_id, i ); vlc_mutex_unlock( &lock ); return (sout_stream_id_sys_t *)p_sys; }
int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *in, block_t **out ) { sout_stream_sys_t *p_sys = p_stream->p_sys; bool b_need_duplicate = false; picture_t *p_pic; *out = NULL; if( unlikely( in == NULL ) ) { if( p_sys->i_threads == 0 ) { block_t *p_block; do { p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL ); block_ChainAppend( out, p_block ); } while( p_block ); } else { /* * FIXME: we need EncoderThread() to flush buffers and signal us * when it's done so we can send the last frames to the chain */ } return VLC_SUCCESS; } while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) ) { if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up ) { mtime_t current_date = mdate(); if( unlikely( current_date + 50000 > p_pic->date ) ) { msg_Dbg( p_stream, "late picture skipped (%"PRId64")", current_date + 50000 - p_pic->date ); picture_Release( p_pic ); continue; } } if( p_sys->b_master_sync ) { mtime_t i_master_drift = p_sys->i_master_drift; mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1; mtime_t i_video_drift = p_pic->date - i_pts; if ( unlikely( i_video_drift > MASTER_SYNC_MAX_DRIFT || i_video_drift < -MASTER_SYNC_MAX_DRIFT ) ) { msg_Dbg( p_stream, "video drift is too high (%"PRId64", resetting master sync", i_video_drift ); date_Set( &id->interpolated_pts, p_pic->date ); i_pts = p_pic->date + 1; } i_video_drift = p_pic->date - i_pts; b_need_duplicate = false; /* Set the pts of the frame being encoded */ p_pic->date = i_pts; if( unlikely( i_video_drift < (i_master_drift - 50000) ) ) { #if 0 msg_Dbg( p_stream, "dropping frame (%i)", (int)(i_video_drift - i_master_drift) ); #endif picture_Release( p_pic ); continue; } else if( unlikely( i_video_drift > (i_master_drift + 50000) ) ) { #if 0 msg_Dbg( p_stream, "adding frame (%i)", (int)(i_video_drift - i_master_drift) ); #endif b_need_duplicate = true; } } if( unlikely ( id->p_encoder->p_module && !video_format_IsSimilar( &p_sys->fmt_input_video, &id->p_decoder->fmt_out.video ) ) ) { msg_Info( p_stream, "aspect-ratio changed, reiniting. %i -> %i : %i -> %i.", p_sys->fmt_input_video.i_sar_num, id->p_decoder->fmt_out.video.i_sar_num, p_sys->fmt_input_video.i_sar_den, id->p_decoder->fmt_out.video.i_sar_den ); /* Close filters */ if( id->p_f_chain ) filter_chain_Delete( id->p_f_chain ); id->p_f_chain = NULL; if( id->p_uf_chain ) filter_chain_Delete( id->p_uf_chain ); id->p_uf_chain = NULL; /* Reinitialize filters */ id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1; id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1; id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_out.video.i_sar_den = 0; transcode_video_filter_init( p_stream, id ); transcode_video_encoder_init( p_stream, id ); conversion_video_filter_append( id ); memcpy( &p_sys->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t)); } if( unlikely( !id->p_encoder->p_module ) ) { if( id->p_f_chain ) filter_chain_Delete( id->p_f_chain ); if( id->p_uf_chain ) filter_chain_Delete( id->p_uf_chain ); id->p_f_chain = id->p_uf_chain = NULL; transcode_video_filter_init( p_stream, id ); transcode_video_encoder_init( p_stream, id ); conversion_video_filter_append( id ); memcpy( &p_sys->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t)); if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS ) { picture_Release( p_pic ); transcode_video_close( p_stream, id ); id->b_transcode = false; return VLC_EGENERIC; } } /* Run the filter and output chains; first with the picture, * and then with NULL as many times as we need until they * stop outputting frames. */ for ( ;; ) { picture_t *p_filtered_pic = p_pic; /* Run filter chain */ if( id->p_f_chain ) p_filtered_pic = filter_chain_VideoFilter( id->p_f_chain, p_filtered_pic ); if( !p_filtered_pic ) break; for ( ;; ) { picture_t *p_user_filtered_pic = p_filtered_pic; /* Run user specified filter chain */ if( id->p_uf_chain ) p_user_filtered_pic = filter_chain_VideoFilter( id->p_uf_chain, p_user_filtered_pic ); if( !p_user_filtered_pic ) break; OutputFrame( p_sys, p_user_filtered_pic, b_need_duplicate, p_stream, id, out ); b_need_duplicate = false; p_filtered_pic = NULL; } p_pic = NULL; } } if( p_sys->i_threads >= 1 ) { /* Pick up any return data the encoder thread wants to output. */ vlc_mutex_lock( &p_sys->lock_out ); *out = p_sys->p_buffers; p_sys->p_buffers = NULL; vlc_mutex_unlock( &p_sys->lock_out ); } return VLC_SUCCESS; }
static int AVI_ChunkRead_strf( stream_t *s, avi_chunk_t *p_chk ) { avi_chunk_t *p_strh; AVI_READCHUNK_ENTER; if( p_chk->common.p_father == NULL ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } if( !( p_strh = AVI_ChunkFind( p_chk->common.p_father, AVIFOURCC_strh, 0 ) ) ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } switch( p_strh->strh.i_type ) { case( AVIFOURCC_auds ): p_chk->strf.auds.i_cat = AUDIO_ES; p_chk->strf.auds.p_wf = xmalloc( __MAX( p_chk->common.i_chunk_size, sizeof( WAVEFORMATEX ) ) ); if ( !p_chk->strf.auds.p_wf ) { AVI_READCHUNK_EXIT( VLC_ENOMEM ); } AVI_READ2BYTES( p_chk->strf.auds.p_wf->wFormatTag ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nChannels ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nSamplesPerSec ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nAvgBytesPerSec ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nBlockAlign ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->wBitsPerSample ); if( p_chk->strf.auds.p_wf->wFormatTag != WAVE_FORMAT_PCM && p_chk->common.i_chunk_size > sizeof( WAVEFORMATEX ) ) { AVI_READ2BYTES( p_chk->strf.auds.p_wf->cbSize ); /* prevent segfault */ if( p_chk->strf.auds.p_wf->cbSize > p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ) ) { p_chk->strf.auds.p_wf->cbSize = p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ); } if( p_chk->strf.auds.p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) { msg_Dbg( s, "Extended header found" ); } } else { p_chk->strf.auds.p_wf->cbSize = 0; } if( p_chk->strf.auds.p_wf->cbSize > 0 ) { memcpy( &p_chk->strf.auds.p_wf[1] , p_buff + 8 + sizeof( WAVEFORMATEX ), /* 8=fourcc+size */ p_chk->strf.auds.p_wf->cbSize ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: audio:0x%4.4x channels:%d %dHz %dbits/sample %dkb/s", p_chk->strf.auds.p_wf->wFormatTag, p_chk->strf.auds.p_wf->nChannels, p_chk->strf.auds.p_wf->nSamplesPerSec, p_chk->strf.auds.p_wf->wBitsPerSample, p_chk->strf.auds.p_wf->nAvgBytesPerSec * 8 / 1024 ); #endif break; case( AVIFOURCC_vids ): p_strh->strh.i_samplesize = 0; /* XXX for ffmpeg avi file */ p_chk->strf.vids.i_cat = VIDEO_ES; p_chk->strf.vids.p_bih = xmalloc( __MAX( p_chk->common.i_chunk_size, sizeof( *p_chk->strf.vids.p_bih ) ) ); if ( !p_chk->strf.vids.p_bih ) { AVI_READCHUNK_EXIT( VLC_ENOMEM ); } AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSize ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biWidth ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biHeight ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biPlanes ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biBitCount ); AVI_READFOURCC( p_chk->strf.vids.p_bih->biCompression ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSizeImage ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biXPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biYPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrUsed ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrImportant ); if( p_chk->strf.vids.p_bih->biSize > p_chk->common.i_chunk_size ) { p_chk->strf.vids.p_bih->biSize = p_chk->common.i_chunk_size; } if ( p_chk->common.i_chunk_size > sizeof(VLC_BITMAPINFOHEADER) ) { uint64_t i_extrasize = p_chk->common.i_chunk_size - sizeof(VLC_BITMAPINFOHEADER); /* There's a color palette appended, set up VLC_BITMAPINFO */ memcpy( &p_chk->strf.vids.p_bih[1], p_buff + 8 + sizeof(VLC_BITMAPINFOHEADER), /* 8=fourrc+size */ i_extrasize ); if ( !p_chk->strf.vids.p_bih->biClrUsed ) p_chk->strf.vids.p_bih->biClrUsed = (1 << p_chk->strf.vids.p_bih->biBitCount); if( i_extrasize / sizeof(uint32_t) > UINT32_MAX ) p_chk->strf.vids.p_bih->biClrUsed = UINT32_MAX; else { p_chk->strf.vids.p_bih->biClrUsed = __MIN( i_extrasize / sizeof(uint32_t), p_chk->strf.vids.p_bih->biClrUsed ); } /* stay within VLC's limits */ p_chk->strf.vids.p_bih->biClrUsed = __MIN( VIDEO_PALETTE_COLORS_MAX, p_chk->strf.vids.p_bih->biClrUsed ); } else p_chk->strf.vids.p_bih->biClrUsed = 0; #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: video:%4.4s %"PRIu32"x%"PRIu32" planes:%d %dbpp", (char*)&p_chk->strf.vids.p_bih->biCompression, (uint32_t)p_chk->strf.vids.p_bih->biWidth, (uint32_t)p_chk->strf.vids.p_bih->biHeight, p_chk->strf.vids.p_bih->biPlanes, p_chk->strf.vids.p_bih->biBitCount ); #endif break; case AVIFOURCC_iavs: case AVIFOURCC_ivas: p_chk->strf.common.i_cat = UNKNOWN_ES; break; case( AVIFOURCC_txts ): p_chk->strf.common.i_cat = SPU_ES; break; default: msg_Warn( (vlc_object_t*)s, "unknown stream type: %4.4s", (char*)&p_strh->strh.i_type ); p_chk->strf.common.i_cat = UNKNOWN_ES; break; } AVI_READCHUNK_EXIT( VLC_SUCCESS ); }