@@ -128,29 +128,36 @@ static enum AVPixelFormat get_hw_pixfmt(AVCodecContext *vc, const enum AVPixelFo
128128}
129129
130130
131- int open_audio_decoder (struct input_ctx * ctx , AVCodec * codec )
131+ static int open_audio_decoder (struct input_ctx * ctx , AVCodec * codec )
132132{
133133 int ret = 0 ;
134134 AVFormatContext * ic = ctx -> ic ;
135135
136136 // open audio decoder
137- AVCodecContext * ac = avcodec_alloc_context3 (codec );
138- if (!ac ) LPMS_ERR (open_audio_err , "Unable to alloc audio codec" );
139- if (ctx -> ac ) LPMS_WARN ("An audio context was already open!" );
140- ctx -> ac = ac ;
141- ret = avcodec_parameters_to_context (ac , ic -> streams [ctx -> ai ]-> codecpar );
142- if (ret < 0 ) LPMS_ERR (open_audio_err , "Unable to assign audio params" );
143- ret = avcodec_open2 (ac , codec , NULL );
144- if (ret < 0 ) LPMS_ERR (open_audio_err , "Unable to open audio decoder" );
145-
137+ AVCodecContext * ac = avcodec_alloc_context3 (codec );
138+ if (!ac ) LPMS_ERR (open_audio_err , "Unable to alloc audio codec" );
139+ if (ctx -> ac ) LPMS_WARN ("An audio context was already open!" );
140+ ctx -> ac = ac ;
141+ ret = avcodec_parameters_to_context (ac , ic -> streams [ctx -> ai ]-> codecpar );
142+ if (ret < 0 ) LPMS_ERR (open_audio_err , "Unable to assign audio params" );
143+ ret = avcodec_open2 (ac , codec , NULL );
144+ if (ret < 0 ) LPMS_ERR (open_audio_err , "Unable to open audio decoder" );
145+ ctx -> last_frame_a = av_frame_alloc ();
146+ if (!ctx -> last_frame_a ) LPMS_ERR (open_audio_err , "Unable to alloc last_frame_a" );
146147 return 0 ;
147148
148149open_audio_err :
149150 free_input (ctx , FORCE_CLOSE_HW_DECODER );
150151 return ret ;
151152}
152153
153- char * get_hw_decoder (int ff_codec_id , int hw_type )
154+ static void close_audio_decoder (struct input_ctx * ictx )
155+ {
156+ if (ictx -> ac ) avcodec_free_context (& ictx -> ac );
157+ if (ictx -> last_frame_a ) av_frame_free (& ictx -> last_frame_a );
158+ }
159+
160+ static char * get_hw_decoder (int ff_codec_id , int hw_type )
154161{
155162 switch (hw_type ) {
156163 case AV_HWDEVICE_TYPE_CUDA :
@@ -184,47 +191,51 @@ char* get_hw_decoder(int ff_codec_id, int hw_type)
184191 }
185192}
186193
187- int open_video_decoder (struct input_ctx * ctx , AVCodec * codec )
194+ static int open_video_decoder (struct input_ctx * ctx , AVCodec * codec )
188195{
189196 int ret = 0 ;
190197 AVDictionary * * opts = NULL ;
191198 AVFormatContext * ic = ctx -> ic ;
192199 // open video decoder
193- if (ctx -> hw_type > AV_HWDEVICE_TYPE_NONE ) {
194- char * decoder_name = get_hw_decoder (codec -> id , ctx -> hw_type );
195- if (!* decoder_name ) {
196- ret = lpms_ERR_INPUT_CODEC ;
197- LPMS_ERR (open_decoder_err , "Input codec does not support hardware acceleration" );
198- }
199- AVCodec * c = avcodec_find_decoder_by_name (decoder_name );
200- if (c ) codec = c ;
201- else LPMS_WARN ("Nvidia decoder not found; defaulting to software" );
202- if (AV_PIX_FMT_YUV420P != ic -> streams [ctx -> vi ]-> codecpar -> format &&
203- AV_PIX_FMT_YUVJ420P != ic -> streams [ctx -> vi ]-> codecpar -> format ) {
204- // TODO check whether the color range is truncated if yuvj420p is used
205- ret = lpms_ERR_INPUT_PIXFMT ;
206- LPMS_ERR (open_decoder_err , "Non 4:2:0 pixel format detected in input" );
207- }
200+ if (ctx -> hw_type > AV_HWDEVICE_TYPE_NONE ) {
201+ char * decoder_name = get_hw_decoder (codec -> id , ctx -> hw_type );
202+ if (!* decoder_name ) {
203+ ret = lpms_ERR_INPUT_CODEC ;
204+ LPMS_ERR (open_decoder_err , "Input codec does not support hardware acceleration" );
208205 }
209- AVCodecContext * vc = avcodec_alloc_context3 (codec );
210- if (!vc ) LPMS_ERR (open_decoder_err , "Unable to alloc video codec" );
211- ctx -> vc = vc ;
212- ret = avcodec_parameters_to_context (vc , ic -> streams [ctx -> vi ]-> codecpar );
213- if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to assign video params" );
214- vc -> opaque = (void * )ctx ;
215- // XXX Could this break if the original device falls out of scope in golang?
216- if (ctx -> hw_type == AV_HWDEVICE_TYPE_CUDA ) {
217- // First set the hw device then set the hw frame
218- ret = av_hwdevice_ctx_create (& ctx -> hw_device_ctx , ctx -> hw_type , ctx -> device , NULL , 0 );
219- if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to open hardware context for decoding" )
220- vc -> hw_device_ctx = av_buffer_ref (ctx -> hw_device_ctx );
221- vc -> get_format = get_hw_pixfmt ;
206+ AVCodec * c = avcodec_find_decoder_by_name (decoder_name );
207+ if (c ) codec = c ;
208+ else LPMS_WARN ("Nvidia decoder not found; defaulting to software" );
209+ // It is safe to use ctx->vi here, because open_video_decoder won't be
210+ // called if vi < 0
211+ if (AV_PIX_FMT_YUV420P != ic -> streams [ctx -> vi ]-> codecpar -> format &&
212+ AV_PIX_FMT_YUVJ420P != ic -> streams [ctx -> vi ]-> codecpar -> format ) {
213+ // TODO check whether the color range is truncated if yuvj420p is used
214+ ret = lpms_ERR_INPUT_PIXFMT ;
215+ LPMS_ERR (open_decoder_err , "Non 4:2:0 pixel format detected in input" );
222216 }
223- vc -> pkt_timebase = ic -> streams [ctx -> vi ]-> time_base ;
224- av_opt_set (vc -> priv_data , "xcoder-params" , ctx -> xcoderParams , 0 );
225- ret = avcodec_open2 (vc , codec , opts );
226- if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to open video decoder" );
217+ }
227218
219+ AVCodecContext * vc = avcodec_alloc_context3 (codec );
220+ if (!vc ) LPMS_ERR (open_decoder_err , "Unable to alloc video codec" );
221+ ctx -> vc = vc ;
222+ ret = avcodec_parameters_to_context (vc , ic -> streams [ctx -> vi ]-> codecpar );
223+ if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to assign video params" );
224+ vc -> opaque = (void * )ctx ;
225+ // XXX Could this break if the original device falls out of scope in golang?
226+ if (ctx -> hw_type == AV_HWDEVICE_TYPE_CUDA ) {
227+ // First set the hw device then set the hw frame
228+ ret = av_hwdevice_ctx_create (& ctx -> hw_device_ctx , ctx -> hw_type , ctx -> device , NULL , 0 );
229+ if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to open hardware context for decoding" )
230+ vc -> hw_device_ctx = av_buffer_ref (ctx -> hw_device_ctx );
231+ vc -> get_format = get_hw_pixfmt ;
232+ }
233+ vc -> pkt_timebase = ic -> streams [ctx -> vi ]-> time_base ;
234+ av_opt_set (vc -> priv_data , "xcoder-params" , ctx -> xcoderParams , 0 );
235+ ret = avcodec_open2 (vc , codec , opts );
236+ if (ret < 0 ) LPMS_ERR (open_decoder_err , "Unable to open video decoder" );
237+ ctx -> last_frame_v = av_frame_alloc ();
238+ if (!ctx -> last_frame_v ) LPMS_ERR (open_decoder_err , "Unable to alloc last_frame_v" );
228239 return 0 ;
229240
230241open_decoder_err :
@@ -233,6 +244,16 @@ int open_video_decoder(struct input_ctx *ctx, AVCodec *codec)
233244 return ret ;
234245}
235246
247+ static void close_video_decoder (struct input_ctx * ictx )
248+ {
249+ if (ictx -> vc ) {
250+ if (ictx -> vc -> hw_device_ctx ) av_buffer_unref (& ictx -> vc -> hw_device_ctx );
251+ avcodec_free_context (& ictx -> vc );
252+ }
253+ if (ictx -> hw_device_ctx ) av_buffer_unref (& ictx -> hw_device_ctx );
254+ if (ictx -> last_frame_v ) av_frame_free (& ictx -> last_frame_v );
255+ }
256+
236257int open_input (input_params * params , struct input_ctx * ctx )
237258{
238259 char * inp = params -> fname ;
@@ -247,52 +268,51 @@ int open_input(input_params *params, struct input_ctx *ctx)
247268 ctx -> device = params -> device ;
248269
249270 // open demuxer
250- if (!ctx -> ic ) {
251- ret = avformat_open_input (& ctx -> ic , inp , NULL , NULL );
252- if (ret < 0 ) LPMS_ERR (open_input_err , "demuxer: Unable to open input" );
253- ret = avformat_find_stream_info (ctx -> ic , NULL );
254- if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to find input info" );
255- } else if (!ctx -> ic -> pb ) {
256- // reopen input segment file IO context if needed
257- ret = avio_open (& ctx -> ic -> pb , inp , AVIO_FLAG_READ );
258- if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to reopen file" );
259- } else reopen_decoders = 0 ;
271+ ret = avformat_open_input (& ctx -> ic , inp , NULL , NULL );
272+ if (ret < 0 ) LPMS_ERR (open_input_err , "demuxer: Unable to open input" );
273+ ret = avformat_find_stream_info (ctx -> ic , NULL );
274+ if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to find input info" );
260275
261276 AVCodec * video_codec = NULL ;
262277 AVCodec * audio_codec = NULL ;
263278 ctx -> vi = av_find_best_stream (ctx -> ic , AVMEDIA_TYPE_VIDEO , -1 , -1 , & video_codec , 0 );
264279 ctx -> ai = av_find_best_stream (ctx -> ic , AVMEDIA_TYPE_AUDIO , -1 , -1 , & audio_codec , 0 );
265280
266- if (AV_HWDEVICE_TYPE_CUDA == ctx -> hw_type && ctx -> vi >= 0 ) {
267- if (ctx -> last_format == AV_PIX_FMT_NONE ) ctx -> last_format = ctx -> ic -> streams [ctx -> vi ]-> codecpar -> format ;
268- else if (ctx -> ic -> streams [ctx -> vi ]-> codecpar -> format != ctx -> last_format ) {
281+ // Now be careful here. It appears that in certain situation (such as .ts
282+ // stream without video stream) ctx->vi will be set to 0, but the format will
283+ // be set to AV_PIX_FMT_NONE and both width and height will be zero, etc
284+ // This is normally fine, but when re-using video decoder we have to be
285+ // extra careful, and handle both situations: one with negative vi, and one
286+ // with positive vi but AV_PIX_FMT_NONE in stream format
287+ enum AVPixelFormat format =
288+ (ctx -> vi >= 0 ) ? ctx -> ic -> streams [ctx -> vi ]-> codecpar -> format : AV_PIX_FMT_NONE ;
289+ if ((AV_HWDEVICE_TYPE_CUDA == ctx -> hw_type ) && (ctx -> vi >= 0 )
290+ && (AV_PIX_FMT_NONE != format )) {
291+ if (ctx -> last_format == AV_PIX_FMT_NONE ) ctx -> last_format = format ;
292+ else if (format != ctx -> last_format ) {
269293 LPMS_WARN ("Input pixel format has been changed in the middle." );
270- ctx -> last_format = ctx -> ic -> streams [ ctx -> vi ] -> codecpar -> format ;
294+ ctx -> last_format = format ;
271295 // if the decoder is not re-opened when the video pixel format is changed,
272296 // the decoder tries HW decoding with the video context initialized to a pixel format different from the input one.
273297 // to handle a change in the input pixel format,
274- // we close the demuxer and re-open the decoder by calling open_input().
275- free_input (ctx , FORCE_CLOSE_HW_DECODER );
276- ret = open_input (params , ctx );
277- if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to reopen video demuxer for HW decoding" );
278- reopen_decoders = 0 ;
298+ // we close the decoder so it will get reopened later
299+ close_video_decoder (ctx );
279300 }
280301 }
281302
282303 if (reopen_decoders ) {
283- if (!ctx -> dv && (ctx -> vi >= 0 ) &&
284- (!ctx -> vc || (ctx -> hw_type == AV_HWDEVICE_TYPE_NONE ))) {
285- ret = open_video_decoder (ctx , video_codec );
286- if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to open video decoder" )
287- ctx -> last_frame_v = av_frame_alloc ();
288- if (!ctx -> last_frame_v ) LPMS_ERR (open_input_err , "Unable to alloc last_frame_v" );
304+ if (!ctx -> dv && (ctx -> vi >= 0 ) && (AV_PIX_FMT_NONE != format )) {
305+ // yes, we have video stream to decode, but check if we should reopen
306+ // decoder
307+ if (!ctx -> vc || (ctx -> hw_type == AV_HWDEVICE_TYPE_NONE )) {
308+ ret = open_video_decoder (ctx , video_codec );
309+ if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to open video decoder" )
310+ }
289311 } else LPMS_WARN ("No video stream found in input" );
290312
291313 if (!ctx -> da && (ctx -> ai >= 0 )) {
292314 ret = open_audio_decoder (ctx , audio_codec );
293315 if (ret < 0 ) LPMS_ERR (open_input_err , "Unable to open audio decoder" )
294- ctx -> last_frame_a = av_frame_alloc ();
295- if (!ctx -> last_frame_a ) LPMS_ERR (open_input_err , "Unable to alloc last_frame_a" );
296316 } else LPMS_WARN ("No audio stream found in input" );
297317 }
298318
@@ -306,44 +326,19 @@ int open_input(input_params *params, struct input_ctx *ctx)
306326
307327void free_input (struct input_ctx * ictx , enum FreeInputPolicy policy )
308328{
309- if (FORCE_CLOSE_HW_DECODER == policy ) {
310- // This means we are closing everything, so we also want to
311- // remove demuxer
312- if (ictx -> ic ) avformat_close_input (& ictx -> ic );
313- } else {
314- // Otherwise we may want to retain demuxer in certain cases. Note that
315- // this is a lot of effort for very little gain, because demuxer is very
316- // cheap to create and destroy (being software component)
317- if (ictx -> ic ) {
318- // Only mpegts reuse the demuxer for subsequent segments.
319- // Close the demuxer for everything else.
320- // TODO might be reusable with fmp4 ; check!
321- if (!is_mpegts (ictx -> ic )) avformat_close_input (& ictx -> ic );
322- else if (ictx -> ic -> pb ) {
323- // Reset leftovers from demuxer internals to prepare for next segment
324- avio_flush (ictx -> ic -> pb );
325- avformat_flush (ictx -> ic );
326- avio_closep (& ictx -> ic -> pb );
327- }
328- }
329- }
329+ if (ictx -> ic ) avformat_close_input (& ictx -> ic );
330330 ictx -> flushed = 0 ;
331331 ictx -> flushing = 0 ;
332332 ictx -> pkt_diff = 0 ;
333333 ictx -> sentinel_count = 0 ;
334+ // this is allocated elsewhere on first video packet
334335 if (ictx -> first_pkt ) av_packet_free (& ictx -> first_pkt );
335- if (ictx -> ac ) avcodec_free_context (& ictx -> ac );
336336 // video decoder is always closed when it is a SW decoder
337337 // otherwise only when forced
338- int close_vc = ictx -> vc &&
339- ((AV_HWDEVICE_TYPE_NONE == ictx -> hw_type ) || (FORCE_CLOSE_HW_DECODER == policy ));
340- if (close_vc ) {
341- if (ictx -> vc -> hw_device_ctx ) av_buffer_unref (& ictx -> vc -> hw_device_ctx );
342- avcodec_free_context (& ictx -> vc );
343- if (ictx -> hw_device_ctx ) av_buffer_unref (& ictx -> hw_device_ctx );
344- if (ictx -> last_frame_v ) av_frame_free (& ictx -> last_frame_v );
338+ if ((AV_HWDEVICE_TYPE_NONE == ictx -> hw_type ) || (FORCE_CLOSE_HW_DECODER == policy )) {
339+ close_video_decoder (ictx );
345340 }
346- if ( ictx -> last_frame_a ) av_frame_free ( & ictx -> last_frame_a );
347-
341+ // audio decoder is always closed
342+ close_audio_decoder ( ictx );
348343}
349344
0 commit comments