diff mbox series

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

Message ID 20201024003225.216806-1-mike@keeley.net.nz
State Superseded
Headers show
Series [FFmpeg-devel] avformat/dhav: also support ZLAV packets
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Michael Keeley Oct. 24, 2020, 12:32 a.m. UTC
Some DVRs (e.g. D7008FH made by Zhuhai Ltd) 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@keeley.net.nz>
---
 Changelog             |  1 +
 libavformat/dhav.c    | 31 ++++++++++++++++++++++---------
 libavformat/version.h |  2 +-
 3 files changed, 24 insertions(+), 10 deletions(-)

Comments

Paul B Mahol Oct. 24, 2020, 8:02 a.m. UTC | #1
LGTM

On Sat, Oct 24, 2020 at 2:32 AM Michael Keeley <mike@keeley.net.nz> wrote:

> Some DVRs (e.g. D7008FH made by Zhuhai Ltd) 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@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 21a4be731b..8e289733e2 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -37,6 +37,7 @@ version <next>:
>  - Cintel RAW decoder
>  - VDPAU accelerated VP9 10/12bit decoding
>  - afreqshift and aphaseshift filters
> +- Add ZLAV format to DHAV demuxer
>
>
>  version 4.3:
> diff --git a/libavformat/dhav.c b/libavformat/dhav.c
> index 79afe9be03..e2f3c40065 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) != 0 && memcmp(p->buf, "ZLAV", 4) != 0)
>          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) == 0 || memcmp(signature,
> "ZLAV", 4) == 0) {
>              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 86e0a232ee..7853068649 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  62
> +#define LIBAVFORMAT_VERSION_MINOR  63
>  #define LIBAVFORMAT_VERSION_MICRO 100
>
>  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR,
> \
> --
> 2.25.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Zhao Zhili Oct. 24, 2020, 12:05 p.m. UTC | #2
Hi Michael,

> On Oct 24, 2020, at 8:32 AM, Michael Keeley <mike@keeley.net.nz> wrote:
> 
> Some DVRs (e.g. D7008FH made by Zhuhai Ltd) output the same format .dav file,
> but use ZLAV/zlav tags to delimit the packets instead of DHAV/dhav.

Zhuhai Ltd doesn't look like the real company name. I didn't find much information
about D7008FH. Could you share more informations so I can help figure out the product
model and vendor? Of course, if such information matters.

> 
> Signed-off-by: Michael Keeley <mike@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 21a4be731b..8e289733e2 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -37,6 +37,7 @@ version <next>:
> - Cintel RAW decoder
> - VDPAU accelerated VP9 10/12bit decoding
> - afreqshift and aphaseshift filters
> +- Add ZLAV format to DHAV demuxer
> 
> 
> version 4.3:
> diff --git a/libavformat/dhav.c b/libavformat/dhav.c
> index 79afe9be03..e2f3c40065 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) != 0 && memcmp(p->buf, "ZLAV", 4) != 0)
>         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) == 0 || memcmp(signature, "ZLAV", 4) == 0) {
>             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 86e0a232ee..7853068649 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  62
> +#define LIBAVFORMAT_VERSION_MINOR  63
> #define LIBAVFORMAT_VERSION_MICRO 100
> 
> #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
> -- 
> 2.25.1
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Michael Keeley Oct. 24, 2020, 11:58 p.m. UTC | #3
Hi Zhao,

> > Some DVRs (e.g. D7008FH made by Zhuhai Ltd) output the same format
> .dav file,
> > but use ZLAV/zlav tags to delimit the packets instead of DHAV/dhav.
> 
> Zhuhai Ltd doesn't look like the real company name. I didn't find much
> information
> about D7008FH. Could you share more informations so I can help figure
> out the product
> model and vendor? Of course, if such information matters.
> 

I own this product, and I have attached the PDF manual for the device. There is no branding on the device itself, except for the model number on a sticker underneath.
I googled the model number and found this manual. The company name is actually iSmart Cities (Zhuhai) Limited, I just assumed Zhuhai was the Chinese company name (based on the ZL tag prefix Zhuhai Ltd -> ZL).
But looking closer, I see that's just the city name, whoops!

Of course, this doesn't affect the code, happy to supply more information if you want it.

Mike.
Zhao Zhili Oct. 26, 2020, 3:13 a.m. UTC | #4
> 
> On Oct 25, 2020, at 7:58 AM, Michael Keeley <mike@keeley.net.nz> wrote:
> 
> Hi Zhao,
> 
>>> Some DVRs (e.g. D7008FH made by Zhuhai Ltd) output the same format
>> .dav file,
>>> but use ZLAV/zlav tags to delimit the packets instead of DHAV/dhav.
>> 
>> Zhuhai Ltd doesn't look like the real company name. I didn't find much
>> information
>> about D7008FH. Could you share more informations so I can help figure
>> out the product
>> model and vendor? Of course, if such information matters.
>> 
> 
> I own this product, and I have attached the PDF manual for the device. There is no branding on the device itself, except for the model number on a sticker underneath.
> I googled the model number and found this manual. The company name is actually iSmart Cities (Zhuhai) Limited, I just assumed Zhuhai was the Chinese company name (based on the ZL tag prefix Zhuhai Ltd -> ZL).
> But looking closer, I see that's just the city name, whoops!

Yes, city names are not allowed to be registered as branding names now in China.

> 
> Of course, this doesn't affect the code, happy to supply more information if you want it.

Thank you, this information may help identify or reverse engineer similar device.

> 
> Mike.
> 
> <D7008FH Manual.pdf>_______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org <mailto:ffmpeg-devel@ffmpeg.org>
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org <mailto:ffmpeg-devel-request@ffmpeg.org> with subject "unsubscribe".
Michael Keeley Nov. 1, 2020, 1:44 a.m. UTC | #5
> -----Original Message-----
> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf
> Of Paul B Mahol
> Sent: Saturday, 24 October 2020 9:03 pm
> To: FFmpeg development discussions and patches
> Cc: Michael Keeley
> Subject: Re: [FFmpeg-devel] [PATCH] avformat/dhav: also support ZLAV
> packets
> 
> LGTM
> 

Thanks for the feedback.
Is there anything more I need to do here, or will someone merge it?

Cheers,
Mike.

> On Sat, Oct 24, 2020 at 2:32 AM Michael Keeley <mike@keeley.net.nz>
> wrote:
> 
> > Some DVRs (e.g. D7008FH made by Zhuhai Ltd) 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@keeley.net.nz>
> > ---
> >  Changelog             |  1 +
> >  libavformat/dhav.c    | 31 ++++++++++++++++++++++---------
> >  libavformat/version.h |  2 +-
> >  3 files changed, 24 insertions(+), 10 deletions(-)
> >

<snip>
Moritz Barsnick Nov. 3, 2020, 9:10 p.m. UTC | #6
On Sat, Oct 24, 2020 at 13:32:25 +1300, Michael Keeley wrote:
> -    if (memcmp(p->buf, "DHAV", 4))
> +    if (memcmp(p->buf, "DHAV", 4) != 0 && memcmp(p->buf, "ZLAV", 4) != 0)

The "!= 0" isn't necessary.

> -        if (!memcmp(signature, "DHAV", 4)) {
> +        if (memcmp(signature, "DHAV", 4) == 0 || memcmp(signature, "ZLAV", 4) == 0) {

Also here, ffmpeg prefers the "!memcmp()" style.

Moritz
diff mbox series

Patch

diff --git a/Changelog b/Changelog
index 21a4be731b..8e289733e2 100644
--- a/Changelog
+++ b/Changelog
@@ -37,6 +37,7 @@  version <next>:
 - Cintel RAW decoder
 - VDPAU accelerated VP9 10/12bit decoding
 - afreqshift and aphaseshift filters
+- Add ZLAV format to DHAV demuxer
 
 
 version 4.3:
diff --git a/libavformat/dhav.c b/libavformat/dhav.c
index 79afe9be03..e2f3c40065 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) != 0 && memcmp(p->buf, "ZLAV", 4) != 0)
         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) == 0 || memcmp(signature, "ZLAV", 4) == 0) {
             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 86e0a232ee..7853068649 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  62
+#define LIBAVFORMAT_VERSION_MINOR  63
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \