aviad rozenhek <[email protected]> added the comment:
tested with some more .mov files, all had same problems.
attached more test cases which show the problem.
----------
title: seek to 0 is broken in specific file -> seek to 0 is broken in mov
demuxer
topic: +avformat
________________________________________________
FFmpeg issue tracker <[email protected]>
<https://roundup.ffmpeg.org/issue2046>
________________________________________________
// google unit test framework
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
#include <inttypes.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <intsafe.h>
#endif
extern "C" {
# include <libavformat/avformat.h>
}
static void read_all_streams_after_seek(AVFormatContext* fmt)
{
int read_packets;
int streams_with_read_packet;
int all_streams_with_read_packet;
int64_t first_timestamp, last_timestamp;
AVPacket packet;
AVRational avtimebaseq = {1, AV_TIME_BASE};
read_packets = 0;
streams_with_read_packet = 0;
all_streams_with_read_packet = (1 << fmt->nb_streams) - 1;
first_timestamp = INT64_MAX;
last_timestamp = INT64_MIN;
do {
ASSERT_LE(0, av_read_frame(fmt, &packet));
streams_with_read_packet |= (1 << packet.stream_index);
read_packets++;
first_timestamp = FFMIN(first_timestamp,
av_rescale_q(packet.dts, fmt->streams[packet.stream_index]->time_base,
avtimebaseq));
last_timestamp = FFMAX(last_timestamp ,
av_rescale_q(packet.dts, fmt->streams[packet.stream_index]->time_base,
avtimebaseq));
}
while(streams_with_read_packet != all_streams_with_read_packet);
// we expect to be able to have read a packet from all streams by going
through less than 1000 packets
// the actual value in this specific case is 2 packets
EXPECT_LE(read_packets, 100);
// we expect that there won't be much time difference between the first
and last timestamp encountered
// the actual value in this specific case is 19139 ( = ~19ms )
EXPECT_LE(last_timestamp - first_timestamp, 5 * AV_TIME_BASE);
}
TEST(AVFormat, seek_test1)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek 20 minutes forward
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 20 * 60 * AV_TIME_BASE,
0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test2)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to end
ASSERT_LE(0, result = avformat_seek_file(fmt, -1, INT64_MIN,
fmt->duration, INT64_MAX, 0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test3)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to 20 minutes
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 20 * 60 * AV_TIME_BASE,
0));
read_all_streams_after_seek(fmt);
/// seek to 0
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 0, 0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test4)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to end
ASSERT_LE(0, result = av_seek_frame(fmt, -1, fmt->duration,
AVSEEK_FLAG_BACKWARD));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test_end)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to 20 minutes
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 20 * 60 * AV_TIME_BASE,
0));
read_all_streams_after_seek(fmt);
/// seek to end
ASSERT_LE(0, result = avformat_seek_file(fmt, -1, 0, 0, fmt->duration,
0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test_begin)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to end
ASSERT_LE(0, result = avformat_seek_file(fmt, -1, 0, fmt->duration,
fmt->duration, 0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test_fails1)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to end
/// XXX: this fails
ASSERT_LE(0, result = av_seek_frame(fmt, -1, fmt->duration, 0));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}
TEST(AVFormat, seek_test_fails2)
{
int result;
AVFormatContext* fmt;
ASSERT_EQ(0, result = av_open_input_file(&fmt,
"\\\\mediafiles\\public\\support\\demo\\PlanetEarth.Jungles.1080i.DivX.AC3.mkv.mp4",
NULL, 0, NULL));
ASSERT_LE(0, result = av_find_stream_info(fmt));
/// seek to 20 minutes
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 20 * 60 * AV_TIME_BASE,
0));
read_all_streams_after_seek(fmt);
// seek back to 0
// XXX: this seems not to work properly for this file! see failed
asserts below
ASSERT_LE(0, result = av_seek_frame(fmt, -1, 0, AVSEEK_FLAG_BACKWARD));
read_all_streams_after_seek(fmt);
av_close_input_stream(fmt);
}