+ avio_seek(s->pb, -seek_back, SEEK_CUR);
+ read_chunk(s);
+ get_timeinfo(dhav->date, &timeinfo);
+ end = av_timegm(&timeinfo) * 1000LL;
+ } else {
+ avio_seek(s->pb, start_pos, SEEK_SET);
+ return 0;
+ }
+
+ avio_seek(s->pb, start_pos, SEEK_SET);
+
+ read_chunk(s);
+ get_timeinfo(dhav->date, &timeinfo);
+ start = av_timegm(&timeinfo) * 1000LL;
+
+ avio_seek(s->pb, start_pos, SEEK_SET);
+
+ return end - start;
+}
+
+static int dhav_read_header(AVFormatContext *s)
+{
+ DHAVContext *dhav = s->priv_data;
+ uint8_t signature[5];
+
+ ffio_ensure_seekback(s->pb, 5);
+ avio_read(s->pb, signature, sizeof(signature));
+ if (!memcmp(signature, "DAHUA", 5)) {
+ avio_skip(s->pb, 0x400 - 5);
+ dhav->last_good_pos = avio_tell(s->pb);
+ } else {
+ if (!memcmp(signature, "DHAV", 4)) {
+ avio_seek(s->pb, -5, SEEK_CUR);
+ dhav->last_good_pos = avio_tell(s->pb);
+ } else if (s->pb->seekable) {
+ avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET);
+ while (avio_rl32(s->pb) == MKTAG('d','h','a','v')) {
+ int seek_back;
+
+ seek_back = avio_rl32(s->pb) + 8;
+ if (seek_back < 9)
+ break;
+ dhav->last_good_pos = avio_tell(s->pb);
+ avio_seek(s->pb, -seek_back, SEEK_CUR);
+ }
+ avio_seek(s->pb, dhav->last_good_pos, SEEK_SET);
+ }
+ }
+
+ dhav->duration = get_duration(s);
+ dhav->last_good_pos = avio_tell(s->pb);
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ dhav->video_stream_index = -1;
+ dhav->audio_stream_index = -1;
+
+ return 0;
+}
+
+static int64_t get_pts(AVFormatContext *s, int stream_index)
+{
+ DHAVStream *dst = s->streams[stream_index]->priv_data;
+ DHAVContext *dhav = s->priv_data;
+ struct tm timeinfo;
+ time_t t;
+
+ get_timeinfo(dhav->date, &timeinfo);
+
+ t = av_timegm(&timeinfo);
+ if (dst->last_time == t) {
+ int64_t diff = dhav->timestamp - dst->last_timestamp;
+
+ if (diff < 0)
+ diff += 65535;
+ dst->pts += diff;
+ } else {
+ dst->pts = t * 1000LL;
+ }
+
+ dst->last_time = t;
+ dst->last_timestamp = dhav->timestamp;
+
+ return dst->pts;
+}
+
+static int dhav_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ DHAVContext *dhav = s->priv_data;
+ int size, ret, stream_index;
+
+retry: