@@ -339,19 +339,21 @@ void FFmpegReader::UpdateAudioInfo()
339339
340340void FFmpegReader::UpdateVideoInfo ()
341341{
342+ if (check_fps)
343+ // Already initialized all the video metadata, no reason to do it again
344+ return ;
345+
342346 // Set values of FileInfo struct
343347 info.has_video = true ;
344348 info.file_size = pFormatCtx->pb ? avio_size (pFormatCtx->pb ) : -1 ;
345349 info.height = AV_GET_CODEC_ATTRIBUTES (pStream, pCodecCtx)->height ;
346350 info.width = AV_GET_CODEC_ATTRIBUTES (pStream, pCodecCtx)->width ;
347351 info.vcodec = pCodecCtx->codec ->name ;
348- info.video_bit_rate = pFormatCtx->bit_rate ;
349- if (!check_fps)
350- {
351- // set frames per second (fps)
352- info.fps .num = pStream->avg_frame_rate .num ;
353- info.fps .den = pStream->avg_frame_rate .den ;
354- }
352+ info.video_bit_rate = (pFormatCtx->bit_rate / 8 );
353+
354+ // set frames per second (fps)
355+ info.fps .num = pStream->avg_frame_rate .num ;
356+ info.fps .den = pStream->avg_frame_rate .den ;
355357
356358 if (pStream->sample_aspect_ratio .num != 0 )
357359 {
@@ -415,16 +417,10 @@ void FFmpegReader::UpdateVideoInfo()
415417 }
416418
417419 // Override an invalid framerate
418- if (info.fps .ToFloat () > 240 .0f || (info.fps .num == 0 || info.fps .den == 0 ))
419- {
420- // Set a few important default video settings (so audio can be divided into frames)
421- info.fps .num = 24 ;
422- info.fps .den = 1 ;
423- info.video_timebase .num = 1 ;
424- info.video_timebase .den = 24 ;
425-
426- // Calculate number of frames
427- info.video_length = round (info.duration * info.fps .ToDouble ());
420+ if (info.fps .ToFloat () > 240 .0f || (info.fps .num == 0 || info.fps .den == 0 )) {
421+ // Calculate FPS, duration, video bit rate, and video length manually
422+ // by scanning through all the video stream packets
423+ CheckFPS ();
428424 }
429425
430426 // Add video metadata (if any)
@@ -1857,16 +1853,12 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
18571853void FFmpegReader::CheckFPS ()
18581854{
18591855 check_fps = true ;
1860- AV_ALLOCATE_IMAGE (pFrame, AV_GET_CODEC_PIXEL_FORMAT (pStream, pCodecCtx), info.width , info.height );
1861-
18621856 int first_second_counter = 0 ;
18631857 int second_second_counter = 0 ;
18641858 int third_second_counter = 0 ;
18651859 int forth_second_counter = 0 ;
18661860 int fifth_second_counter = 0 ;
1867-
1868- int iterations = 0 ;
1869- int threshold = 500 ;
1861+ int frames_detected = 0 ;
18701862
18711863 // Loop through the stream
18721864 while (true )
@@ -1908,63 +1900,41 @@ void FFmpegReader::CheckFPS()
19081900 forth_second_counter++;
19091901 else if (video_seconds > 4.0 && video_seconds <= 5.0 )
19101902 fifth_second_counter++;
1911- else
1912- // Too far
1913- break ;
1903+
1904+ // Increment counters
1905+ frames_detected++ ;
19141906 }
19151907 }
1916-
1917- // Increment counters
1918- iterations++;
1919-
1920- // Give up (if threshold exceeded)
1921- if (iterations > threshold)
1922- break ;
19231908 }
19241909
19251910 // Double check that all counters have greater than zero (or give up)
1926- if (second_second_counter == 0 || third_second_counter == 0 || forth_second_counter == 0 || fifth_second_counter == 0 )
1927- {
1928- // Seek to frame 1
1929- Seek ( 1 );
1911+ if (second_second_counter != 0 && third_second_counter != 0 && forth_second_counter != 0 && fifth_second_counter != 0 ) {
1912+ // Calculate average FPS
1913+ int sum_fps = second_second_counter + third_second_counter + forth_second_counter + fifth_second_counter;
1914+ int avg_fps = round (sum_fps / 4 . 0f );
19301915
1931- // exit with no changes to FPS (not enough data to calculate)
1932- return ;
1933- }
1916+ // Update FPS
1917+ info.fps = Fraction (avg_fps, 1 );
19341918
1935- int sum_fps = second_second_counter + third_second_counter + forth_second_counter + fifth_second_counter;
1936- int avg_fps = round (sum_fps / 4 .0f );
1919+ // Update Duration and Length
1920+ info.video_length = frames_detected;
1921+ info.duration = frames_detected / round (sum_fps / 4 .0f );
19371922
1938- // Sometimes the FPS is incorrectly detected by FFmpeg. If the 1st and 2nd seconds counters
1939- // agree with each other, we are going to adjust the FPS of this reader instance. Otherwise, print
1940- // a warning message.
1923+ // Update video bit rate
1924+ info. video_bit_rate = info. file_size / info. duration ;
1925+ } else {
19411926
1942- // Get diff from actual frame rate
1943- double fps = info.fps .ToDouble ();
1944- double diff = fps - double (avg_fps);
1945-
1946- // Is difference bigger than 1 frame?
1947- if (diff <= -1 || diff >= 1 )
1948- {
1949- // Compare to half the frame rate (the most common type of issue)
1950- double half_fps = Fraction (info.fps .num / 2 , info.fps .den ).ToDouble ();
1951- diff = half_fps - double (avg_fps);
1927+ // Too short to determine framerate, just default FPS
1928+ // Set a few important default video settings (so audio can be divided into frames)
1929+ info.fps .num = 30 ;
1930+ info.fps .den = 1 ;
1931+ info.video_timebase .num = info.fps .den ;
1932+ info.video_timebase .den = info.fps .num ;
19521933
1953- // Is difference bigger than 1 frame?
1954- if (diff <= -1 || diff >= 1 )
1955- {
1956- // Update FPS for this reader instance
1957- info.fps = Fraction (avg_fps, 1 );
1958- }
1959- else
1960- {
1961- // Update FPS for this reader instance (to 1/2 the original framerate)
1962- info.fps = Fraction (info.fps .num / 2 , info.fps .den );
1963- }
1934+ // Calculate number of frames
1935+ info.video_length = frames_detected;
1936+ info.duration = frames_detected / info.video_timebase .ToFloat ();
19641937 }
1965-
1966- // Seek to frame 1
1967- Seek (1 );
19681938}
19691939
19701940// Remove AVFrame from cache (and deallocate it's memory)
0 commit comments