The patch is for ticket #5154. 

Support for h264 stream from Arecont Camera, The video contains a http
header at several places in the stream, which makes it not possible to
demux, the structure of the http header is- 

--fbdr 
Content-Type: video/H.264I 
ETag: Channel=1 

( there are two CR+LF characters at the end ) 

I also detected the stream by detecting this header. For the video to
play, i removed the header. The function arecont_find_sign() searches
for the signature  and returns its position, (-1 when not found ). 

Also, in the function read_raw_arecont_h264_packet, i used two variables
to store data, the 'pkt->data' and 'data'. I first filled the 'data' and
find the position of http header ( if it is present) and copied the
bytes before the position of the http header, skipped the header, and
again did the same thing for rest of the bytes. also as the packet can
contain partial header at the beginning and end of the pkt, i took extra
size to read from the input stream 

Please review 

Thank You 

Shivam Goyal
From deb859ff488c500b7e6005e350f04c200f2853a4 Mon Sep 17 00:00:00 2001
From: Shivam Goyal <shivamgoyal1...@outlook.com>
Date: Thu, 9 May 2019 23:18:13 +0530
Subject: [PATCH] lavf/h264: Add support for h264 video from Arecont Camera,
 Fixes ticket #5154

---
 Changelog                |   1 +
 libavformat/Makefile     |   1 +
 libavformat/allformats.c |   1 +
 libavformat/h264dec.c    | 127 +++++++++++++++++++++++++++++++++++++++
 libavformat/version.h    |   4 +-
 5 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/Changelog b/Changelog
index a3fa0c14a2..0733e360fc 100644
--- a/Changelog
+++ b/Changelog
@@ -26,6 +26,7 @@ version <next>:
 - lscr decoder
 - lagfun filter
 - asoftclip filter
+- Support for raw h264 video from Arecont camera
 
 
 version 4.1:
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 99be60d184..be0f286870 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -99,6 +99,7 @@ OBJS-$(CONFIG_APTX_MUXER)                += rawenc.o
 OBJS-$(CONFIG_APTX_HD_DEMUXER)           += aptxdec.o rawdec.o
 OBJS-$(CONFIG_APTX_HD_MUXER)             += rawenc.o
 OBJS-$(CONFIG_AQTITLE_DEMUXER)           += aqtitledec.o subtitles.o
+OBJS-$(CONFIG_ARECONT_H264_DEMUXER)      += h264dec.o rawdec.o
 OBJS-$(CONFIG_ASF_DEMUXER)               += asfdec_f.o asf.o asfcrypt.o \
                                             avlanguage.o
 OBJS-$(CONFIG_ASF_O_DEMUXER)             += asfdec_o.o asf.o asfcrypt.o \
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index d316a0529a..fff8083172 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -60,6 +60,7 @@ extern AVOutputFormat ff_aptx_muxer;
 extern AVInputFormat  ff_aptx_hd_demuxer;
 extern AVOutputFormat ff_aptx_hd_muxer;
 extern AVInputFormat  ff_aqtitle_demuxer;
+extern AVInputFormat  ff_arecont_h264_demuxer;
 extern AVInputFormat  ff_asf_demuxer;
 extern AVOutputFormat ff_asf_muxer;
 extern AVInputFormat  ff_asf_o_demuxer;
diff --git a/libavformat/h264dec.c b/libavformat/h264dec.c
index 199e87fbfa..99d7f85b40 100644
--- a/libavformat/h264dec.c
+++ b/libavformat/h264dec.c
@@ -28,6 +28,9 @@
 #define MAX_SPS_COUNT          32
 #define MAX_PPS_COUNT         256
 
+#define ARECONT_H264_MIME_SIZE  100
+#define RAW_PACKET_SIZE         1024
+
 static int h264_probe(const AVProbeData *p)
 {
     uint32_t code = -1;
@@ -117,4 +120,128 @@ static int h264_probe(const AVProbeData *p)
     return 0;
 }
 
+static const uint8_t arecont_sign[] = {0x2D, 0x2D, 0x66, 0x62, 0x64, 0x72, 0x0D, 0x0A};
+
+static int arecont_find_sign(unsigned char *data, int size)
+{
+    unsigned char *j;
+    int sign_size = sizeof(arecont_sign) / sizeof(arecont_sign[0]);
+
+    j = memchr(data, arecont_sign[0], size);
+    while (j != NULL && size - sign_size >= (j - data)) {
+        if (!memcmp(arecont_sign, j, sign_size))
+            return (j - data);
+        if (size - sign_size == (j - data))
+            return -1;
+        j = memchr(data + (j - data) + 1, arecont_sign[0], size - (j - data));
+    }
+    return -1;
+}
+
+static int arecont_h264_probe(const AVProbeData *p)
+{
+    int ret = h264_probe(p);
+
+    if (!ret)
+        return 0;
+    if (arecont_find_sign(p->buf, p->buf_size) >= 0)
+        return ret + 1;
+    return 0;
+}
+
+static int read_raw_arecont_h264_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    int ret, size, start, end, new_size = 0, i = 0, j = 0, k = 0, w = 0;
+    uint8_t *data;
+    int64_t pos;
+    int sign_size = sizeof(arecont_sign) / sizeof(arecont_sign[0]);
+
+    //Extra to find the http header
+    size = 2 * ARECONT_H264_MIME_SIZE + RAW_PACKET_SIZE;
+
+    if (av_new_packet(pkt, size) < 0)
+        return AVERROR(ENOMEM);
+
+    pkt->pos = avio_tell(s->pb);
+    pkt->stream_index = 0;
+    pos = avio_tell(s->pb);
+
+    data = av_malloc(size);
+    ret = avio_read_partial(s->pb, data, size);
+    if (ret < 0) {
+        av_free(data);
+        av_packet_unref(pkt);
+        return ret;
+    }
+    if (pos <= ARECONT_H264_MIME_SIZE) {
+        avio_seek(s->pb, 0, SEEK_SET);
+        start = pos;
+    } else {
+        avio_seek(s->pb, pos - ARECONT_H264_MIME_SIZE, SEEK_SET);
+        start = ARECONT_H264_MIME_SIZE;
+    }
+    ret = avio_read_partial(s->pb, data, size);
+    if (ret < 0 || start >= ret) {
+        av_free(data);
+        av_packet_unref(pkt);
+        return ret;
+    }
+    if (start + RAW_PACKET_SIZE > ret) {
+        end = ret - 1;
+    } else
+        end = start + RAW_PACKET_SIZE - 1;
+
+
+    // Search and remove the http header
+    for (;;) {
+        if ((j = arecont_find_sign(data + i, ret - i)) >= 0) {
+            k = 0;
+            for (w = j + sign_size; w + 1 < ret; w++) {
+                if (!(data[w] == 0x0D && data[w + 1] == 0x0A))
+                    continue;
+                k++;
+                if (k < 3)
+                    continue;
+                if (j < start) {
+                    i = w + 2;
+                    break;
+                }
+                memcpy(pkt->data + new_size, data + FFMAX(i, start), FFMIN(j, end + 1) - FFMAX(i, start));
+                new_size +=  FFMIN(j, end + 1) - FFMAX(i, start);
+                i = w + 2;
+                break;
+            }
+        } else
+            break;
+    }
+    if (i < end) {
+        memcpy(pkt->data + new_size, data + FFMAX(i, start), end + 1 - FFMAX(i, start));
+        new_size += end + 1 - FFMAX(i, start);
+    }
+    avio_seek(s->pb, pos + end - start + 1, SEEK_SET);
+    av_shrink_packet(pkt, new_size);
+    av_free(data);
+    return new_size;
+}
+
 FF_DEF_RAWVIDEO_DEMUXER(h264, "raw H.264 video", h264_probe, "h26l,h264,264,avc", AV_CODEC_ID_H264)
+
+static const AVClass arecont_h264_class = {
+    .class_name = "arecont_h264_dec",
+    .item_name  = av_default_item_name,
+    .option     = ff_rawvideo_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_arecont_h264_demuxer = {
+    .name           = "arecont_h264",
+    .long_name      = NULL_IF_CONFIG_SMALL("raw H.264 video from Arecont camera"),
+    .read_probe     = arecont_h264_probe,
+    .read_header    = ff_raw_video_read_header,
+    .read_packet    = read_raw_arecont_h264_packet,
+    .extensions     = "",
+    .flags          = AVFMT_GENERIC_INDEX,
+    .raw_codec_id   = AV_CODEC_ID_H264,
+    .priv_data_size = sizeof(FFRawVideoDemuxerContext),
+    .priv_class     = &arecont_h264_class,
+};
\ No newline at end of file
diff --git a/libavformat/version.h b/libavformat/version.h
index 150a72e27d..52dd95f5c6 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,8 +32,8 @@
 // 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  27
-#define LIBAVFORMAT_VERSION_MICRO 103
+#define LIBAVFORMAT_VERSION_MINOR  28
+#define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
2.21.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to