[FFmpeg-devel,v2] Added XV Support

Submitted by Shivam Goyal on April 7, 2019, 6:53 a.m.

Details

Message ID 44851af6-bf54-c6be-98dc-f36f635e2a61@iitk.ac.in
State New
Headers show

Commit Message

Shivam Goyal April 7, 2019, 6:53 a.m.
This time i modified the initial buffer at the time of reading header 
instead of changing the IO layer.

Suggest any changes required.

Comments

Carl Eugen Hoyos April 7, 2019, 10:12 p.m.
2019-04-07 8:53 GMT+02:00, Shivam Goyal <shivgo@iitk.ac.in>:
> This time i modified the initial buffer at the time of reading
> header instead of changing the IO layer.
>
> Suggest any changes required.

Please mention ticket #3720 in the commit message.

> +static int xv_probe(const AVProbeData *p)
> +{
> +    const uint8_t *d = p->buf;
> +
> +    if (d[0] == 'X' &&
> +        d[1] == 'L' &&
> +        d[2] == 'V' &&
> +        d[3] == 'F') {
> +        return AVPROBE_SCORE_MAX;

Should be MAX / 2 + 1 for 32 bit match.

[...]

> +    // For XV file the flv data starts from 0x200000 byte
> +    if(!strcmp(s->iformat->name , "xv")){
> +        for (i=0; i < FFMIN(2,fileposlen); i++){
> +            filepositions[i] += 0x200000;

The comment does not look super useful to me.

> +static int xv_read_header(AVFormatContext *s)

This function contains trailing whitespace that cannot
be committed to the FFmpeg repository, please remove
it.

> +    offset = ((((avio_r8(ic) + rot)&0xff)<<24) |
> +                (((avio_r8(ic) + rot)&0xff)<<16) |
> +                (((avio_r8(ic) + rot)&0xff)<<8) |
> +                (((avio_r8(ic) + rot)&0xff)))+ 0x200000;

Too many parentheses.

> +    // Will modify the current buffer, as only

I don't know if this is something a demuxer is allowed to do,
hopefully another developer will comment.

> +    // the bytes from 0x200000 to 0x200400 are needed to decode
> +    int size = ic->buf_end - ic->buf_ptr;

> +    int64_t pos = ic->pos - size;
> +    for(int i=0;i<0x400; i++){

Maybe I miss something but it looks as if only one of i and
pos should be needed, no? (And size could be merged as
well if that does not make reading the function too difficult.)
In any case, formatting should be:
for (int x = 0; x < 0x123; i++) {

> +        if(pos >= 0x200400) break;

> +        (*(ic->buf_ptr + i)) = (((*(ic->buf_ptr + i)) + rot) & 0xff );

Why is this not "ic->buf_ptr[i] = ic->buf_ptr[..."?
And assuming this is a char*, I would suspect the "& 0xff" is
not necessary.

+        pos+=1;

pos++

Carl Eugen
Steven Liu April 7, 2019, 10:39 p.m.
>+    .long_name      = NULL_IF_CONFIG_SMALL("Xunlie Video File"),

The this should
.long_name      = NULL_IF_CONFIG_SMALL("Xunlei Video File”),
or
.long_name      = NULL_IF_CONFIG_SMALL(“Xunlei(Thunder) Video File”),
Xunlei is Chinese PinYin[pi:n, yi:n]. Application is Thunder.app

> 在 2019年4月7日,14:53,Shivam Goyal <shivgo@iitk.ac.in> 写道:
> 
> <added_xv_support_v2.patch>

Thanks
Steven
Lauri Kasanen April 8, 2019, 6:19 a.m.
On Mon, 8 Apr 2019 06:39:27 +0800
Steven Liu <lq@chinaffmpeg.org> wrote:

> >+    .long_name      = NULL_IF_CONFIG_SMALL("Xunlie Video File"),

XV is a video output format, so please make the title something like
"flv: Add XV (Xunlie Video) support".

- Lauri

Patch hide | download patch | download mbox

From 277a4267f8cbb68c5fa57a0bddd215e04ca662bd Mon Sep 17 00:00:00 2001
From: Shivam Goyal <shivgo@iitk.ac.in>
Date: Sun, 7 Apr 2019 12:13:21 +0530
Subject: [PATCH] Added XV Support

---
 libavformat/Makefile     |  1 +
 libavformat/allformats.c |  1 +
 libavformat/flvdec.c     | 87 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 99be60d184..262df876e9 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -563,6 +563,7 @@  OBJS-$(CONFIG_XBIN_DEMUXER)              += bintext.o sauce.o
 OBJS-$(CONFIG_XMV_DEMUXER)               += xmv.o
 OBJS-$(CONFIG_XVAG_DEMUXER)              += xvag.o
 OBJS-$(CONFIG_XWMA_DEMUXER)              += xwma.o
+OBJS-$(CONFIG_XV_DEMUXER)                += flvdec.o
 OBJS-$(CONFIG_YOP_DEMUXER)               += yop.o
 OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER)      += yuv4mpegdec.o
 OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER)        += yuv4mpegenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index d316a0529a..b499186071 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -456,6 +456,7 @@  extern AVOutputFormat ff_wv_muxer;
 extern AVInputFormat  ff_xa_demuxer;
 extern AVInputFormat  ff_xbin_demuxer;
 extern AVInputFormat  ff_xmv_demuxer;
+extern AVInputFormat  ff_xv_demuxer;
 extern AVInputFormat  ff_xvag_demuxer;
 extern AVInputFormat  ff_xwma_demuxer;
 extern AVInputFormat  ff_yop_demuxer;
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index b531a39adc..df732ca65e 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -127,6 +127,19 @@  static int kux_probe(const AVProbeData *p)
     return 0;
 }
 
+static int xv_probe(const AVProbeData *p)
+{
+    const uint8_t *d = p->buf;
+
+    if (d[0] == 'X' &&
+        d[1] == 'L' &&
+        d[2] == 'V' &&
+        d[3] == 'F') {
+        return AVPROBE_SCORE_MAX;
+    }
+    return 0;
+}
+
 static void add_keyframes_index(AVFormatContext *s)
 {
     FLVContext *flv   = s->priv_data;
@@ -459,6 +472,13 @@  static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t m
         }
     }
 
+    // For XV file the flv data starts from 0x200000 byte
+    if(!strcmp(s->iformat->name , "xv")){
+        for (i=0; i < FFMIN(2,fileposlen); i++){
+            filepositions[i] += 0x200000;
+        }
+    }
+
     if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) {
         for (i = 0; i < FFMIN(2,fileposlen); i++) {
             flv->validate_index[i].pos = filepositions[i];
@@ -783,6 +803,52 @@  static int flv_read_header(AVFormatContext *s)
     return 0;
 }
 
+static int xv_read_header(AVFormatContext *s)
+{
+    int flags;
+    FLVContext *xv = s->priv_data;
+    AVIOContext *ic = s->pb;
+    int offset;
+    int pre_tag_size = 0;
+    int rot;
+
+    //Find the rot value for rotating the bytes
+    avio_seek(ic, 0x200000, SEEK_SET);
+    rot = 0x46 - avio_r8(ic);
+    
+    avio_skip(ic, 3);
+
+    flags = (avio_r8(ic) + rot ) & 0xff;
+
+    xv->missing_streams = flags & (FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO);
+
+    s->ctx_flags |= AVFMTCTX_NOHEADER;
+     
+    offset = ((((avio_r8(ic) + rot)&0xff)<<24) | 
+                (((avio_r8(ic) + rot)&0xff)<<16) |
+                (((avio_r8(ic) + rot)&0xff)<<8) |
+                (((avio_r8(ic) + rot)&0xff)))+ 0x200000;
+
+    avio_seek(ic, offset + 4, SEEK_SET);
+
+
+    // Will modify the current buffer, as only
+    // the bytes from 0x200000 to 0x200400 are needed to decode
+    int size = ic->buf_end - ic->buf_ptr;
+    int64_t pos = ic->pos - size;
+    for(int i=0;i<0x400; i++){
+        if(pos >= 0x200400) break;
+        (*(ic->buf_ptr + i)) = (((*(ic->buf_ptr + i)) + rot) & 0xff );
+        pos+=1;
+    }
+
+    s->start_time = 0;
+    xv->sum_flv_tag_size = 0;
+    xv->last_keyframe_stream_index = -1;
+
+    return 0;
+}
+
 static int flv_read_close(AVFormatContext *s)
 {
     int i;
@@ -1424,3 +1490,24 @@  AVInputFormat ff_kux_demuxer = {
     .extensions     = "kux",
     .priv_class     = &kux_class,
 };
+
+static const AVClass xv_class = {
+    .class_name = "xvdec",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_xv_demuxer = {
+    .name           = "xv",
+    .long_name      = NULL_IF_CONFIG_SMALL("Xunlie Video File"),
+    .priv_data_size = sizeof(FLVContext),
+    .read_probe     = xv_probe,
+    .read_header    = xv_read_header,
+    .read_packet    = flv_read_packet,
+    .read_seek      = flv_read_seek,
+    .read_close     = flv_read_close,
+    .extensions     = "xv",
+    .priv_class     = &xv_class,
+    .flags          = AVFMT_TS_DISCONT
+};
-- 
2.21.0