[FFmpeg-devel] [PATCH v2] avformat/dhav: also support ZLAV packets

Zane van Iperen zane at zanevaniperen.com
Sat Nov 14 14:58:22 EET 2020



On 8/11/20 7:41 pm, Michael Keeley wrote:
> Some DVRs (e.g. D7008FH made by iSmart Cities (Zhuhai) Limited) output the same format .dav file,
> but use ZLAV/zlav tags to delimit the packets instead of DHAV/dhav.
> 
> Signed-off-by: Michael Keeley <mike at keeley.net.nz>
> ---
>   Changelog             |  1 +
>   libavformat/dhav.c    | 31 ++++++++++++++++++++++---------
>   libavformat/version.h |  2 +-
>   3 files changed, 24 insertions(+), 10 deletions(-)
> 
> diff --git a/Changelog b/Changelog
> index 0ea1901bbe..a56216543d 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -41,6 +41,7 @@ version <next>:
>   - LEGO Racers ALP (.tun & .pcm) muxer
>   - AV1 VAAPI decoder
>   - adenorm filter
> +- Add ZLAV format to DHAV demuxer

Just make this "ZLAV demuxer" or something similar.

>   
>   
>   version 4.3:
> diff --git a/libavformat/dhav.c b/libavformat/dhav.c
> index 53deaff77e..40c2cc78b0 100644
> --- a/libavformat/dhav.c
> +++ b/libavformat/dhav.c
> @@ -1,5 +1,5 @@
>   /*
> - * DHAV demuxer
> + * DHAV/ZLAV demuxer
>    *
>    * Copyright (c) 2018 Paul B Mahol
>    *
> @@ -57,7 +57,7 @@ static int dhav_probe(const AVProbeData *p)
>       if (!memcmp(p->buf, "DAHUA", 5))
>           return AVPROBE_SCORE_MAX;
>   
> -    if (memcmp(p->buf, "DHAV", 4))
> +    if (memcmp(p->buf, "DHAV", 4) && memcmp(p->buf, "ZLAV", 4))
>           return 0;
>   
>       if (p->buf[4] == 0xf0 ||
> @@ -163,6 +163,19 @@ static int parse_ext(AVFormatContext *s, int length)
>       return 0;
>   }
>   
> +static int read_start_tag(AVIOContext *pb)
> +{
> +    unsigned int start_tag = avio_rl32(pb);
> +    return start_tag == MKTAG('D','H','A','V') || start_tag == MKTAG('Z','L','A','V');
> +}
> +
> +static int read_end_tag(AVIOContext *pb)
> +{
> +    unsigned int end_tag = avio_rl32(pb);
> +    return end_tag == MKTAG('d','h','a','v') || end_tag == MKTAG('z','l','a','v');
> +}
> +
> +
>   static int read_chunk(AVFormatContext *s)
>   {
>       DHAVContext *dhav = s->priv_data;
> @@ -173,11 +186,11 @@ static int read_chunk(AVFormatContext *s)
>       if (avio_feof(s->pb))
>           return AVERROR_EOF;
>   
> -    if (avio_rl32(s->pb) != MKTAG('D','H','A','V')) {
> +    if (!read_start_tag(s->pb)) {
>           dhav->last_good_pos += 0x8000;
>           avio_seek(s->pb, dhav->last_good_pos, SEEK_SET);
>   
> -        while (avio_rl32(s->pb) != MKTAG('D','H','A','V')) {
> +        while (!read_start_tag(s->pb)) {
>               if (avio_feof(s->pb))
>                   return AVERROR_EOF;
>               dhav->last_good_pos += 0x8000;
> @@ -247,7 +260,7 @@ static int64_t get_duration(AVFormatContext *s)
>           return 0;
>   
>       avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET);
> -    if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) {
> +    if (read_end_tag(s->pb)) {
>           int seek_back = avio_rl32(s->pb);
>   
>           avio_seek(s->pb, -seek_back, SEEK_CUR);
> @@ -281,12 +294,12 @@ static int dhav_read_header(AVFormatContext *s)
>           avio_skip(s->pb, 0x400 - 5);
>           dhav->last_good_pos = avio_tell(s->pb);
>       } else {
> -        if (!memcmp(signature, "DHAV", 4)) {
> +        if (!memcmp(signature, "DHAV", 4) || !memcmp(signature, "ZLAV", 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')) {
> +            while (read_end_tag(s->pb)) {
>                   int seek_back;
>   
>                   seek_back = avio_rl32(s->pb) + 8;
> @@ -409,7 +422,7 @@ retry:
>       stream_index = dhav->type == 0xf0 ? dhav->audio_stream_index : dhav->video_stream_index;
>       if (stream_index < 0) {
>           avio_skip(s->pb, ret);
> -        if (avio_rl32(s->pb) == MKTAG('d','h','a','v'))
> +        if (read_end_tag(s->pb))
>               avio_skip(s->pb, 4);
>           goto retry;
>       }
> @@ -425,7 +438,7 @@ retry:
>       if (pkt->stream_index >= 0)
>           pkt->pts = get_pts(s, pkt->stream_index);
>       pkt->pos = dhav->last_good_pos;
> -    if (avio_rl32(s->pb) == MKTAG('d','h','a','v'))
> +    if (read_end_tag(s->pb))
>           avio_skip(s->pb, 4);
>   
>       return ret;
> diff --git a/libavformat/version.h b/libavformat/version.h
> index ddcca9ae50..b43193bcb1 100644
> --- a/libavformat/version.h
> +++ b/libavformat/version.h
> @@ -32,7 +32,7 @@
>   // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
>   // Also please add any ticket numbers that you believe might be affected here
>   #define LIBAVFORMAT_VERSION_MAJOR  58
> -#define LIBAVFORMAT_VERSION_MINOR  64
> +#define LIBAVFORMAT_VERSION_MINOR  65
>   #define LIBAVFORMAT_VERSION_MICRO 100
>   
>   #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
> 

This looks mostly alright to me at a glance.

One thing to note, this would accept packets starting with "DHAV" and ending
with "zlav" (and vice versa).

Could this be a problem? If so, might it be worth storing the current "type"
and ensuring you get the correct delimiter?



More information about the ffmpeg-devel mailing list