/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*) p_this; int i_cat, i_codec_id, i_result; const char *psz_namecodec; AVCodecContext *p_context = NULL; AVCodec *p_codec = NULL; /* *** determine codec type *** */ if( !GetFfmpegCodec( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id, &psz_namecodec ) ) { return VLC_EGENERIC; } /* Initialization must be done before avcodec_find_decoder() */ InitLibavcodec(p_this); /* *** ask ffmpeg for a decoder *** */ p_codec = avcodec_find_decoder( i_codec_id ); if( !p_codec ) { msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec ); return VLC_EGENERIC; } /* *** get a p_context *** */ p_context = avcodec_alloc_context(); if( !p_context ) return VLC_ENOMEM; p_context->debug = var_InheritInteger( p_dec, "ffmpeg-debug" ); p_context->opaque = (void *)p_this; /* Set CPU capabilities */ unsigned i_cpu = vlc_CPU(); p_context->dsp_mask = 0; if( !(i_cpu & CPU_CAPABILITY_MMX) ) { p_context->dsp_mask |= AV_CPU_FLAG_MMX; } if( !(i_cpu & CPU_CAPABILITY_MMXEXT) ) { p_context->dsp_mask |= AV_CPU_FLAG_MMX2; } if( !(i_cpu & CPU_CAPABILITY_3DNOW) ) { p_context->dsp_mask |= AV_CPU_FLAG_3DNOW; } if( !(i_cpu & CPU_CAPABILITY_SSE) ) { p_context->dsp_mask |= AV_CPU_FLAG_SSE; } if( !(i_cpu & CPU_CAPABILITY_SSE2) ) { p_context->dsp_mask |= AV_CPU_FLAG_SSE2; } #ifdef AV_CPU_FLAG_SSE3 if( !(i_cpu & CPU_CAPABILITY_SSE3) ) p_context->dsp_mask |= AV_CPU_FLAG_SSE3; #endif #ifdef AV_CPU_FLAG_SSSE3 if( !(i_cpu & CPU_CAPABILITY_SSSE3) ) p_context->dsp_mask |= AV_CPU_FLAG_SSSE3; #endif #ifdef AV_CPU_FLAG_SSE4 if( !(i_cpu & CPU_CAPABILITY_SSE4_1) ) p_context->dsp_mask |= AV_CPU_FLAG_SSE4; #endif #ifdef AV_CPU_FLAG_SSE42 if( !(i_cpu & CPU_CAPABILITY_SSE4_2) ) p_context->dsp_mask |= AV_CPU_FLAG_SSE42; #endif p_dec->b_need_packetized = true; switch( i_cat ) { case VIDEO_ES: p_dec->pf_decode_video = DecodeVideo; i_result = InitVideoDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case AUDIO_ES: p_dec->pf_decode_audio = DecodeAudio; i_result = InitAudioDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case SPU_ES: p_dec->pf_decode_sub = DecodeSubtitle; i_result = InitSubtitleDec( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; default: i_result = VLC_EGENERIC; } if( i_result == VLC_SUCCESS ) { p_dec->p_sys->i_cat = i_cat; if( p_context->profile != FF_PROFILE_UNKNOWN) p_dec->fmt_in.i_profile = p_context->profile; if( p_context->level != FF_LEVEL_UNKNOWN) p_dec->fmt_in.i_level = p_context->level; } return i_result; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*) p_this; unsigned i_codec_id; int i_cat, i_result; const char *psz_namecodec; AVCodecContext *p_context = NULL; AVCodec *p_codec = NULL; /* *** determine codec type *** */ if( !GetFfmpegCodec( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id, &psz_namecodec ) ) { return VLC_EGENERIC; } /* Initialization must be done before avcodec_find_decoder() */ vlc_init_avcodec(p_this); /* *** ask ffmpeg for a decoder *** */ char *psz_decoder = var_CreateGetString( p_this, "avcodec-codec" ); if( psz_decoder && *psz_decoder ) { p_codec = avcodec_find_decoder_by_name( psz_decoder ); if( !p_codec ) msg_Err( p_this, "Decoder `%s' not found", psz_decoder ); else if( p_codec->id != i_codec_id ) { msg_Err( p_this, "Decoder `%s' can't handle %4.4s", psz_decoder, (char*)&p_dec->fmt_in.i_codec ); p_codec = NULL; } } free( psz_decoder ); if( !p_codec ) p_codec = avcodec_find_decoder( i_codec_id ); if( !p_codec ) { msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec ); return VLC_EGENERIC; } /* *** get a p_context *** */ p_context = avcodec_alloc_context3(p_codec); if( !p_context ) return VLC_ENOMEM; p_context->debug = var_InheritInteger( p_dec, "avcodec-debug" ); p_context->opaque = (void *)p_this; p_dec->b_need_packetized = true; switch( i_cat ) { case VIDEO_ES: p_dec->pf_decode_video = DecodeVideo; i_result = InitVideoDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case AUDIO_ES: p_dec->pf_decode_audio = DecodeAudio; i_result = InitAudioDec ( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; case SPU_ES: p_dec->pf_decode_sub = DecodeSubtitle; i_result = InitSubtitleDec( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); break; default: i_result = VLC_EGENERIC; } if( i_result == VLC_SUCCESS ) { p_dec->p_sys->i_cat = i_cat; if( p_context->profile != FF_PROFILE_UNKNOWN) p_dec->fmt_in.i_profile = p_context->profile; if( p_context->level != FF_LEVEL_UNKNOWN) p_dec->fmt_in.i_level = p_context->level; } return i_result; }
/***************************************************************************** * AddStream *****************************************************************************/ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) { sout_mux_sys_t *p_sys = p_mux->p_sys; const es_format_t *fmt = p_input->p_fmt; unsigned i_codec_id; msg_Dbg( p_mux, "adding input" ); if( !GetFfmpegCodec( fmt->i_cat, fmt->i_codec, &i_codec_id, NULL ) || i_codec_id == AV_CODEC_ID_NONE ) { msg_Dbg( p_mux, "couldn't find codec for fourcc '%4.4s'", (char *)&fmt->i_codec ); return VLC_EGENERIC; } unsigned opus_size[XIPH_MAX_HEADER_COUNT]; void *opus_packet[XIPH_MAX_HEADER_COUNT]; if( fmt->i_codec == VLC_CODEC_OPUS ) { unsigned count; /* Only transmits the first packet (OpusHead) */ if( xiph_SplitHeaders(opus_size, opus_packet, &count, fmt->i_extra, fmt->p_extra ) ) { count = 0; } if (count != 2 || opus_size[0] < 19) { msg_Err(p_mux, "Invalid Opus header"); return VLC_EGENERIC; } } if( fmt->i_cat != VIDEO_ES && fmt->i_cat != AUDIO_ES) { msg_Warn( p_mux, "Unhandled ES category" ); return VLC_EGENERIC; } /* */ p_input->p_sys = malloc( sizeof( int ) ); if( unlikely(p_input->p_sys == NULL) ) return VLC_ENOMEM; *((int *)p_input->p_sys) = p_sys->oc->nb_streams; /* */ AVStream *stream = avformat_new_stream( p_sys->oc, NULL); if( !stream ) { free( p_input->p_sys ); return VLC_EGENERIC; } #if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 5, 0)) AVCodecParameters *codecpar = stream->codecpar; #else AVCodecContext *codecpar = stream->codec; #endif unsigned int i_bitrate = fmt->i_bitrate; unsigned int i_frame_rate = fmt->video.i_frame_rate; unsigned int i_frame_rate_base = fmt->video.i_frame_rate_base; switch( fmt->i_cat ) { case AUDIO_ES: codecpar->codec_type = AVMEDIA_TYPE_AUDIO; codecpar->channels = fmt->audio.i_channels; codecpar->sample_rate = fmt->audio.i_rate; stream->time_base = (AVRational){1, codecpar->sample_rate}; if (fmt->i_bitrate == 0) { msg_Warn( p_mux, "Missing audio bitrate, assuming 64k" ); i_bitrate = 64000; } break; case VIDEO_ES: if( !fmt->video.i_frame_rate || !fmt->video.i_frame_rate_base ) { msg_Warn( p_mux, "Missing frame rate, assuming 25fps" ); i_frame_rate = 25; i_frame_rate_base = 1; } else msg_Dbg( p_mux, "Muxing framerate will be %d/%d = %.2f fps", fmt->video.i_frame_rate, fmt->video.i_frame_rate_base, (double)fmt->video.i_frame_rate/(double)fmt->video.i_frame_rate_base ); codecpar->codec_type = AVMEDIA_TYPE_VIDEO; codecpar->width = fmt->video.i_visible_width; codecpar->height = fmt->video.i_visible_height; av_reduce( &codecpar->sample_aspect_ratio.num, &codecpar->sample_aspect_ratio.den, fmt->video.i_sar_num, fmt->video.i_sar_den, 1 << 30 /* something big */ ); msg_Dbg(p_mux, "Muxing aspect ratio will be %d/%d", fmt->video.i_sar_num, fmt->video.i_sar_den); stream->sample_aspect_ratio.den = codecpar->sample_aspect_ratio.den; stream->sample_aspect_ratio.num = codecpar->sample_aspect_ratio.num; stream->time_base.den = i_frame_rate; stream->time_base.num = i_frame_rate_base; if (fmt->i_bitrate == 0) { msg_Warn( p_mux, "Missing video bitrate, assuming 512k" ); i_bitrate = 512000; } else msg_Dbg( p_mux, "Muxing video bitrate will be %d", fmt->i_bitrate ); break; default: vlc_assert_unreachable(); } codecpar->bit_rate = i_bitrate; codecpar->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id ); if( !codecpar->codec_tag && i_codec_id == AV_CODEC_ID_MP2 ) { i_codec_id = AV_CODEC_ID_MP3; codecpar->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id ); } codecpar->codec_id = i_codec_id; if( fmt->i_extra ) { if( fmt->i_codec == VLC_CODEC_OPUS ) { codecpar->extradata_size = opus_size[0]; codecpar->extradata = av_malloc( opus_size[0] ); memcpy( codecpar->extradata, opus_packet[0], opus_size[0] ); } else { codecpar->extradata_size = fmt->i_extra; codecpar->extradata = av_malloc( fmt->i_extra ); memcpy( codecpar->extradata, fmt->p_extra, fmt->i_extra ); } } return VLC_SUCCESS; }