/***************************************************************************** * DecodeAudio: Called to decode one frame *****************************************************************************/ static block_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; AVCodecContext *ctx = p_sys->p_context; if( !pp_block || !*pp_block ) return NULL; block_t *p_block = *pp_block; if( !ctx->extradata_size && p_dec->fmt_in.i_extra && p_sys->b_delayed_open) { InitDecoderConfig( p_dec, ctx ); OpenAudioCodec( p_dec ); } if( p_sys->b_delayed_open ) goto end; if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { avcodec_flush_buffers( ctx ); date_Set( &p_sys->end_date, VLC_TS_INVALID ); if( ctx->codec_id == AV_CODEC_ID_MP2 || ctx->codec_id == AV_CODEC_ID_MP3 ) p_sys->i_reject_count = 3; goto end; } /* We've just started the stream, wait for the first PTS. */ if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID ) goto end; if( p_block->i_buffer <= 0 ) goto end; if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 ) { p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); if( !p_block ) return NULL; *pp_block = p_block; p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE ); p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED; } AVFrame *frame = av_frame_alloc(); if (unlikely(frame == NULL)) goto end; for( int got_frame = 0; !got_frame; ) { if( p_block->i_buffer == 0 ) goto end; AVPacket pkt; av_init_packet( &pkt ); pkt.data = p_block->p_buffer; pkt.size = p_block->i_buffer; int used = avcodec_decode_audio4( ctx, frame, &got_frame, &pkt ); if( used < 0 ) { msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); goto end; } assert( p_block->i_buffer >= (unsigned)used ); if( used > p_block->i_buffer ) used = p_block->i_buffer; p_block->p_buffer += used; p_block->i_buffer -= used; } if( ctx->channels <= 0 || ctx->channels > 8 || ctx->sample_rate <= 0 ) { msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d", ctx->channels, ctx->sample_rate ); goto end; } if( p_dec->fmt_out.audio.i_rate != (unsigned int)ctx->sample_rate ) date_Init( &p_sys->end_date, ctx->sample_rate, 1 ); if( p_block->i_pts > date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } if( p_block->i_buffer == 0 ) { /* Done with this buffer */ block_Release( p_block ); p_block = NULL; *pp_block = NULL; } /* NOTE WELL: Beyond this point, p_block refers to the DECODED block! */ SetupOutputFormat( p_dec, true ); if( decoder_UpdateAudioFormat( p_dec ) ) goto drop; /* Interleave audio if required */ if( av_sample_fmt_is_planar( ctx->sample_fmt ) ) { p_block = block_Alloc(frame->linesize[0] * ctx->channels); if (unlikely(p_block == NULL)) goto drop; const void *planes[ctx->channels]; for (int i = 0; i < ctx->channels; i++) planes[i] = frame->extended_data[i]; aout_Interleave(p_block->p_buffer, planes, frame->nb_samples, ctx->channels, p_dec->fmt_out.audio.i_format); p_block->i_nb_samples = frame->nb_samples; av_frame_free(&frame); } else { p_block = vlc_av_frame_Wrap(frame); if (unlikely(p_block == NULL)) goto drop; } if (p_sys->b_extract) { /* TODO: do not drop channels... at least not here */ block_t *p_buffer = block_Alloc( p_dec->fmt_out.audio.i_bytes_per_frame * p_block->i_nb_samples ); if( unlikely(p_buffer == NULL) ) goto drop; aout_ChannelExtract( p_buffer->p_buffer, p_dec->fmt_out.audio.i_channels, p_block->p_buffer, ctx->channels, p_block->i_nb_samples, p_sys->pi_extraction, p_dec->fmt_out.audio.i_bitspersample ); p_buffer->i_nb_samples = p_block->i_nb_samples; block_Release( p_block ); p_block = p_buffer; } /* Silent unwanted samples */ if( p_sys->i_reject_count > 0 ) { memset( p_block->p_buffer, 0, p_block->i_buffer ); p_sys->i_reject_count--; } p_block->i_buffer = p_block->i_nb_samples * p_dec->fmt_out.audio.i_bytes_per_frame; p_block->i_pts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples ) - p_block->i_pts; return p_block; end: *pp_block = NULL; drop: if( p_block != NULL ) block_Release(p_block); return NULL; }
/** * Find the best suited decoder mode GUID and render format. */ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORMAT *output) { /* Retreive supported modes from the decoder service */ UINT input_count = 0; GUID *input_list = NULL; if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(va->vs, &input_count, &input_list))) { msg_Err(va->log, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed"); return VLC_EGENERIC; } for (unsigned i = 0; i < input_count; i++) { const GUID *g = &input_list[i]; const dxva2_mode_t *mode = Dxva2FindMode(g); if (mode) { msg_Dbg(va->log, "- '%s' is supported by hardware", mode->name); } else { msg_Warn(va->log, "- Unknown GUID = %08X-%04x-%04x-XXXX", (unsigned)g->Data1, g->Data2, g->Data3); } } /* Try all supported mode by our priority */ for (unsigned i = 0; dxva2_modes[i].name; i++) { const dxva2_mode_t *mode = &dxva2_modes[i]; if (!mode->codec || mode->codec != va->codec_id) continue; /* */ bool is_suported = false; for (const GUID *g = &input_list[0]; !is_suported && g < &input_list[input_count]; g++) { is_suported = IsEqualGUID(mode->guid, g); } if (!is_suported) continue; /* */ msg_Dbg(va->log, "Trying to use '%s' as input", mode->name); UINT output_count = 0; D3DFORMAT *output_list = NULL; if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(va->vs, mode->guid, &output_count, &output_list))) { msg_Err(va->log, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed"); continue; } for (unsigned j = 0; j < output_count; j++) { const D3DFORMAT f = output_list[j]; const d3d_format_t *format = D3dFindFormat(f); if (format) { msg_Dbg(va->log, "%s is supported for output", format->name); } else { msg_Dbg(va->log, "%d is supported for output (%4.4s)", f, (const char*)&f); } } /* */ for (unsigned j = 0; d3d_formats[j].name; j++) { const d3d_format_t *format = &d3d_formats[j]; /* */ bool is_suported = false; for (unsigned k = 0; !is_suported && k < output_count; k++) { is_suported = format->format == output_list[k]; } if (!is_suported) continue; /* We have our solution */ msg_Dbg(va->log, "Using '%s' to decode to '%s'", mode->name, format->name); *input = *mode->guid; *output = format->format; CoTaskMemFree(output_list); CoTaskMemFree(input_list); return VLC_SUCCESS; } CoTaskMemFree(output_list); } CoTaskMemFree(input_list); return VLC_EGENERIC; }
/***************************************************************************** * DecodeVideo: Called to decode one or more frames *****************************************************************************/ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; AVCodecContext *p_context = p_sys->p_context; int b_drawpicture; int b_null_size = false; block_t *p_block; if( !pp_block || !*pp_block ) return NULL; if( !p_context->extradata_size && p_dec->fmt_in.i_extra ) { ffmpeg_InitCodec( p_dec ); if( p_sys->b_delayed_open ) { if( ffmpeg_OpenCodec( p_dec ) ) msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); } } p_block = *pp_block; if( p_sys->b_delayed_open ) { block_Release( p_block ); return NULL; } if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ p_sys->i_late_frames = 0; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) avcodec_flush_buffers( p_context ); block_Release( p_block ); return NULL; } if( p_block->i_flags & BLOCK_FLAG_PREROLL ) { /* Do not care about late frames when prerolling * TODO avoid decoding of non reference frame * (ie all B except for H264 where it depends only on nal_ref_idc) */ p_sys->i_late_frames = 0; } if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) && (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) ) { if( p_sys->i_pts > VLC_TS_INVALID ) { msg_Err( p_dec, "more than 5 seconds of late video -> " "dropping frame (computer too slow ?)" ); p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */ } block_Release( p_block ); p_sys->i_late_frames--; return NULL; } /* A good idea could be to decode all I pictures and see for the other */ if( !p_dec->b_pace_control && p_sys->b_hurry_up && (p_sys->i_late_frames > 4) ) { b_drawpicture = 0; if( p_sys->i_late_frames < 12 ) { p_context->skip_frame = (p_sys->i_skip_frame <= AVDISCARD_NONREF) ? AVDISCARD_NONREF : p_sys->i_skip_frame; } else { /* picture too late, won't decode * but break picture until a new I, and for mpeg4 ...*/ p_sys->i_late_frames--; /* needed else it will never be decrease */ block_Release( p_block ); return NULL; } } else { if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) b_drawpicture = 1; else b_drawpicture = 0; } if( p_context->width <= 0 || p_context->height <= 0 ) { if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; b_null_size = true; } else if( !b_drawpicture ) { /* It creates broken picture * FIXME either our parser or ffmpeg is broken */ #if 0 if( p_sys->b_hurry_up ) p_context->skip_frame = __MAX( p_context->skip_frame, AVDISCARD_NONREF ); #endif } /* * Do the actual decoding now */ /* Don't forget that ffmpeg requires a little more bytes * that the real frame size */ if( p_block->i_buffer > 0 ) { p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0; p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); if( !p_block ) return NULL; p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; *pp_block = p_block; memset( p_block->p_buffer + p_block->i_buffer, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } while( p_block->i_buffer > 0 || p_sys->b_flush ) { int i_used, b_gotpicture; picture_t *p_pic; AVPacket pkt; /* Set the PTS/DTS in the context reordered_opaque field */ if( p_block->i_pts > VLC_TS_INVALID ) p_context->reordered_opaque = (p_block->i_pts << 1) | 0; else if( p_block->i_dts > VLC_TS_INVALID ) p_context->reordered_opaque = (p_block->i_dts << 1) | 1; else p_context->reordered_opaque = INT64_MIN; p_sys->p_ff_pic->reordered_opaque = p_context->reordered_opaque; /* Make sure we don't reuse the same timestamps twice */ p_block->i_pts = p_block->i_dts = VLC_TS_INVALID; post_mt( p_sys ); av_init_packet( &pkt ); pkt.data = p_block->p_buffer; pkt.size = p_block->i_buffer; i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, &b_gotpicture, &pkt ); if( b_null_size && !p_sys->b_flush && p_context->width > 0 && p_context->height > 0 ) { /* Reparse it to not drop the I frame */ b_null_size = false; if( p_sys->b_hurry_up ) p_context->skip_frame = p_sys->i_skip_frame; i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, &b_gotpicture, &pkt ); } wait_mt( p_sys ); if( p_sys->b_flush ) p_sys->b_first_frame = true; if( p_block->i_buffer <= 0 ) p_sys->b_flush = false; if( i_used < 0 ) { if( b_drawpicture ) msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); block_Release( p_block ); return NULL; } else if( i_used > p_block->i_buffer || p_context->thread_count > 1 ) { i_used = p_block->i_buffer; } /* Consumed bytes */ p_block->i_buffer -= i_used; p_block->p_buffer += i_used; /* Nothing to display */ if( !b_gotpicture ) { if( i_used == 0 ) break; continue; } /* Sanity check (seems to be needed for some streams) */ if( p_sys->p_ff_pic->pict_type == AV_PICTURE_TYPE_B) { p_sys->b_has_b_frames = true; } /* Compute the PTS */ mtime_t i_pts = VLC_TS_INVALID; if( p_sys->p_ff_pic->reordered_opaque != INT64_MIN ) { mtime_t i_ts = p_sys->p_ff_pic->reordered_opaque >> 1; bool b_dts = p_sys->p_ff_pic->reordered_opaque & 1; if( b_dts ) { if( !p_context->has_b_frames || !p_sys->b_has_b_frames || !p_sys->p_ff_pic->reference || p_sys->i_pts <= VLC_TS_INVALID ) i_pts = i_ts; /* Guess what ? The rules are different for Real Video :( */ if( (p_dec->fmt_in.i_codec == VLC_CODEC_RV30 || p_dec->fmt_in.i_codec == VLC_CODEC_RV40) && p_sys->b_has_b_frames ) { i_pts = VLC_TS_INVALID; if(p_sys->p_ff_pic->reference) i_pts = i_ts; } } else { i_pts = i_ts; } } if( i_pts <= VLC_TS_INVALID ) i_pts = p_sys->i_pts; /* Interpolate the next PTS */ if( i_pts > VLC_TS_INVALID ) p_sys->i_pts = i_pts; if( p_sys->i_pts > VLC_TS_INVALID ) { /* interpolate the next PTS */ if( p_dec->fmt_in.video.i_frame_rate > 0 && p_dec->fmt_in.video.i_frame_rate_base > 0 ) { p_sys->i_pts += INT64_C(1000000) * (2 + p_sys->p_ff_pic->repeat_pict) * p_dec->fmt_in.video.i_frame_rate_base / (2 * p_dec->fmt_in.video.i_frame_rate); } else if( p_context->time_base.den > 0 ) { int i_tick = p_context->ticks_per_frame; if( i_tick <= 0 ) i_tick = 1; p_sys->i_pts += INT64_C(1000000) * (2 + p_sys->p_ff_pic->repeat_pict) * i_tick * p_context->time_base.num / (2 * p_context->time_base.den); } } /* Update frame late count (except when doing preroll) */ mtime_t i_display_date = 0; if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) i_display_date = decoder_GetDisplayDate( p_dec, i_pts ); if( i_display_date > 0 && i_display_date <= mdate() ) { p_sys->i_late_frames++; if( p_sys->i_late_frames == 1 ) p_sys->i_late_frames_start = mdate(); } else { p_sys->i_late_frames = 0; } if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) ) continue; if( !p_sys->p_ff_pic->opaque ) { /* Get a new picture */ p_pic = ffmpeg_NewPictBuf( p_dec, p_context ); if( !p_pic ) { block_Release( p_block ); return NULL; } /* Fill p_picture_t from AVVideoFrame and do chroma conversion * if needed */ ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic ); } else { p_pic = (picture_t *)p_sys->p_ff_pic->opaque; decoder_LinkPicture( p_dec, p_pic ); } if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den ) { /* Fetch again the aspect ratio in case it changed */ p_dec->fmt_out.video.i_sar_num = p_context->sample_aspect_ratio.num; p_dec->fmt_out.video.i_sar_den = p_context->sample_aspect_ratio.den; if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den ) { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } } /* Send decoded frame to vout */ if( i_pts > VLC_TS_INVALID) { p_pic->date = i_pts; if( p_sys->b_first_frame ) { /* Hack to force display of still pictures */ p_sys->b_first_frame = false; p_pic->b_force = true; } p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict; p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame; p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first; p_pic->i_qstride = p_sys->p_ff_pic->qstride; int i_mb_h = ( p_pic->format.i_height + 15 ) / 16; p_pic->p_q = malloc( p_pic->i_qstride * i_mb_h ); memcpy( p_pic->p_q, p_sys->p_ff_pic->qscale_table, p_pic->i_qstride * i_mb_h ); switch( p_sys->p_ff_pic->qscale_type ) { case FF_QSCALE_TYPE_MPEG1: p_pic->i_qtype = QTYPE_MPEG1; break; case FF_QSCALE_TYPE_MPEG2: p_pic->i_qtype = QTYPE_MPEG2; break; case FF_QSCALE_TYPE_H264: p_pic->i_qtype = QTYPE_H264; break; } return p_pic; } else { decoder_DeletePicture( p_dec, p_pic ); } }
bool config_ParseHost( output_config_t *p_config, char *psz_string ) { struct addrinfo *p_ai; int i_mtu; p_config->psz_displayname = strdup( psz_string ); p_ai = ParseNodeService( psz_string, &psz_string, DEFAULT_PORT ); if ( p_ai == NULL ) return false; memcpy( &p_config->connect_addr, p_ai->ai_addr, p_ai->ai_addrlen ); freeaddrinfo( p_ai ); p_config->i_family = p_config->connect_addr.ss_family; if ( p_config->i_family == AF_UNSPEC ) return false; if ( psz_string == NULL || !*psz_string ) goto end; if ( *psz_string == '@' ) { psz_string++; p_ai = ParseNodeService( psz_string, &psz_string, 0 ); if ( p_ai == NULL || p_ai->ai_family != p_config->i_family ) msg_Warn( NULL, "invalid bind address" ); else memcpy( &p_config->bind_addr, p_ai->ai_addr, p_ai->ai_addrlen ); freeaddrinfo( p_ai ); } while ( (psz_string = strchr( psz_string, '/' )) != NULL ) { *psz_string++ = '\0'; #define IS_OPTION( option ) (!strncasecmp( psz_string, option, strlen(option) )) #define ARG_OPTION( option ) (psz_string + strlen(option)) if ( IS_OPTION("udp") ) p_config->i_config |= OUTPUT_UDP; else if ( IS_OPTION("dvb") ) p_config->i_config |= OUTPUT_DVB; else if ( IS_OPTION("epg") ) p_config->i_config |= OUTPUT_EPG; else if ( IS_OPTION("tsid=") ) p_config->i_tsid = strtol( ARG_OPTION("tsid="), NULL, 0 ); else if ( IS_OPTION("retention=") ) p_config->i_max_retention = strtoll( ARG_OPTION("retention="), NULL, 0 ) * 1000; else if ( IS_OPTION("latency=") ) p_config->i_output_latency = strtoll( ARG_OPTION("latency="), NULL, 0 ) * 1000; else if ( IS_OPTION("ttl=") ) p_config->i_ttl = strtol( ARG_OPTION("ttl="), NULL, 0 ); else if ( IS_OPTION("tos=") ) p_config->i_tos = strtol( ARG_OPTION("tos="), NULL, 0 ); else if ( IS_OPTION("mtu=") ) p_config->i_mtu = strtol( ARG_OPTION("mtu="), NULL, 0 ); else if ( IS_OPTION("ifindex=") ) p_config->i_if_index_v6 = strtol( ARG_OPTION("ifindex="), NULL, 0 ); else if ( IS_OPTION("srvname=") ) { if ( p_config->psz_service_name ) free( p_config->psz_service_name ); p_config->psz_service_name = config_stropt( ARG_OPTION("srvname=") ); } else if ( IS_OPTION("srvprovider=") ) { if ( !p_config->psz_service_provider ) free( p_config->psz_service_provider ); p_config->psz_service_provider = config_stropt( ARG_OPTION("srvprovider=") ); } else if ( IS_OPTION("ssrc=") ) { in_addr_t i_addr = inet_addr( ARG_OPTION("ssrc=") ); memcpy( p_config->pi_ssrc, &i_addr, 4 * sizeof(uint8_t) ); } else msg_Warn( NULL, "unrecognized option %s", psz_string ); #undef IS_OPTION #undef ARG_OPTION } if ( !p_config->psz_service_provider && psz_provider_name ) p_config->psz_service_provider = strdup( psz_provider_name ); end: i_mtu = p_config->i_family == AF_INET6 ? DEFAULT_IPV6_MTU : DEFAULT_IPV4_MTU; if ( !p_config->i_mtu ) p_config->i_mtu = i_mtu; else if ( p_config->i_mtu < TS_SIZE + RTP_HEADER_SIZE ) { msg_Warn( NULL, "invalid MTU %d, setting %d", p_config->i_mtu, i_mtu ); p_config->i_mtu = i_mtu; } return true; }
static int GenericOpen( demux_t *p_demux, const char *psz_module, vlc_fourcc_t i_codec, int(*pf_probe)(const uint8_t *, size_t, void *), void *p_ctx, const char **pp_psz_exts, const char **pp_psz_mimes ) { demux_sys_t *p_sys; const uint8_t *p_peek; es_format_t fmt; uint8_t annexb_startcode[] = {0,0,0,1}; int i_ret = 0; /* Restrict by type first */ if( !p_demux->obj.force && !check_Property( p_demux, pp_psz_exts, demux_IsPathExtension ) && !check_Property( p_demux, pp_psz_mimes, demux_IsContentType ) ) { return VLC_EGENERIC; } /* First check for first AnnexB header */ if( vlc_stream_Peek( p_demux->s, &p_peek, H26X_MIN_PEEK ) == H26X_MIN_PEEK && !memcmp( p_peek, annexb_startcode, 4 ) ) { size_t i_peek = H26X_MIN_PEEK; size_t i_peek_target = H26X_MIN_PEEK; size_t i_probe_offset = 4; const uint8_t *p_probe = p_peek; bool b_synced = true; unsigned i_bitflow = 0; for( unsigned i=0; i<H26X_NAL_COUNT; i++ ) { while( !b_synced ) { if( i_probe_offset + H26X_MIN_PEEK >= i_peek && i_peek_target + H26X_PEEK_CHUNK <= H26X_MAX_PEEK ) { i_peek_target += H26X_PEEK_CHUNK; i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_peek_target ); } if( i_probe_offset + H26X_MIN_PEEK >= i_peek ) break; p_probe = &p_peek[i_probe_offset]; i_bitflow = (i_bitflow << 1) | (!p_probe[0]); /* Check for annexB */ if( p_probe[0] == 0x01 && ((i_bitflow & 0x06) == 0x06) ) b_synced = true; i_probe_offset++; } if( b_synced ) { p_probe = &p_peek[i_probe_offset]; i_ret = pf_probe( p_probe, i_peek - i_probe_offset, p_ctx ); } if( i_ret != 0 ) break; i_probe_offset += 4; b_synced = false; } } if( i_ret < 1 ) { if( !p_demux->obj.force ) { msg_Warn( p_demux, "%s module discarded (no startcode)", psz_module ); return VLC_EGENERIC; } msg_Err( p_demux, "this doesn't look like a %s ES stream, " "continuing anyway", psz_module ); } p_demux->pf_demux = Demux; p_demux->pf_control= Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->p_es = NULL; p_sys->frame_rate_num = 0; p_sys->frame_rate_den = 0; float f_fps = 0; char *psz_fpsvar; if( asprintf( &psz_fpsvar, "%s-fps", psz_module ) ) { f_fps = var_CreateGetFloat( p_demux, psz_fpsvar ); free( psz_fpsvar ); } if( f_fps ) { if ( f_fps < 0.001f ) f_fps = 0.001f; p_sys->frame_rate_den = 1000; p_sys->frame_rate_num = 1000 * f_fps; date_Init( &p_sys->dts, p_sys->frame_rate_num, p_sys->frame_rate_den ); } else date_Init( &p_sys->dts, 25000, 1000 ); date_Set( &p_sys->dts, VLC_TS_0 ); /* Load the mpegvideo packetizer */ es_format_Init( &fmt, VIDEO_ES, i_codec ); p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, psz_module ); if( !p_sys->p_packetizer ) { free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }
static int vlclua_node_add_subitem( lua_State *L ) { services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L ); input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" ); if( *pp_node ) { if( lua_istable( L, -1 ) ) { lua_getfield( L, -1, "path" ); if( lua_isstring( L, -1 ) ) { const char *psz_path = lua_tostring( L, -1 ); /* The table must be at the top of the stack when calling * vlclua_read_options() */ char **ppsz_options = NULL; int i_options = 0; lua_pushvalue( L, -2 ); vlclua_read_options( p_sd, L, &i_options, &ppsz_options ); input_item_t *p_input = input_item_NewExt( psz_path, psz_path, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED, -1 ); lua_pop( L, 2 ); if( p_input ) { input_item_node_t *p_input_node = input_item_node_Create( *pp_node ); vlclua_read_meta_data( p_sd, L, p_input ); /* This one is to be tested... */ vlclua_read_custom_meta_data( p_sd, L, p_input ); lua_getfield( L, -1, "duration" ); if( lua_isnumber( L, -1 ) ) input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) ); else if( !lua_isnil( L, -1 ) ) msg_Warn( p_sd, "Item duration should be a number (in seconds)." ); lua_pop( L, 1 ); input_item_node_AppendItem( p_input_node, p_input ); input_item_node_PostAndDelete( p_input_node ); input_item_t **udata = (input_item_t **) lua_newuserdata( L, sizeof( input_item_t * ) ); *udata = p_input; if( luaL_newmetatable( L, "input_item_t" ) ) { lua_newtable( L ); luaL_register( L, NULL, vlclua_item_reg ); lua_setfield( L, -2, "__index" ); lua_pushliteral( L, "none of your business" ); lua_setfield( L, -2, "__metatable" ); } lua_setmetatable( L, -2 ); vlc_gc_decref( p_input ); } while( i_options > 0 ) free( ppsz_options[--i_options] ); free( ppsz_options ); } else msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" ); } else msg_Err( p_sd, "Error parsing add_subitem arguments" ); } return 1; }
void VLMDialog::addVLMItem() { int vlmItemCount = vlmItems.count(); /* Take the name and Check it */ QString name = ui.nameLedit->text(); if( name.isEmpty() || !isNameGenuine( name ) ) { msg_Err( p_intf, "VLM Name is empty or already exists, I can't do it" ); return; } int type = ui.mediaType->itemData( ui.mediaType->currentIndex() ).toInt(); QString typeShortName; QString inputText = ui.inputLedit->text(); QString outputText = ui.outputLedit->text(); bool b_checked = ui.enableCheck->isChecked(); bool b_looped = ui.loopBCast->isChecked(); QDateTime schetime = time->dateTime(); QDateTime schedate = date->dateTime(); int repeatnum = scherepeatnumber->value(); int repeatdays = repeatDays->value(); VLMAWidget * vlmAwidget; outputText.remove( ":sout=" ); switch( type ) { case QVLM_Broadcast: typeShortName = "Bcast"; vlmAwidget = new VLMBroadcast( name, inputText, inputOptions, outputText, b_checked, b_looped, this ); VLMWrapper::AddBroadcast( name, inputText, inputOptions, outputText, b_checked, b_looped ); break; case QVLM_VOD: typeShortName = "VOD"; vlmAwidget = new VLMVod( name, inputText, inputOptions, outputText, b_checked, ui.muxLedit->text(), this ); VLMWrapper::AddVod( name, inputText, inputOptions, outputText, b_checked ); break; case QVLM_Schedule: typeShortName = "Sched"; vlmAwidget = new VLMSchedule( name, inputText, inputOptions, outputText, schetime, schedate, repeatnum, repeatdays, b_checked, this ); VLMWrapper::AddSchedule( name, inputText, inputOptions, outputText, schetime, schedate, repeatnum, repeatdays, b_checked); break; default: msg_Warn( p_intf, "Something bad happened" ); return; } /* Add an Item of the Side List */ ui.vlmListItem->addItem( typeShortName + " : " + name ); ui.vlmListItem->setCurrentRow( vlmItemCount - 1 ); /* Add a new VLMAWidget on the main List */ vlmItemLayout->insertWidget( vlmItemCount, vlmAwidget ); vlmItems.append( vlmAwidget ); clearWidgets(); }
/***************************************************************************** * Win32VoutCreateWindow: create a window for the video. ***************************************************************************** * Before creating a direct draw surface, we need to create a window in which * the video will be displayed. This window will also allow us to capture the * events. *****************************************************************************/ static int Win32VoutCreateWindow( event_thread_t *p_event ) { vout_display_t *vd = p_event->vd; HINSTANCE hInstance; HMENU hMenu; RECT rect_window; WNDCLASS wc; /* window class components */ TCHAR vlc_path[MAX_PATH+1]; int i_style, i_stylex; msg_Dbg( vd, "Win32VoutCreateWindow" ); /* Get this module's instance */ hInstance = GetModuleHandle(NULL); #ifdef MODULE_NAME_IS_direct3d if( !p_event->use_desktop ) { #endif /* If an external window was specified, we'll draw in it. */ p_event->parent_window = vout_display_NewWindow(vd, &p_event->wnd_cfg ); if( p_event->parent_window ) p_event->hparent = (HWND) p_event->parent_window->handle.hwnd; // sunqueen modify else p_event->hparent = NULL; #ifdef MODULE_NAME_IS_direct3d } else { p_event->parent_window = NULL; p_event->hparent = GetDesktopHandle(vd); } #endif p_event->cursor_arrow = LoadCursor(NULL, IDC_ARROW); p_event->cursor_empty = EmptyCursor(hInstance); /* Get the Icon from the main app */ p_event->vlc_icon = NULL; if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) ) { p_event->vlc_icon = ExtractIcon( hInstance, vlc_path, 0 ); } /* Fill in the window class structure */ wc.style = CS_OWNDC|CS_DBLCLKS; /* style: dbl click */ wc.lpfnWndProc = (WNDPROC)WinVoutEventProc; /* event handler */ wc.cbClsExtra = 0; /* no extra class data */ wc.cbWndExtra = 0; /* no extra window data */ wc.hInstance = hInstance; /* instance */ wc.hIcon = p_event->vlc_icon; /* load the vlc big icon */ wc.hCursor = p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); /* background color */ // sunqueen modify wc.lpszMenuName = NULL; /* no menu */ wc.lpszClassName = p_event->class_main; /* use a special class */ /* Register the window class */ if( !RegisterClass(&wc) ) { if( p_event->vlc_icon ) DestroyIcon( p_event->vlc_icon ); msg_Err( vd, "Win32VoutCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() ); return VLC_EGENERIC; } /* Register the video sub-window class */ wc.lpszClassName = p_event->class_video; wc.hIcon = 0; wc.hbrBackground = NULL; /* no background color */ if( !RegisterClass(&wc) ) { msg_Err( vd, "Win32VoutCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() ); return VLC_EGENERIC; } /* When you create a window you give the dimensions you wish it to * have. Unfortunatly these dimensions will include the borders and * titlebar. We use the following function to find out the size of * the window corresponding to the useable surface we want */ rect_window.left = 10; rect_window.top = 10; rect_window.right = rect_window.left + p_event->wnd_cfg.width; rect_window.bottom = rect_window.top + p_event->wnd_cfg.height; if( var_GetBool( vd, "video-deco" ) ) { /* Open with window decoration */ AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 ); i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN; i_stylex = 0; } else { /* No window decoration */ AdjustWindowRect( &rect_window, WS_POPUP, 0 ); i_style = WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN; i_stylex = 0; // WS_EX_TOOLWINDOW; Is TOOLWINDOW really needed ? // It messes up the fullscreen window. } if( p_event->hparent ) { i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD; i_stylex = 0; /* allow user to regain control over input events if requested */ bool b_mouse_support = var_InheritBool( vd, "mouse-events" ); bool b_key_support = var_InheritBool( vd, "keyboard-events" ); if( !b_mouse_support && !b_key_support ) i_style |= WS_DISABLED; } p_event->i_window_style = i_style; /* Create the window */ p_event->hwnd = CreateWindowEx( WS_EX_NOPARENTNOTIFY | i_stylex, p_event->class_main, /* name of window class */ _T(VOUT_TITLE) _T(" (VLC Video Output)"), /* window title */ i_style, /* window style */ (!p_event->wnd_cfg.x) ? (UINT)CW_USEDEFAULT : (UINT)p_event->wnd_cfg.x, /* default X coordinate */ (!p_event->wnd_cfg.y) ? (UINT)CW_USEDEFAULT : (UINT)p_event->wnd_cfg.y, /* default Y coordinate */ rect_window.right - rect_window.left, /* window width */ rect_window.bottom - rect_window.top, /* window height */ p_event->hparent, /* parent window */ NULL, /* no menu in this window */ hInstance, /* handle of this program instance */ (LPVOID)p_event ); /* send vd to WM_CREATE */ if( !p_event->hwnd ) { msg_Warn( vd, "Win32VoutCreateWindow create window FAILED (err=%lu)", GetLastError() ); return VLC_EGENERIC; } InitGestures( p_event->hwnd, &p_event->p_gesture ); if( p_event->hparent ) { LONG i_style; /* We don't want the window owner to overwrite our client area */ i_style = GetWindowLong( p_event->hparent, GWL_STYLE ); if( !(i_style & WS_CLIPCHILDREN) ) /* Hmmm, apparently this is a blocking call... */ SetWindowLong( p_event->hparent, GWL_STYLE, i_style | WS_CLIPCHILDREN ); /* Create our fullscreen window */ p_event->hfswnd = CreateWindowEx( WS_EX_APPWINDOW, p_event->class_main, _T(VOUT_TITLE) _T(" (VLC Fullscreen Video Output)"), WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_SIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); } else { p_event->hfswnd = NULL; } /* Append a "Always On Top" entry in the system menu */ hMenu = GetSystemMenu( p_event->hwnd, FALSE ); AppendMenu( hMenu, MF_SEPARATOR, 0, _T("") ); AppendMenu( hMenu, MF_STRING | MF_UNCHECKED, IDM_TOGGLE_ON_TOP, _T("Always on &Top") ); /* Create video sub-window. This sub window will always exactly match * the size of the video, which allows us to use crazy overlay colorkeys * without having them shown outside of the video area. */ /* FIXME vd->source.i_width/i_height seems wrong */ p_event->hvideownd = CreateWindow( p_event->class_video, _T(""), /* window class */ WS_CHILD, /* window style, not visible initially */ 0, 0, vd->source.i_width, /* default width */ vd->source.i_height, /* default height */ p_event->hwnd, /* parent window */ NULL, hInstance, (LPVOID)p_event ); /* send vd to WM_CREATE */ if( !p_event->hvideownd ) msg_Warn( vd, "can't create video sub-window" ); else msg_Dbg( vd, "created video sub-window" ); /* Now display the window */ ShowWindow( p_event->hwnd, SW_SHOW ); return VLC_SUCCESS; }
/***************************************************************************** * VideoWindow::_AllocateBuffers *****************************************************************************/ status_t VideoWindow::_AllocateBuffers(int width, int height, int* mode) { // clear any old buffers _FreeBuffers(); // set default mode *mode = BITMAP; bitmap_count = 3; BRect bitmapFrame( 0, 0, width, height ); // read from config, if we are supposed to use overlay at all int noOverlay = !config_GetInt( p_vout, "overlay" ); /* Test for overlay capability: for every chroma in colspace, we try to do double-buffered overlay, single-buffered overlay or basic overlay. If nothing worked, we then have to work with a non-overlay BBitmap. */ for( int i = 0; i < COLOR_COUNT; i++ ) { if( noOverlay ) break; bitmap[0] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, colspace[i].colspace ); if( bitmap[0] && bitmap[0]->InitCheck() == B_OK ) { colspace_index = i; *mode = OVERLAY; rgb_color key; view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(), view->Bounds(), &key, B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL ); view->SetViewColor( key ); SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" ); bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY, colspace[colspace_index].colspace); if( bitmap[1] && bitmap[1]->InitCheck() == B_OK ) { bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY, colspace[colspace_index].colspace); if( bitmap[2] && bitmap[2]->InitCheck() == B_OK ) { msg_Dbg( p_vout, "using double-buffered overlay" ); } else { msg_Dbg( p_vout, "using single-buffered overlay" ); bitmap_count = 2; if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; } } } else { msg_Dbg( p_vout, "using simple overlay" ); bitmap_count = 1; if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; } } break; } else { if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; } } } if (*mode == BITMAP) { msg_Warn( p_vout, "no possible overlay" ); // fallback to RGB colspace_index = DEFAULT_COL; // B_RGB32 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace ); bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace ); bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace ); SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" ); } // see if everything went well status_t status = B_ERROR; for (int32_t i = 0; i < bitmap_count; i++) { if (bitmap[i]) status = bitmap[i]->InitCheck(); if (status < B_OK) break; } if (status >= B_OK) { // clear bitmaps to black for (int32_t i = 0; i < bitmap_count; i++) _BlankBitmap(bitmap[i]); } return status; }
/** * Non-MIDI Meta events handler */ static int HandleMeta (demux_t *p_demux, mtrk_t *tr) { stream_t *s = p_demux->s; demux_sys_t *p_sys = p_demux->p_sys; uint8_t *payload; uint8_t type; int32_t length; int ret = 0; if (stream_Read (s, &type, 1) != 1) return -1; length = ReadVarInt (s); if (length < 0) return -1; payload = malloc (length + 1); if ((payload == NULL) || (stream_Read (s, payload, length) != length)) { free (payload); return -1; } payload[length] = '\0'; switch (type) { case 0x00: /* Sequence Number */ break; case 0x01: /* Text (comment) */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Text : %s", (char *)payload); break; case 0x02: /* Copyright */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Copyright : %s", (char *)payload); break; case 0x03: /* Track name */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Track name: %s", (char *)payload); break; case 0x04: /* Instrument name */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Instrument: %s", (char *)payload); break; case 0x05: /* Lyric (one syllable) */ /*EnsureUTF8 ((char *)payload);*/ break; case 0x06: /* Marker text */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Marker : %s", (char *)payload); case 0x07: /* Cue point (WAVE filename) */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Cue point : %s", (char *)payload); break; case 0x08: /* Program/Patch name */ EnsureUTF8 ((char *)payload); msg_Info (p_demux, "Patch name: %s", (char *)payload); break; case 0x09: /* MIDI port name */ EnsureUTF8 ((char *)payload); msg_Dbg (p_demux, "MIDI port : %s", (char *)payload); break; case 0x2F: /* End of track */ if (tr->start + tr->length != stream_Tell (s)) { msg_Err (p_demux, "misplaced end of track"); ret = -1; } break; case 0x51: /* Tempo */ if (length == 3) { uint32_t uspqn = (payload[0] << 16) | (payload[1] << 8) | payload[2]; unsigned tempo = 60 * 1000000 / (uspqn ? uspqn : 1); msg_Dbg (p_demux, "tempo: %uus/qn -> %u BPM", (unsigned)uspqn, tempo); if (tempo < TEMPO_MIN) { msg_Warn (p_demux, "tempo too slow -> %u BPM", TEMPO_MIN); tempo = TEMPO_MIN; } else if (tempo > TEMPO_MAX) { msg_Warn (p_demux, "tempo too fast -> %u BPM", TEMPO_MAX); tempo = TEMPO_MAX; } date_Change (&p_sys->pts, p_sys->ppqn * tempo, 60); } else ret = -1; break; case 0x54: /* SMPTE offset */ if (length == 5) msg_Warn (p_demux, "SMPTE offset not implemented"); else ret = -1; break; case 0x58: /* Time signature */ if (length == 4) ; else ret = -1; break; case 0x59: /* Key signature */ if (length == 2) ; else ret = -1; break; case 0x7f: /* Proprietary event */ msg_Dbg (p_demux, "ignored proprietary SMF Meta Event (%d bytes)", length); break; default: msg_Warn (p_demux, "unknown SMF Meta Event type 0x%02X (%d bytes)", type, length); } free (payload); return ret; }
/***************************************************************************** * EventThread: Create video window & handle its messages ***************************************************************************** * This function creates a video window and then enters an infinite loop * that handles the messages sent to that window. * The main goal of this thread is to isolate the Win32 PeekMessage function * because this one can block for a long time. *****************************************************************************/ static void *EventThread( void *p_this ) { event_thread_t *p_event = (event_thread_t *)p_this; vout_display_t *vd = p_event->vd; MSG msg; POINT old_mouse_pos = {0,0}, mouse_pos; int canc = vlc_savecancel (); bool b_mouse_support = var_InheritBool( p_event->vd, "mouse-events" ); bool b_key_support = var_InheritBool( p_event->vd, "keyboard-events" ); vlc_mutex_lock( &p_event->lock ); /* Create a window for the video */ /* Creating a window under Windows also initializes the thread's event * message queue */ if( Win32VoutCreateWindow( p_event ) ) p_event->b_error = true; p_event->b_ready = true; vlc_cond_signal( &p_event->wait ); const bool b_error = p_event->b_error; vlc_mutex_unlock( &p_event->lock ); if( b_error ) { vlc_restorecancel( canc ); return NULL; } /* Prevent monitor from powering off */ if (var_GetBool(vd, "disable-screensaver")) SetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED | ES_CONTINUOUS ); /* Main loop */ /* GetMessage will sleep if there's no message in the queue */ for( ;; ) { vout_display_place_t place; video_format_t source; if( !GetMessage( &msg, 0, 0, 0 ) ) { vlc_mutex_lock( &p_event->lock ); p_event->b_done = true; vlc_mutex_unlock( &p_event->lock ); break; } /* Check if we are asked to exit */ vlc_mutex_lock( &p_event->lock ); const bool b_done = p_event->b_done; vlc_mutex_unlock( &p_event->lock ); if( b_done ) break; if( !b_mouse_support && isMouseEvent( msg.message ) ) continue; if( !b_key_support && isKeyEvent( msg.message ) ) continue; /* Handle mouse state */ if( msg.message == WM_MOUSEMOVE || msg.message == WM_NCMOUSEMOVE ) { GetCursorPos( &mouse_pos ); /* FIXME, why this >2 limits ? */ if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 || (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) ) { old_mouse_pos = mouse_pos; UpdateCursor( p_event, true ); } } else if( isMouseEvent( msg.message ) ) { UpdateCursor( p_event, true ); } else if( msg.message == WM_VLC_HIDE_MOUSE ) { UpdateCursor( p_event, false ); } /* */ switch( msg.message ) { case WM_MOUSEMOVE: vlc_mutex_lock( &p_event->lock ); place = p_event->place; source = p_event->source; vlc_mutex_unlock( &p_event->lock ); if( place.width > 0 && place.height > 0 ) { if( msg.hwnd == p_event->hvideownd ) { /* Child window */ place.x = 0; place.y = 0; } const int x = source.i_x_offset + (int64_t)(GET_X_LPARAM(msg.lParam) - place.x) * source.i_width / place.width; const int y = source.i_y_offset + (int64_t)(GET_Y_LPARAM(msg.lParam) - place.y) * source.i_height / place.height; vout_display_SendEventMouseMoved(vd, x, y); } break; case WM_NCMOUSEMOVE: break; case WM_VLC_HIDE_MOUSE: break; case WM_LBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONDBLCLK: vout_display_SendEventMouseDoubleClick(vd); break; case WM_MBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_CENTER ); break; case WM_MBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_CENTER ); break; case WM_RBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_RIGHT ); break; case WM_RBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_RIGHT ); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { /* The key events are first processed here and not translated * into WM_CHAR events because we need to know the status of the * modifier keys. */ int i_key = Win32VoutConvertKey( msg.wParam ); if( !i_key ) { /* This appears to be a "normal" (ascii) key */ i_key = tolower( (unsigned char)MapVirtualKey( msg.wParam, 2 ) ); } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_MOUSEWHEEL: { int i_key; if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 ) { i_key = KEY_MOUSEWHEELUP; } else { i_key = KEY_MOUSEWHEELDOWN; } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_VLC_CHANGE_TEXT: { vlc_mutex_lock( &p_event->lock ); wchar_t *pwz_title = NULL; if( p_event->psz_title ) { const size_t i_length = strlen(p_event->psz_title); pwz_title = (wchar_t *)malloc( 2 * (i_length + 1) ); // sunqueen modify if( pwz_title ) { mbstowcs( pwz_title, p_event->psz_title, 2 * i_length ); pwz_title[i_length] = 0; } } vlc_mutex_unlock( &p_event->lock ); if( pwz_title ) { SetWindowTextW( p_event->hwnd, pwz_title ); if( p_event->hfswnd ) SetWindowTextW( p_event->hfswnd, pwz_title ); free( pwz_title ); } break; } default: /* Messages we don't handle directly are dispatched to the * window procedure */ TranslateMessage(&msg); DispatchMessage(&msg); break; } /* End Switch */ } /* End Main loop */ /* Check for WM_QUIT if we created the window */ if( !p_event->hparent && msg.message == WM_QUIT ) { msg_Warn( vd, "WM_QUIT... should not happen!!" ); p_event->hwnd = NULL; /* Window already destroyed */ } msg_Dbg( vd, "Win32 Vout EventThread terminating" ); Win32VoutCloseWindow( p_event ); vlc_restorecancel(canc); return NULL; }
static int Open(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t*)p_this; vout_display_sys_t *sys; video_format_t sub_fmt; if (vout_display_IsWindowed(vd)) return VLC_EGENERIC; /* Allocate structure */ vd->sys = sys = (struct vout_display_sys_t*)calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->p_awh = AWindowHandler_new(p_this); if (!sys->p_awh) { free(sys); msg_Err(vd, "AWindowHandler_new failed"); return VLC_EGENERIC; } sys->anw = AWindowHandler_getANativeWindowAPI(sys->p_awh); #ifdef USE_ANWP sys->anwp = AWindowHandler_getANativeWindowPrivAPI(sys->p_awh); if (!sys->anwp) msg_Warn(vd, "Could not initialize NativeWindow Priv API."); #endif sys->i_display_width = vd->cfg->display.width; sys->i_display_height = vd->cfg->display.height; if (vd->fmt.i_chroma != VLC_CODEC_ANDROID_OPAQUE) { /* Setup chroma */ char *psz_fcc = var_InheritString(vd, CFG_PREFIX "chroma"); if (psz_fcc) { vd->fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_fcc); free(psz_fcc); } else vd->fmt.i_chroma = VLC_CODEC_RGB32; switch(vd->fmt.i_chroma) { case VLC_CODEC_YV12: /* avoid swscale usage by asking for I420 instead since the * vout already has code to swap the buffers */ vd->fmt.i_chroma = VLC_CODEC_I420; case VLC_CODEC_I420: break; case VLC_CODEC_RGB16: case VLC_CODEC_RGB32: case VLC_CODEC_RGBA: SetRGBMask(&vd->fmt); video_format_FixRgb(&vd->fmt); break; default: goto error; } } sys->p_window = AndroidWindow_New(vd, &vd->fmt, AWindow_Video, true); if (!sys->p_window) goto error; if (AndroidWindow_Setup(sys, sys->p_window, 0) != 0) goto error; /* use software rotation if we don't use private anw */ if (!sys->p_window->b_opaque && !sys->p_window->b_use_priv) video_format_ApplyRotation(&vd->fmt, &vd->fmt); msg_Dbg(vd, "using %s", sys->p_window->b_opaque ? "opaque" : (sys->p_window->b_use_priv ? "ANWP" : "ANW")); video_format_ApplyRotation(&sub_fmt, &vd->fmt); sub_fmt.i_chroma = subpicture_chromas[0]; SetRGBMask(&sub_fmt); video_format_FixRgb(&sub_fmt); sys->p_sub_window = AndroidWindow_New(vd, &sub_fmt, AWindow_Subtitles, false); if (sys->p_sub_window) { FixSubtitleFormat(sys); sys->i_sub_last_order = -1; /* Export the subpicture capability of this vout. */ vd->info.subpicture_chromas = subpicture_chromas; } /* Setup vout_display */ vd->pool = Pool; vd->prepare = Prepare; vd->display = Display; vd->control = Control; vd->manage = Manage; /* Fix initial state */ vout_display_SendEventFullscreen(vd, true); SendEventDisplaySize(vd); return VLC_SUCCESS; error: Close(p_this); return VLC_ENOMEM; }
static int Control(vout_display_t *vd, int query, va_list args) { vout_display_sys_t *sys = vd->sys; switch (query) { case VOUT_DISPLAY_HIDE_MOUSE: case VOUT_DISPLAY_CHANGE_FULLSCREEN: return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: { if (sys->p_window->b_opaque) return VLC_EGENERIC; msg_Dbg(vd, "resetting pictures"); if (sys->pool != NULL) { picture_pool_Release(sys->pool); sys->pool = NULL; } return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_SOURCE_CROP: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) { const video_format_t *source; msg_Dbg(vd, "change source crop/aspect"); source = va_arg(args, const video_format_t *); if (query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) { video_format_CopyCrop(&sys->p_window->fmt, source); AndroidWindow_UpdateCrop(sys, sys->p_window); } else CopySourceAspect(&sys->p_window->fmt, source); UpdateWindowSize(sys, &sys->p_window->fmt, sys->p_window->b_use_priv); } else { const vout_display_cfg_t *cfg; cfg = va_arg(args, const vout_display_cfg_t *); sys->i_display_width = cfg->display.width; sys->i_display_height = cfg->display.height; msg_Dbg(vd, "change display size: %dx%d", sys->i_display_width, sys->i_display_height); } FixSubtitleFormat(sys); return VLC_SUCCESS; } default: msg_Warn(vd, "Unknown request in android_window"); case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: return VLC_EGENERIC; }
/** * Reads ACL entries from a file. * * @param p_acl ACL object in which to insert parsed entries. * @param psz_patch filename from which to parse entries. * * @return 0 on success, -1 on error. */ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) { FILE *file; if( p_acl == NULL ) return -1; file = utf8_fopen( psz_path, "r" ); if( file == NULL ) return -1; msg_Dbg( p_acl->p_owner, "find .hosts in dir=%s", psz_path ); while( !feof( file ) ) { char line[1024], *psz_ip, *ptr; if( fgets( line, sizeof( line ), file ) == NULL ) { if( ferror( file ) ) { msg_Err( p_acl->p_owner, "error reading %s : %m", psz_path ); goto error; } continue; } /* fgets() is cool : never overflow, always nul-terminate */ psz_ip = line; /* skips blanks - cannot overflow given '\0' is not space */ while( isspace( *psz_ip ) ) psz_ip++; if( *psz_ip == '\0' ) /* empty/blank line */ continue; ptr = strchr( psz_ip, '\n' ); if( ptr == NULL ) { msg_Warn( p_acl->p_owner, "skipping overly long line in %s", psz_path); do { if( fgets( line, sizeof( line ), file ) == NULL ) { if( ferror( file ) ) { msg_Err( p_acl->p_owner, "error reading %s : %m", psz_path ); } goto error; } } while( strchr( line, '\n' ) == NULL); continue; /* skip unusable line */ } /* skips comment-only line */ if( *psz_ip == '#' ) continue; /* looks for first space, CR, LF, etc. or end-of-line comment */ /* (there is at least a linefeed) */ for( ptr = psz_ip; ( *ptr != '#' ) && !isspace( *ptr ); ptr++ ); *ptr = '\0'; msg_Dbg( p_acl->p_owner, "restricted to %s", psz_ip ); ptr = strchr( psz_ip, '/' ); if( ptr != NULL ) *ptr++ = '\0'; /* separate address from mask length */ if( (ptr != NULL) ? ACL_AddNet( p_acl, psz_ip, atoi( ptr ), true ) : ACL_AddHost( p_acl, psz_ip, true ) ) { msg_Err( p_acl->p_owner, "cannot add ACL from %s", psz_path ); continue; } } fclose( file ); return 0; error: fclose( file ); return -1; }
/***************************************************************************** * Open: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *) p_this; decoder_sys_t *p_sys = NULL; if( p_dec->fmt_in.i_codec != VLC_CODEC_TELETEXT ) return VLC_EGENERIC; int i_page = var_CreateGetInteger( p_dec, "vbi-page" ); if( i_page > 999 ) { msg_Warn( p_dec, "invalid vbi-page requested"); i_page = 0; } p_sys = p_dec->p_sys = calloc( 1, sizeof(decoder_sys_t) ); if( p_sys == NULL ) return VLC_ENOMEM; p_sys->i_key[0] = p_sys->i_key[1] = p_sys->i_key[2] = '*' - '0'; p_sys->b_update = false; p_sys->p_vbi_dec = vbi_decoder_new(); vlc_mutex_init( &p_sys->lock ); if( p_sys->p_vbi_dec == NULL ) { msg_Err( p_dec, "VBI decoder could not be created." ); Close( p_this ); return VLC_ENOMEM; } /* Some broadcasters in countries with level 1 and level 1.5 still not send a G0 to do * matches against table 32 of ETSI 300 706. We try to do some best effort guessing * This is not perfect, but might handle some cases where we know the vbi language * is known. It would be better if people started sending G0 */ for( int i = 0; ppsz_default_triplet[i] != NULL; i++ ) { if( p_dec->fmt_in.psz_language && !strcasecmp( p_dec->fmt_in.psz_language, ppsz_default_triplet[i] ) ) { vbi_teletext_set_default_region( p_sys->p_vbi_dec, pi_default_triplet[i]); msg_Dbg( p_dec, "overwriting default zvbi region: %d", pi_default_triplet[i] ); } } vbi_event_handler_register( p_sys->p_vbi_dec, VBI_EVENT_TTX_PAGE | VBI_EVENT_NETWORK | #ifdef ZVBI_DEBUG VBI_EVENT_CAPTION | VBI_EVENT_TRIGGER | VBI_EVENT_ASPECT | VBI_EVENT_PROG_INFO | VBI_EVENT_NETWORK_ID | #endif 0 , EventHandler, p_dec ); /* Create the var on vlc_global. */ p_sys->i_wanted_page = i_page; var_AddCallback( p_dec, "vbi-page", RequestPage, p_sys ); /* Check if the Teletext track has a known "initial page". */ if( p_sys->i_wanted_page == 100 && p_dec->fmt_in.subs.teletext.i_magazine != -1 ) { p_sys->i_wanted_page = 100 * p_dec->fmt_in.subs.teletext.i_magazine + vbi_bcd2dec( p_dec->fmt_in.subs.teletext.i_page ); var_SetInteger( p_dec, "vbi-page", p_sys->i_wanted_page ); } p_sys->i_wanted_subpage = VBI_ANY_SUBNO; p_sys->b_opaque = var_CreateGetBool( p_dec, "vbi-opaque" ); var_AddCallback( p_dec, "vbi-opaque", Opaque, p_sys ); p_sys->i_align = var_CreateGetInteger( p_dec, "vbi-position" ); p_sys->b_text = var_CreateGetBool( p_dec, "vbi-text" ); p_sys->i_level = var_CreateGetInteger( p_dec, "vbi-level" ); p_dec->fmt_out.i_codec = p_sys->b_text ? VLC_CODEC_TEXT : VLC_CODEC_RGBA; p_dec->pf_decode = Decode; return VLC_SUCCESS; }
/** * It creates a Direct3D device and the associated resources. */ static int Direct3DOpen(vout_display_t *vd, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; LPDIRECT3D9 d3dobj = sys->d3dobj; if (Direct3DFillPresentationParameters(vd)) return VLC_EGENERIC; // Create the D3DDevice LPDIRECT3DDEVICE9 d3ddev; UINT AdapterToUse = D3DADAPTER_DEFAULT; D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL; #ifndef NDEBUG // Look for 'NVIDIA PerfHUD' adapter // If it is present, override default settings for (UINT Adapter=0; Adapter< IDirect3D9_GetAdapterCount(d3dobj); ++Adapter) { D3DADAPTER_IDENTIFIER9 Identifier; HRESULT Res = IDirect3D9_GetAdapterIdentifier(d3dobj,Adapter,0,&Identifier); if (SUCCEEDED(Res) && strstr(Identifier.Description,"PerfHUD") != 0) { AdapterToUse = Adapter; DeviceType = D3DDEVTYPE_REF; break; } } #endif /* */ D3DADAPTER_IDENTIFIER9 d3dai; if (FAILED(IDirect3D9_GetAdapterIdentifier(d3dobj,AdapterToUse,0, &d3dai))) { msg_Warn(vd, "IDirect3D9_GetAdapterIdentifier failed"); } else { msg_Dbg(vd, "Direct3d Device: %s %lu %lu %lu", d3dai.Description, d3dai.VendorId, d3dai.DeviceId, d3dai.Revision ); } HRESULT hr = IDirect3D9_CreateDevice(d3dobj, AdapterToUse, DeviceType, sys->hvideownd, D3DCREATE_SOFTWARE_VERTEXPROCESSING| D3DCREATE_MULTITHREADED, &sys->d3dpp, &d3ddev); if (FAILED(hr)) { msg_Err(vd, "Could not create the D3D device! (hr=0x%lX)", hr); return VLC_EGENERIC; } sys->d3ddev = d3ddev; UpdateRects(vd, NULL, NULL, true); if (Direct3DCreateResources(vd, fmt)) { msg_Err(vd, "Failed to allocate resources"); return VLC_EGENERIC; } /* Change the window title bar text */ EventThreadUpdateTitle(sys->event, VOUT_TITLE " (Direct3D output)"); msg_Dbg(vd, "Direct3D device adapter successfully initialized"); return VLC_SUCCESS; }
static int vlclua_sd_add_item( lua_State *L ) { services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L ); if( lua_istable( L, -1 ) ) { lua_getfield( L, -1, "path" ); if( lua_isstring( L, -1 ) ) { const char *psz_path = lua_tostring( L, -1 ); lua_getfield( L, -2, "title" ); const char *psz_title = luaL_checkstring( L, -1 ) ? luaL_checkstring( L, -1 ) : psz_path; /* The table must be at the top of the stack when calling * vlclua_read_options() */ char **ppsz_options = NULL; int i_options = 0; lua_pushvalue( L, -3 ); vlclua_read_options( p_sd, L, &i_options, &ppsz_options ); input_item_t *p_input = input_item_NewExt( psz_path, psz_title, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED, -1 ); lua_pop( L, 3 ); if( p_input ) { vlclua_read_meta_data( p_sd, L, p_input ); /* This one is to be tested... */ vlclua_read_custom_meta_data( p_sd, L, p_input ); /* The duration is given in seconds, convert to microseconds */ lua_getfield( L, -1, "duration" ); if( lua_isnumber( L, -1 ) ) input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) ); else if( !lua_isnil( L, -1 ) ) msg_Warn( p_sd, "Item duration should be a number (in seconds)." ); lua_pop( L, 1 ); lua_getfield( L, -1, "category" ); if( lua_isstring( L, -1 ) ) services_discovery_AddItem( p_sd, p_input, luaL_checkstring( L, -1 ) ); else services_discovery_AddItem( p_sd, p_input, NULL ); lua_pop( L, 1 ); /* string to build the input item uid */ lua_getfield( L, -1, "uiddata" ); if( lua_isstring( L, -1 ) ) { char *s = strdup( luaL_checkstring( L, -1 ) ); if ( s ) { struct md5_s md5; InitMD5( &md5 ); AddMD5( &md5, s, strlen( s ) ); EndMD5( &md5 ); free( s ); s = psz_md5_hash( &md5 ); if ( s ) input_item_AddInfo( p_input, "uid", "md5", "%s", s ); free( s ); } } lua_pop( L, 1 ); input_item_t **udata = (input_item_t **) lua_newuserdata( L, sizeof( input_item_t * ) ); *udata = p_input; if( luaL_newmetatable( L, "input_item_t" ) ) { lua_newtable( L ); luaL_register( L, NULL, vlclua_item_reg ); lua_setfield( L, -2, "__index" ); lua_pushliteral( L, "none of your business" ); lua_setfield( L, -2, "__metatable" ); } lua_setmetatable( L, -2 ); vlc_gc_decref( p_input ); } while( i_options > 0 ) free( ppsz_options[--i_options] ); free( ppsz_options ); } else msg_Err( p_sd, "vlc.sd.add_item: the \"path\" parameter can't be empty" ); } else msg_Err( p_sd, "Error parsing add_item arguments" ); return 1; }
/***************************************************************************** * ParseText: parse an text subtitle packet and send it to the video output *****************************************************************************/ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; char *psz_subtitle = NULL; if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) return NULL; /* We cannot display a subpicture with no date */ if( p_block->i_pts <= VLC_TS_INVALID ) { msg_Warn( p_dec, "subtitle without a date" ); return NULL; } /* Check validity of packet data */ /* An "empty" line containing only \0 can be used to force and ephemer picture from the screen */ if( p_block->i_buffer < 1 ) { msg_Warn( p_dec, "no subtitle data" ); return NULL; } /* Should be resiliant against bad subtitles */ psz_subtitle = malloc( p_block->i_buffer + 1 ); if( psz_subtitle == NULL ) return NULL; memcpy( psz_subtitle, p_block->p_buffer, p_block->i_buffer ); psz_subtitle[p_block->i_buffer] = '\0'; if( p_sys->iconv_handle == (vlc_iconv_t)-1 ) { if (EnsureUTF8( psz_subtitle ) == NULL) { msg_Err( p_dec, "failed to convert subtitle encoding.\n" "Try manually setting a character-encoding " "before you open the file." ); } } else { if( p_sys->b_autodetect_utf8 ) { if( IsUTF8( psz_subtitle ) == NULL ) { msg_Dbg( p_dec, "invalid UTF-8 sequence: " "disabling UTF-8 subtitles autodetection" ); p_sys->b_autodetect_utf8 = false; } } if( !p_sys->b_autodetect_utf8 ) { size_t inbytes_left = strlen( psz_subtitle ); size_t outbytes_left = 6 * inbytes_left; char *psz_new_subtitle = xmalloc( outbytes_left + 1 ); char *psz_convert_buffer_out = psz_new_subtitle; const char *psz_convert_buffer_in = psz_subtitle; size_t ret = vlc_iconv( p_sys->iconv_handle, &psz_convert_buffer_in, &inbytes_left, &psz_convert_buffer_out, &outbytes_left ); *psz_convert_buffer_out++ = '\0'; free( psz_subtitle ); if( ( ret == (size_t)(-1) ) || inbytes_left ) { free( psz_new_subtitle ); msg_Err( p_dec, "failed to convert subtitle encoding.\n" "Try manually setting a character-encoding " "before you open the file." ); return NULL; } psz_subtitle = realloc( psz_new_subtitle, psz_convert_buffer_out - psz_new_subtitle ); if( !psz_subtitle ) psz_subtitle = psz_new_subtitle; } } /* Create the subpicture unit */ p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { free( psz_subtitle ); return NULL; } p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align; p_spu_sys->p_segments = ParseSubtitles( &p_spu_sys->align, psz_subtitle ); free( psz_subtitle ); return p_spu; }
static void user_warning( png_structp p_png, png_const_charp warning_msg ) { png_sys_t *p_sys = (png_sys_t *)png_get_error_ptr( p_png ); msg_Warn( p_sys->p_obj, "%s", warning_msg ); }
static int Demux( demux_t *p_demux ) { char *psz_name = NULL; char *psz_line; char *psz_mrl = NULL; char *psz_mrl_orig = NULL; char *psz_key; char *psz_value; int i_item = -1; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); while( ( psz_line = stream_ReadLine( p_demux->s ) ) ) { if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) || !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) ) { free( psz_line ); continue; } psz_key = psz_line; psz_value = strchr( psz_line, '=' ); if( psz_value ) { *psz_value='\0'; psz_value++; } else { free( psz_line ); continue; } if( !strcasecmp( psz_key, "version" ) ) { msg_Dbg( p_demux, "pls file version: %s", psz_value ); free( psz_line ); continue; } if( !strcasecmp( psz_key, "numberofentries" ) ) { msg_Dbg( p_demux, "pls should have %d entries", atoi(psz_value) ); free( psz_line); continue; } /* find the number part of of file1, title1 or length1 etc */ int i_new_item; if( sscanf( psz_key, "%*[^0-9]%d", &i_new_item ) != 1 ) { msg_Warn( p_demux, "couldn't find number of items" ); free( psz_line ); continue; } if( i_item == -1 ) i_item = i_new_item; else if( i_item != i_new_item ) { /* we found a new item, insert the previous */ if( psz_mrl ) { p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_mrl_orig ); psz_mrl_orig = psz_mrl = NULL; } else { msg_Warn( p_demux, "no file= part found for item %d", i_item ); } free( psz_name ); psz_name = NULL; i_item = i_new_item; } if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) || !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) ) { free( psz_mrl_orig ); psz_mrl_orig = psz_mrl = ProcessMRL( psz_value, p_demux->p_sys->psz_prefix ); if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) ) { if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) ) memcpy( psz_mrl, "mmsh", 4 ); } } else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) ) { free( psz_name ); psz_name = strdup( psz_value ); } else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) ) /* duration in seconds */; else { msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key ); } free( psz_line ); } /* Add last object */ if( psz_mrl ) { p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_mrl_orig ); } else { msg_Warn( p_demux, "no file= part found for item %d", i_item ); } free( psz_name ); psz_name = NULL; input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); return 0; /* Needed for correct operation of go back */ }
VLMDialog::VLMDialog( intf_thread_t *_p_intf ) : QVLCDialog( (QWidget*)_p_intf->p_sys->p_mi, _p_intf ) { p_vlm = vlm_New( p_intf ); if( !p_vlm ) { msg_Warn( p_intf, "Couldn't build VLM object "); return; } vlmWrapper = new VLMWrapper( p_vlm ); // UI stuff ui.setupUi( this ); ui.saveButton->hide(); #define ADDMEDIATYPES( str, type ) ui.mediaType->addItem( qtr( str ), QVariant( type ) ); ADDMEDIATYPES( N_("Broadcast"), QVLM_Broadcast ); ADDMEDIATYPES( N_("Schedule"), QVLM_Schedule ); ADDMEDIATYPES( N_("Video On Demand ( VOD )"), QVLM_VOD ); #undef ADDMEDIATYPES /* Schedule Stuffs */ QGridLayout *schetimelayout = new QGridLayout( ui.schedBox ); QLabel *schetimelabel = new QLabel( qtr( "Hours / Minutes / Seconds:" ) ); schetimelayout->addWidget( schetimelabel, 0, 0 ); QLabel *schedatelabel = new QLabel( qtr( "Day / Month / Year:" ) ); schetimelayout->addWidget( schedatelabel, 1, 0 ); QLabel *scherepeatLabel = new QLabel( qtr( "Repeat:" ) ); schetimelayout->addWidget( scherepeatLabel, 2, 0 ); QLabel *scherepeatTimeLabel = new QLabel( qtr( "Repeat delay:" ) ); schetimelayout->addWidget( scherepeatTimeLabel, 3, 0 ); time = new QDateTimeEdit( QTime::currentTime() ); time->setAlignment( Qt::AlignRight ); time->setDisplayFormat( "hh:mm:ss" ); schetimelayout->addWidget( time, 0, 1, 1, 3 ); date = new QDateTimeEdit( QDate::currentDate() ); date->setAlignment( Qt::AlignRight ); date->setCalendarPopup( true ); #ifdef WIN32 date->setDisplayFormat( "dd MM yyyy" ); #else date->setDisplayFormat( "dd MMMM yyyy" ); #endif schetimelayout->addWidget( date, 1, 1, 1, 3 ); scherepeatnumber = new QSpinBox; scherepeatnumber->setAlignment( Qt::AlignRight ); schetimelayout->addWidget( scherepeatnumber, 2, 1, 1, 3 ); repeatDays = new QSpinBox; repeatDays->setAlignment( Qt::AlignRight ); schetimelayout->addWidget( repeatDays, 3, 1, 1, 1 ); repeatDays->setSuffix( qtr(" days") ); repeatTime = new QDateTimeEdit; repeatTime->setAlignment( Qt::AlignRight ); schetimelayout->addWidget( repeatTime, 3, 2, 1, 2 ); repeatTime->setDisplayFormat( "hh:mm:ss" ); /* scrollArea */ ui.vlmItemScroll->setFrameStyle( QFrame::NoFrame ); ui.vlmItemScroll->setWidgetResizable( true ); vlmItemWidget = new QWidget; vlmItemLayout = new QVBoxLayout( vlmItemWidget ); vlmItemWidget->setLayout( vlmItemLayout ); ui.vlmItemScroll->setWidget( vlmItemWidget ); QSpacerItem *spacer = new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); vlmItemLayout->addItem( spacer ); QPushButton *importButton = new QPushButton( qtr( "I&mport" ) ); ui.buttonBox->addButton( importButton, QDialogButtonBox::ActionRole ); QPushButton *exportButton = new QPushButton( qtr( "E&xport" ) ); ui.buttonBox->addButton( exportButton, QDialogButtonBox::ActionRole ); QPushButton *closeButton = new QPushButton( qtr( "&Close" ) ); ui.buttonBox->addButton( closeButton, QDialogButtonBox::RejectRole ); showScheduleWidget( QVLM_Broadcast ); /* Connect the comboBox to show the right Widgets */ CONNECT( ui.mediaType, currentIndexChanged( int ), this, showScheduleWidget( int ) ); /* Connect the leftList to show the good VLMItem */ CONNECT( ui.vlmListItem, currentRowChanged( int ), this, selectVLMItem( int ) ); BUTTONACT( closeButton, close() ); BUTTONACT( exportButton, exportVLMConf() ); BUTTONACT( importButton, importVLMConf() ); BUTTONACT( ui.addButton, addVLMItem() ); BUTTONACT( ui.clearButton, clearWidgets() ); BUTTONACT( ui.saveButton, saveModifications() ); BUTTONACT( ui.inputButton, selectInput() ); BUTTONACT( ui.outputButton, selectOutput() ); if( !restoreGeometry( getSettings()->value("VLM/geometry").toByteArray() ) ) { resize( QSize( 700, 500 ) ); } }
/** * Initialize a libvlc instance * This function initializes a previously allocated libvlc instance: * - CPU detection * - gettext initialization * - message queue, module bank and playlist initialization * - configuration and commandline parsing */ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, const char *ppsz_argv[] ) { libvlc_priv_t *priv = libvlc_priv (p_libvlc); char * psz_modules = NULL; char * psz_parser = NULL; char * psz_control = NULL; char *psz_val; /* System specific initialization code */ system_Init(); vlc_LogPreinit(p_libvlc); /* Initialize the module bank and load the configuration of the * core module. We need to do this at this stage to be able to display * a short help if required by the user. (short help == core module * options) */ module_InitBank (); /* Get command line options that affect module loading. */ if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, NULL ) ) { module_EndBank (false); return VLC_EGENERIC; } vlc_threads_setup (p_libvlc); /* Load the builtins and plugins into the module_bank. * We have to do it before config_Load*() because this also gets the * list of configuration options exported by each module and loads their * default values. */ size_t module_count = module_LoadPlugins (p_libvlc); /* * Override default configuration with config file settings */ if( !var_InheritBool( p_libvlc, "ignore-config" ) ) { if( var_InheritBool( p_libvlc, "reset-config" ) ) config_SaveConfigFile( p_libvlc ); /* Save default config */ else config_LoadConfigFile( p_libvlc ); } /* * Override configuration with command line settings */ int vlc_optind; if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, &vlc_optind ) ) { vlc_LogDeinit (p_libvlc); module_EndBank (true); return VLC_EGENERIC; } vlc_LogInit(p_libvlc); /* * Support for gettext */ #if defined( ENABLE_NLS ) \ && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) ) vlc_bindtextdomain (PACKAGE_NAME); #endif /*xgettext: Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */ msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") ); if (config_PrintHelp (VLC_OBJECT(p_libvlc))) { module_EndBank (true); exit(0); } if( module_count <= 1 ) { msg_Err( p_libvlc, "No plugins found! Check your VLC installation."); vlc_LogDeinit (p_libvlc); module_EndBank (true); return VLC_ENOMOD; } #ifdef HAVE_DAEMON /* Check for daemon mode */ if( var_InheritBool( p_libvlc, "daemon" ) ) { if( daemon( 1, 0) != 0 ) { msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" ); vlc_LogDeinit (p_libvlc); module_EndBank (true); return VLC_ENOMEM; } /* lets check if we need to write the pidfile */ char *pidfile = var_InheritString( p_libvlc, "pidfile" ); if( pidfile != NULL ) { FILE *stream = vlc_fopen( pidfile, "w" ); if( stream != NULL ) { fprintf( stream, "%d", (int)getpid() ); fclose( stream ); msg_Dbg( p_libvlc, "written PID file %s", pidfile ); } else msg_Err( p_libvlc, "cannot write PID file %s: %s", pidfile, vlc_strerror_c(errno) ); free( pidfile ); } } else { var_Create( p_libvlc, "pidfile", VLC_VAR_STRING ); var_SetString( p_libvlc, "pidfile", "" ); } #endif if( libvlc_InternalDialogInit( p_libvlc ) != VLC_SUCCESS ) { vlc_LogDeinit (p_libvlc); module_EndBank (true); return VLC_ENOMEM; } if( libvlc_InternalKeystoreInit( p_libvlc ) != VLC_SUCCESS ) msg_Warn( p_libvlc, "memory keystore init failed" ); /* FIXME: could be replaced by using Unix sockets */ #ifdef HAVE_DBUS #define MPRIS_APPEND "/org/mpris/MediaPlayer2/TrackList/Append" #define MPRIS_BUS_NAME "org.mpris.MediaPlayer2.vlc" #define MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2" #define MPRIS_TRACKLIST_INTERFACE "org.mpris.MediaPlayer2.TrackList" if( var_InheritBool( p_libvlc, "one-instance" ) || ( var_InheritBool( p_libvlc, "one-instance-when-started-from-file" ) && var_InheritBool( p_libvlc, "started-from-file" ) ) ) { for( int i = vlc_optind; i < i_argc; i++ ) if( ppsz_argv[i][0] == ':' ) { msg_Err( p_libvlc, "item option %s incompatible with single instance", ppsz_argv[i] ); goto dbus_out; } /* Initialise D-Bus interface, check for other instances */ dbus_threads_init_default(); DBusError err; dbus_error_init( &err ); /* connect to the session bus */ DBusConnection *conn = dbus_bus_get( DBUS_BUS_SESSION, &err ); if( conn == NULL ) { msg_Err( p_libvlc, "Failed to connect to D-Bus session daemon: %s", err.message ); dbus_error_free( &err ); goto dbus_out; } /* check if VLC is available on the bus * if not: D-Bus control is not enabled on the other * instance and we can't pass MRLs to it */ /* FIXME: This check is totally brain-dead and buggy. */ if( !dbus_bus_name_has_owner( conn, MPRIS_BUS_NAME, &err ) ) { dbus_connection_unref( conn ); if( dbus_error_is_set( &err ) ) { msg_Err( p_libvlc, "D-Bus error: %s", err.message ); } else msg_Dbg( p_libvlc, "No media player running. Continuing normally." ); dbus_error_free( &err ); goto dbus_out; } const dbus_bool_t play = !var_InheritBool( p_libvlc, "playlist-enqueue" ); msg_Warn( p_libvlc, "media player running. Exiting..."); for( int i = vlc_optind; i < i_argc; i++ ) { DBusMessage *msg = dbus_message_new_method_call( MPRIS_BUS_NAME, MPRIS_OBJECT_PATH, MPRIS_TRACKLIST_INTERFACE, "AddTrack" ); if( unlikely(msg == NULL) ) continue; /* We need to resolve relative paths in this instance */ char *mrl; if( strstr( ppsz_argv[i], "://" ) ) mrl = strdup( ppsz_argv[i] ); else mrl = vlc_path2uri( ppsz_argv[i], NULL ); if( mrl == NULL ) { dbus_message_unref( msg ); continue; } const char *after_track = MPRIS_APPEND; /* append MRLs */ if( !dbus_message_append_args( msg, DBUS_TYPE_STRING, &mrl, DBUS_TYPE_OBJECT_PATH, &after_track, DBUS_TYPE_BOOLEAN, &play, DBUS_TYPE_INVALID ) ) { dbus_message_unref( msg ); msg = NULL; free( mrl ); continue; } msg_Dbg( p_libvlc, "Adds %s to the running media player", mrl ); free( mrl ); /* send message and get a handle for a reply */ DBusMessage *reply = dbus_connection_send_with_reply_and_block( conn, msg, -1, &err ); dbus_message_unref( msg ); if( reply == NULL ) { msg_Err( p_libvlc, "D-Bus error: %s", err.message ); continue; } dbus_message_unref( reply ); } /* we unreference the connection when we've finished with it */ dbus_connection_unref( conn ); exit( 0 ); } #undef MPRIS_APPEND #undef MPRIS_BUS_NAME #undef MPRIS_OBJECT_PATH #undef MPRIS_TRACKLIST_INTERFACE dbus_out: #endif // HAVE_DBUS vlc_CPU_dump( VLC_OBJECT(p_libvlc) ); priv->b_stats = var_InheritBool( p_libvlc, "stats" ); /* * Initialize hotkey handling */ priv->actions = vlc_InitActions( p_libvlc ); /* * Meta data handling */ priv->parser = playlist_preparser_New(VLC_OBJECT(p_libvlc)); /* Create a variable for showing the fullscreen interface */ var_Create( p_libvlc, "intf-toggle-fscontrol", VLC_VAR_BOOL ); var_SetBool( p_libvlc, "intf-toggle-fscontrol", true ); /* Create a variable for the Boss Key */ var_Create( p_libvlc, "intf-boss", VLC_VAR_VOID ); /* Create a variable for showing the main interface */ var_Create( p_libvlc, "intf-show", VLC_VAR_BOOL ); /* Create a variable for showing the right click menu */ var_Create( p_libvlc, "intf-popupmenu", VLC_VAR_BOOL ); /* variables for signalling creation of new files */ var_Create( p_libvlc, "snapshot-file", VLC_VAR_STRING ); var_Create( p_libvlc, "record-file", VLC_VAR_STRING ); /* some default internal settings */ var_Create( p_libvlc, "window", VLC_VAR_STRING ); /* NOTE: Because the playlist and interfaces start before this function * returns control to the application (DESIGN BUG!), all these variables * must be created (in place of libvlc_new()) and set to VLC defaults * (in place of VLC main()) *here*. */ var_Create( p_libvlc, "user-agent", VLC_VAR_STRING ); var_SetString( p_libvlc, "user-agent", "VLC media player (LibVLC "VERSION")" ); var_Create( p_libvlc, "http-user-agent", VLC_VAR_STRING ); var_SetString( p_libvlc, "http-user-agent", "VLC/"PACKAGE_VERSION" LibVLC/"PACKAGE_VERSION ); var_Create( p_libvlc, "app-icon-name", VLC_VAR_STRING ); var_SetString( p_libvlc, "app-icon-name", PACKAGE_NAME ); var_Create( p_libvlc, "app-id", VLC_VAR_STRING ); var_SetString( p_libvlc, "app-id", "org.VideoLAN.VLC" ); var_Create( p_libvlc, "app-version", VLC_VAR_STRING ); var_SetString( p_libvlc, "app-version", PACKAGE_VERSION ); /* System specific configuration */ system_Configure( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind ); #ifdef ENABLE_VLM /* Initialize VLM if vlm-conf is specified */ psz_parser = var_CreateGetNonEmptyString( p_libvlc, "vlm-conf" ); if( psz_parser ) { priv->p_vlm = vlm_New( p_libvlc ); if( !priv->p_vlm ) msg_Err( p_libvlc, "VLM initialization failed" ); } free( psz_parser ); #endif /* * Load background interfaces */ psz_modules = var_CreateGetNonEmptyString( p_libvlc, "extraintf" ); psz_control = var_CreateGetNonEmptyString( p_libvlc, "control" ); if( psz_modules && psz_control ) { char* psz_tmp; if( asprintf( &psz_tmp, "%s:%s", psz_modules, psz_control ) != -1 ) { free( psz_modules ); psz_modules = psz_tmp; } } else if( psz_control ) { free( psz_modules ); psz_modules = strdup( psz_control ); } psz_parser = psz_modules; while ( psz_parser && *psz_parser ) { char *psz_module, *psz_temp; psz_module = psz_parser; psz_parser = strchr( psz_module, ':' ); if ( psz_parser ) { *psz_parser = '\0'; psz_parser++; } if( asprintf( &psz_temp, "%s,none", psz_module ) != -1) { libvlc_InternalAddIntf( p_libvlc, psz_temp ); free( psz_temp ); } } free( psz_modules ); free( psz_control ); if( var_InheritBool( p_libvlc, "network-synchronisation") ) libvlc_InternalAddIntf( p_libvlc, "netsync,none" ); #ifdef __APPLE__ var_Create( p_libvlc, "drawable-view-top", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-view-left", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-view-bottom", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-view-right", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-clip-top", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-clip-left", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-clip-bottom", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER ); var_Create( p_libvlc, "drawable-nsobject", VLC_VAR_ADDRESS ); #endif /* * Get input filenames given as commandline arguments. * We assume that the remaining parameters are filenames * and their input options. */ GetFilenames( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind ); /* * Get --open argument */ psz_val = var_InheritString( p_libvlc, "open" ); if ( psz_val != NULL ) { intf_InsertItem( p_libvlc, psz_val, 0, NULL, 0 ); free( psz_val ); } 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: ky0123456789 * 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' }, { "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' }, { "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' }, { "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' }, { 0, 0, 0, 0 } }; while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:", 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; 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 'f': i_frequency = strtol( optarg, NULL, 0 ); if ( pf_Open != NULL ) usage(); pf_Open = dvb_Open; pf_Read = dvb_Read; pf_Reset = dvb_Reset; pf_SetFilter = dvb_SetFilter; pf_UnsetFilter = dvb_UnsetFilter; 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 '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 '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; 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': i_asi_adapter = strtol( optarg, NULL, 0 ); if ( pf_Open != NULL ) usage(); pf_Open = asi_Open; pf_Read = asi_Read; pf_Reset = asi_Reset; pf_SetFilter = asi_SetFilter; pf_UnsetFilter = asi_UnsetFilter; 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; b_dvb_global = 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': if ( !strcmp(optarg, "text") ) i_print_type = PRINT_TEXT; else if ( !strcmp(optarg, "xml") ) i_print_type = PRINT_XML; else 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 '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; }
/** * Get the update file and parse it * p_update has to be locked when calling this function * * \param p_update pointer to update struct * \return true if the update is valid and authenticated */ static bool GetUpdateFile( update_t *p_update ) { stream_t *p_stream = NULL; char *psz_version_line = NULL; char *psz_update_data = NULL; p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL ); if( !p_stream ) { msg_Err( p_update->p_libvlc, "Failed to open %s for reading", UPDATE_VLC_STATUS_URL ); goto error; } const int64_t i_read = stream_Size( p_stream ); psz_update_data = malloc( i_read + 1 ); /* terminating '\0' */ if( !psz_update_data ) goto error; if( stream_Read( p_stream, psz_update_data, i_read ) != i_read ) { msg_Err( p_update->p_libvlc, "Couldn't download update file %s", UPDATE_VLC_STATUS_URL ); goto error; } psz_update_data[i_read] = '\0'; stream_Delete( p_stream ); p_stream = NULL; /* first line : version number */ char *psz_update_data_parser = psz_update_data; size_t i_len = strcspn( psz_update_data, "\r\n" ); psz_update_data_parser += i_len; while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' ) psz_update_data_parser++; if( !(psz_version_line = malloc( i_len + 1)) ) goto error; strncpy( psz_version_line, psz_update_data, i_len ); psz_version_line[i_len] = '\0'; p_update->release.i_extra = 0; int ret = sscanf( psz_version_line, "%i.%i.%i.%i", &p_update->release.i_major, &p_update->release.i_minor, &p_update->release.i_revision, &p_update->release.i_extra); if( ret != 3 && ret != 4 ) { msg_Err( p_update->p_libvlc, "Update version false formated" ); goto error; } /* second line : URL */ i_len = strcspn( psz_update_data_parser, "\r\n" ); if( i_len == 0 ) { msg_Err( p_update->p_libvlc, "Update file %s is corrupted: URL missing", UPDATE_VLC_STATUS_URL ); goto error; } if( !(p_update->release.psz_url = malloc( i_len + 1)) ) goto error; strncpy( p_update->release.psz_url, psz_update_data_parser, i_len ); p_update->release.psz_url[i_len] = '\0'; psz_update_data_parser += i_len; while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' ) psz_update_data_parser++; /* Remaining data : description */ i_len = strlen( psz_update_data_parser ); if( i_len == 0 ) { msg_Err( p_update->p_libvlc, "Update file %s is corrupted: description missing", UPDATE_VLC_STATUS_URL ); goto error; } if( !(p_update->release.psz_desc = malloc( i_len + 1)) ) goto error; strncpy( p_update->release.psz_desc, psz_update_data_parser, i_len ); p_update->release.psz_desc[i_len] = '\0'; /* Now that we know the status is valid, we must download its signature * to authenticate it */ signature_packet_t sign; if( download_signature( VLC_OBJECT( p_update->p_libvlc ), &sign, UPDATE_VLC_STATUS_URL ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "Couldn't download signature of status file" ); goto error; } if( sign.type != BINARY_SIGNATURE && sign.type != TEXT_SIGNATURE ) { msg_Err( p_update->p_libvlc, "Invalid signature type" ); goto error; } p_update->p_pkey = (public_key_t*)malloc( sizeof( public_key_t ) ); if( !p_update->p_pkey ) goto error; if( parse_public_key( videolan_public_key, sizeof( videolan_public_key ), p_update->p_pkey, NULL ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "Couldn't parse embedded public key, something went really wrong..." ); FREENULL( p_update->p_pkey ); goto error; } memcpy( p_update->p_pkey->longid, videolan_public_key_longid, 8 ); if( memcmp( sign.issuer_longid, p_update->p_pkey->longid , 8 ) != 0 ) { msg_Dbg( p_update->p_libvlc, "Need to download the GPG key" ); public_key_t *p_new_pkey = download_key( VLC_OBJECT(p_update->p_libvlc), sign.issuer_longid, videolan_public_key_longid ); if( !p_new_pkey ) { msg_Err( p_update->p_libvlc, "Couldn't download GPG key" ); FREENULL( p_update->p_pkey ); goto error; } uint8_t *p_hash = hash_sha1_from_public_key( p_new_pkey ); if( !p_hash ) { msg_Err( p_update->p_libvlc, "Failed to hash signature" ); free( p_new_pkey ); FREENULL( p_update->p_pkey ); goto error; } if( verify_signature( p_new_pkey->sig.r, p_new_pkey->sig.s, &p_update->p_pkey->key, p_hash ) == VLC_SUCCESS ) { free( p_hash ); msg_Info( p_update->p_libvlc, "Key authenticated" ); free( p_update->p_pkey ); p_update->p_pkey = p_new_pkey; } else { free( p_hash ); msg_Err( p_update->p_libvlc, "Key signature invalid !" ); goto error; } } uint8_t *p_hash = hash_sha1_from_text( psz_update_data, &sign ); if( !p_hash ) { msg_Warn( p_update->p_libvlc, "Can't compute SHA1 hash for status file" ); goto error; } else if( p_hash[0] != sign.hash_verification[0] || p_hash[1] != sign.hash_verification[1] ) { msg_Warn( p_update->p_libvlc, "Bad SHA1 hash for status file" ); free( p_hash ); goto error; } else if( verify_signature( sign.r, sign.s, &p_update->p_pkey->key, p_hash ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "BAD SIGNATURE for status file" ); free( p_hash ); goto error; } else { msg_Info( p_update->p_libvlc, "Status file authenticated" ); return true; } error: if( p_stream ) stream_Delete( p_stream ); free( psz_version_line ); free( psz_update_data ); return false; }
/** * This function initializes SDL vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; #if !defined(_WIN32) && !defined(__OS2__) if (!vlc_xlib_init (object)) return VLC_EGENERIC; #endif /* XXX: check for conflicts with the SDL audio output */ vlc_mutex_lock(&sdl_lock); /* Check if SDL video module has been initialized */ if (SDL_WasInit(SDL_INIT_VIDEO) != 0) { vlc_mutex_unlock(&sdl_lock); return VLC_EGENERIC; } vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&sdl_lock); return VLC_ENOMEM; } /* */ int sdl_flags = SDL_INIT_VIDEO; #ifndef _WIN32 /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/ sdl_flags |= SDL_INIT_EVENTTHREAD; #endif /* In debug mode you may want vlc to dump a core instead of staying stuck */ sdl_flags |= SDL_INIT_NOPARACHUTE; /* Initialize library */ if (SDL_Init(sdl_flags) < 0) { vlc_mutex_unlock(&sdl_lock); msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError()); free(sys); return VLC_EGENERIC; } vlc_mutex_unlock(&sdl_lock); /* Translate keys into unicode */ SDL_EnableUNICODE(1); /* Get the desktop resolution */ /* FIXME: SDL has a problem with virtual desktop */ sys->desktop_width = SDL_GetVideoInfo()->current_w; sys->desktop_height = SDL_GetVideoInfo()->current_h; /* */ video_format_t fmt; video_format_ApplyRotation(&fmt, &vd->fmt); /* */ vout_display_info_t info = vd->info; /* Set main window's size */ int display_width; int display_height; if (vd->cfg->is_fullscreen) { display_width = sys->desktop_width; display_height = sys->desktop_height; } else { display_width = vd->cfg->display.width; display_height = vd->cfg->display.height; } /* Initialize flags and cursor */ sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF; sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE; sys->display_bpp = SDL_VideoModeOK(display_width, display_height, 16, sys->display_flags); if (sys->display_bpp == 0) { msg_Err(vd, "no video mode available"); goto error; } vout_display_DeleteWindow(vd, NULL); sys->display = SDL_SetVideoMode(display_width, display_height, sys->display_bpp, sys->display_flags); if (!sys->display) { msg_Err(vd, "cannot set video mode"); goto error; } /* We keep the surface locked forever */ SDL_LockSurface(sys->display); /* */ vlc_fourcc_t forced_chroma = 0; char *psz_chroma = var_InheritString(vd, "sdl-chroma"); if (psz_chroma) { forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma); if (forced_chroma) msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)", forced_chroma, (const char*)&forced_chroma); free(psz_chroma); } /* Try to open an overlay if requested */ sys->overlay = NULL; const bool is_overlay = var_InheritBool(vd, "overlay"); if (is_overlay) { static const struct { vlc_fourcc_t vlc; uint32_t sdl; } vlc_to_sdl[] = { { VLC_CODEC_YV12, SDL_YV12_OVERLAY }, { VLC_CODEC_I420, SDL_IYUV_OVERLAY }, { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY }, { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY }, { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY }, { 0, 0 } }; const vlc_fourcc_t forced_chromas[] = { forced_chroma, 0 }; const vlc_fourcc_t *fallback_chromas = vlc_fourcc_GetYUVFallback(fmt.i_chroma); const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas; for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) { for (int i = 0; chromas[i] != 0; i++) { const vlc_fourcc_t vlc = chromas[i]; uint32_t sdl = 0; for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) { if (vlc_to_sdl[j].vlc == vlc) sdl = vlc_to_sdl[j].sdl; } if (!sdl) continue; sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height, sdl, sys->display); if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) { /* Ignore non hardware overlay surface in first pass */ SDL_FreeYUVOverlay(sys->overlay); sys->overlay = NULL; } if (sys->overlay) { /* We keep the surface locked forever */ SDL_LockYUVOverlay(sys->overlay); fmt.i_chroma = vlc; sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma, vd->fmt.i_chroma); if (sys->is_uv_swapped) fmt.i_chroma = vd->fmt.i_chroma; break; } } } } else { msg_Warn(vd, "SDL overlay disabled by the user"); } /* */ vout_display_cfg_t place_cfg = *vd->cfg; place_cfg.display.width = display_width; place_cfg.display.height = display_height; vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay); /* If no overlay, fallback to software output */ if (!sys->overlay) { /* */ switch (sys->display->format->BitsPerPixel) { case 8: fmt.i_chroma = VLC_CODEC_RGB8; break; case 15: fmt.i_chroma = VLC_CODEC_RGB15; break; case 16: fmt.i_chroma = VLC_CODEC_RGB16; break; case 24: fmt.i_chroma = VLC_CODEC_RGB24; break; case 32: fmt.i_chroma = VLC_CODEC_RGB32; break; default: msg_Err(vd, "unknown screen depth %i", sys->display->format->BitsPerPixel); goto error; } /* All we have is an RGB image with square pixels */ fmt.i_width = display_width; fmt.i_height = display_height; fmt.i_rmask = sys->display->format->Rmask; fmt.i_gmask = sys->display->format->Gmask; fmt.i_bmask = sys->display->format->Bmask; info.has_pictures_invalid = true; } if (vd->cfg->display.title) SDL_WM_SetCaption(vd->cfg->display.title, vd->cfg->display.title); else if (!sys->overlay) SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)", VOUT_TITLE " (software RGB SDL output)"); else if (sys->overlay->hw_overlay) SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)", VOUT_TITLE " (hardware YUV SDL output)"); else SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)", VOUT_TITLE " (software YUV SDL output)"); /* Setup events */ SDL_EventState(SDL_KEYUP, SDL_IGNORE); /* ignore keys up */ /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* */ vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen); return VLC_SUCCESS; error: msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError()); if (sys->display) { SDL_UnlockSurface(sys->display); SDL_FreeSurface(sys->display); } vlc_mutex_lock(&sdl_lock); SDL_QuitSubSystem(SDL_INIT_VIDEO); vlc_mutex_unlock(&sdl_lock); free(sys); return VLC_EGENERIC; }
/***************************************************************************** * DecodeAudio: Called to decode one frame *****************************************************************************/ aout_buffer_t * DecodeAudio ( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_used, i_output; aout_buffer_t *p_buffer; 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 ); avcodec_flush_buffers( p_sys->p_context ); p_sys->i_samples = 0; date_Set( &p_sys->end_date, 0 ); if( p_sys->i_codec_id == CODEC_ID_MP2 || p_sys->i_codec_id == CODEC_ID_MP3 ) p_sys->i_reject_count = 3; return NULL; } if( p_sys->i_samples > 0 ) { /* More data */ p_buffer = SplitBuffer( p_dec ); if( !p_buffer ) block_Release( p_block ); return p_buffer; } if( !date_Get( &p_sys->end_date ) && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); return NULL; } if( p_block->i_buffer <= 0 ) { block_Release( p_block ); return NULL; } if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 ) { *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); if( !p_block ) return NULL; p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE ); p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED; } do { i_output = __MAX( p_block->i_buffer, p_sys->i_output_max ); if( i_output > p_sys->i_output_max ) { /* Grow output buffer if necessary (eg. for PCM data) */ p_sys->p_output = av_realloc( p_sys->p_output, i_output ); } i_used = avcodec_decode_audio2( p_sys->p_context, (int16_t*)p_sys->p_output, &i_output, p_block->p_buffer, p_block->i_buffer ); if( i_used < 0 || i_output < 0 ) { if( i_used < 0 ) msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); block_Release( p_block ); return NULL; } else if( (size_t)i_used > p_block->i_buffer ) { i_used = p_block->i_buffer; } p_block->i_buffer -= i_used; p_block->p_buffer += i_used; } while( p_block->i_buffer > 0 && i_output <= 0 ); if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 8 || p_sys->p_context->sample_rate <= 0 ) { msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d", p_sys->p_context->channels, p_sys->p_context->sample_rate ); block_Release( p_block ); return NULL; } if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate ) { date_Init( &p_sys->end_date, p_sys->p_context->sample_rate, 1 ); date_Set( &p_sys->end_date, p_block->i_pts ); } /* **** Set audio output parameters **** */ SetupOutputFormat( p_dec, true ); if( p_block->i_pts != 0 && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } p_block->i_pts = 0; /* **** Now we can output these samples **** */ p_sys->i_samples = i_output / (p_dec->fmt_out.audio.i_bitspersample / 8) / p_sys->p_context->channels; p_sys->p_samples = p_sys->p_output; /* Silent unwanted samples */ if( p_sys->i_reject_count > 0 ) { memset( p_sys->p_output, 0, i_output ); p_sys->i_reject_count--; } p_buffer = SplitBuffer( p_dec ); if( !p_buffer ) block_Release( p_block ); return p_buffer; }
/***************************************************************************** * 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" ); #if LIBAVCODEC_VERSION_MAJOR < 54 p_sys->p_context->error_recognition = #else p_sys->p_context->err_recognition = #endif var_InheritInteger( p_dec, "avcodec-error-resilience" ); if( var_CreateGetBool( p_dec, "grayscale" ) ) p_sys->p_context->flags |= CODEC_FLAG_GRAY; 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-lowres" ); if( i_val > 0 && i_val <= 2 ) p_sys->p_context->lowres = 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; /* ***** ffmpeg frame skipping ***** */ p_sys->b_hurry_up = var_CreateGetBool( p_dec, "avcodec-hurry-up" ); switch( var_CreateGetInteger( p_dec, "avcodec-skip-frame" ) ) { case -1: p_sys->p_context->skip_frame = AVDISCARD_NONE; break; case 0: p_sys->p_context->skip_frame = AVDISCARD_DEFAULT; break; case 1: p_sys->p_context->skip_frame = AVDISCARD_NONREF; break; case 2: p_sys->p_context->skip_frame = AVDISCARD_NONKEY; break; case 3: p_sys->p_context->skip_frame = AVDISCARD_ALL; break; default: p_sys->p_context->skip_frame = AVDISCARD_NONE; break; } p_sys->i_skip_frame = p_sys->p_context->skip_frame; switch( var_CreateGetInteger( p_dec, "avcodec-skip-idct" ) ) { case -1: p_sys->p_context->skip_idct = AVDISCARD_NONE; break; case 0: p_sys->p_context->skip_idct = AVDISCARD_DEFAULT; break; case 1: p_sys->p_context->skip_idct = AVDISCARD_NONREF; break; case 2: p_sys->p_context->skip_idct = AVDISCARD_NONKEY; break; case 3: p_sys->p_context->skip_idct = AVDISCARD_ALL; break; default: p_sys->p_context->skip_idct = AVDISCARD_NONE; break; } p_sys->i_skip_idct = p_sys->p_context->skip_idct; /* ***** ffmpeg 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 != CODEC_ID_TSCC && p_sys->i_codec_id != CODEC_ID_CSCD && p_sys->i_codec_id != CODEC_ID_CINEPAK && #if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 68, 2 ) ) && (LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 100, 1 ) ) /* avcodec native vp8 decode doesn't handle EMU_EDGE flag, and I don't have idea howto implement fallback to libvpx decoder */ p_sys->i_codec_id != CODEC_ID_VP8 && #endif !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; } /* ffmpeg 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" ); } /* Always use our get_buffer wrapper so we can calculate the * PTS correctly */ p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf; p_sys->p_context->reget_buffer = ffmpeg_ReGetFrameBuf; p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf; 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; #endif #ifdef HAVE_AVCODEC_VA const bool b_use_hw = var_CreateGetBool( p_dec, "avcodec-hw" ); if( b_use_hw && (i_codec_id == CODEC_ID_MPEG1VIDEO || i_codec_id == CODEC_ID_MPEG2VIDEO || i_codec_id == CODEC_ID_MPEG4 || i_codec_id == CODEC_ID_H264 || i_codec_id == CODEC_ID_VC1 || i_codec_id == CODEC_ID_WMV3) ) { #ifdef HAVE_AVCODEC_MT if( p_sys->p_context->thread_type & FF_THREAD_FRAME ) { msg_Warn( p_dec, "threaded frame decoding is not compatible with ffmpeg-hw, disabled" ); p_sys->p_context->thread_type &= ~FF_THREAD_FRAME; } if( ( p_sys->p_context->thread_type & FF_THREAD_SLICE ) && ( i_codec_id == CODEC_ID_MPEG1VIDEO || i_codec_id == CODEC_ID_MPEG2VIDEO ) ) { msg_Warn( p_dec, "threaded slice decoding is not compatible with ffmpeg-hw, disabled" ); p_sys->p_context->thread_type &= ~FF_THREAD_SLICE; } #endif p_sys->p_context->get_format = ffmpeg_GetFormat; } #endif #ifdef HAVE_AVCODEC_MT 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; #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 # warning FIXME #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; }
/***************************************************************************** * 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; } /* Discard legacy username/password syntax - not supported */ const char *psz_location = strchr( p_access->psz_location, '@' ); if( psz_location != NULL ) psz_location++; else psz_location = p_access->psz_location; p_access->pf_read = NULL; p_access->pf_block = BlockRead; p_access->pf_seek = Seek; p_access->pf_control = Control; p_access->info.b_eof = false; 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, psz_location, 0 ); if( i_result ) { msg_Dbg( p_access, "could not connect to: %s", psz_location ); 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_Alloc( 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; } free( psz_server ); return VLC_SUCCESS; error: free( psz_server ); Close( p_this ); return VLC_EGENERIC; }
/***************************************************************************** * 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 == AV_CODEC_ID_VC1 || p_sys->i_codec_id == AV_CODEC_ID_VORBIS || p_sys->i_codec_id == AV_CODEC_ID_THEORA || ( p_sys->i_codec_id == AV_CODEC_ID_AAC && !p_dec->fmt_in.b_packetized ) ) { 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; if( p_sys->i_codec_id == AV_CODEC_ID_ADPCM_G726 && p_sys->p_context->bit_rate > 0 && p_sys->p_context->sample_rate > 0) p_sys->p_context->bits_per_coded_sample = p_sys->p_context->bit_rate / p_sys->p_context->sample_rate; } int ret; char *psz_opts = var_InheritString( p_dec, "avcodec-options" ); AVDictionary *options = NULL; if (psz_opts && *psz_opts) options = vlc_av_get_options(psz_opts); free(psz_opts); vlc_avcodec_lock(); ret = avcodec_open2( p_sys->p_context, p_sys->p_codec, options ? &options : NULL ); vlc_avcodec_unlock(); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) { msg_Err( p_dec, "Unknown option \"%s\"", t->key ); } av_dict_free(&options); if( ret < 0 ) return VLC_EGENERIC; msg_Dbg( p_dec, "avcodec 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 block_t *Reassemble( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *p_buffer; uint16_t i_expected_image; uint8_t i_packet, i_expected_packet; if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) ) { block_Release( p_block ); return NULL; } if( p_block->i_buffer < SPU_HEADER_LEN ) { msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" , p_block->i_buffer, SPU_HEADER_LEN ); block_Release( p_block ); return NULL; } p_buffer = p_block->p_buffer; if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY ) { i_expected_image = p_sys->i_image + 1; i_expected_packet = 0; } else { i_expected_image = p_sys->i_image; i_expected_packet = p_sys->i_packet + 1; } /* The dummy ES that the menu selection uses has an 0x70 at the head which we need to strip off. */ p_buffer += 2; if( *p_buffer & 0x80 ) { p_sys->i_state = SUBTITLE_BLOCK_COMPLETE; i_packet = *p_buffer++ & 0x7F; } else { p_sys->i_state = SUBTITLE_BLOCK_PARTIAL; i_packet = *p_buffer++; } p_sys->i_image = GETINT16(p_buffer); if( p_sys->i_image != i_expected_image ) { msg_Warn( p_dec, "expected subtitle image %u but found %u", i_expected_image, p_sys->i_image ); } if( i_packet != i_expected_packet ) { msg_Warn( p_dec, "expected subtitle image packet %u but found %u", i_expected_packet, i_packet ); } p_block->p_buffer += SPU_HEADER_LEN; p_block->i_buffer -= SPU_HEADER_LEN; p_sys->i_packet = i_packet; /* First packet in the subtitle block */ if( !p_sys->i_packet ) ParseHeader( p_dec, p_block ); block_ChainAppend( &p_sys->p_spu, p_block ); if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE ) { block_t *p_spu = block_ChainGather( p_sys->p_spu ); if( p_spu->i_buffer != p_sys->i_spu_size ) { msg_Warn( p_dec, "subtitle packets size=%zu should be %zu", p_spu->i_buffer, p_sys->i_spu_size ); } msg_Dbg( p_dec, "subtitle packet complete, size=%zu", p_spu->i_buffer ); p_sys->i_state = SUBTITLE_BLOCK_EMPTY; p_sys->p_spu = 0; return p_spu; } return NULL; }