[FFmpeg-devel] [PATCH v2] avcodec/v4l2_m2m_dec: resolve resolution change

2023-06-30 Thread Hsia-Jun Li
From: "Hsia-Jun(Randy) Li" 

It shouldn't allocate buffer nor get the capture fmt before
the resolution change event appeared in decoder setup.

And it should not apply to new resolution before
the buffer from the previous sequence is dequeued.

Changelog:
v2
1. Decoder won't get or set format before dynamic resolution
change event is received.
2. Decoder won't need order V4L2_DEC_CMD_START before
STREAMON.
3. Decoder would reallocate buffer when either capture
pixel fmt or image sizes changed.

Change-Id: Id04550b0f17e1501b670a3bcbdd860d5836259bf
Signed-off-by: Hsia-Jun(Randy) Li 
---
 libavcodec/v4l2_context.c | 114 +++---
 libavcodec/v4l2_context.h |   6 ++
 libavcodec/v4l2_m2m.c |  12 ++--
 libavcodec/v4l2_m2m_dec.c |  14 +++--
 4 files changed, 102 insertions(+), 44 deletions(-)

diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index a40be94690..d0f45b445e 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -81,15 +81,36 @@ static AVRational v4l2_get_sar(V4L2Context *ctx)
 return sar;
 }
 
+static inline unsigned int v4l2_sizeimage_changed(struct 
v4l2_pix_format_mplane *fmt1,
+  struct 
v4l2_pix_format_mplane *fmt2)
+{
+unsigned int i;
+
+if (fmt1->num_planes != fmt2->num_planes)
+return 1;
+
+
+for (i = 0; i < fmt2->num_planes; i++) {
+if (fmt1->plane_fmt[i].sizeimage < fmt2->plane_fmt[i].sizeimage)
+return 1;
+}
+
+return 0;
+}
+
 static inline unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct 
v4l2_format *fmt2)
 {
 struct v4l2_format *fmt1 = >format;
 int ret =  V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
+fmt1->fmt.pix_mp.pixelformat != fmt2->fmt.pix_mp.pixelformat ||
 fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width ||
-fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height
+fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height ||
+v4l2_sizeimage_changed(>fmt.pix_mp, >fmt.pix_mp)
 :
+fmt1->fmt.pix.pixelformat != fmt2->fmt.pix.pixelformat ||
 fmt1->fmt.pix.width != fmt2->fmt.pix.width ||
-fmt1->fmt.pix.height != fmt2->fmt.pix.height;
+fmt1->fmt.pix.height != fmt2->fmt.pix.height ||
+fmt1->fmt.pix.sizeimage != fmt2->fmt.pix.sizeimage;
 
 if (ret)
 av_log(logger(ctx), AV_LOG_DEBUG, "%s changed (%dx%d) -> (%dx%d)\n",
@@ -169,30 +190,17 @@ static int v4l2_start_decode(V4L2Context *ctx)
 }
 
 /**
- * handle resolution change event and end of stream event
+ * handle resolution change event
  * returns 1 if reinit was successful, negative if it failed
  * returns 0 if reinit was not executed
  */
-static int v4l2_handle_event(V4L2Context *ctx)
+static int v4l2_handle_dyn_res_change(V4L2Context *ctx)
 {
 V4L2m2mContext *s = ctx_to_m2mctx(ctx);
 struct v4l2_format cap_fmt = s->capture.format;
-struct v4l2_event evt = { 0 };
 int ret;
 
-ret = ioctl(s->fd, VIDIOC_DQEVENT, );
-if (ret < 0) {
-av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
-return 0;
-}
-
-if (evt.type == V4L2_EVENT_EOS) {
-ctx->done = 1;
-return 0;
-}
-
-if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
-return 0;
+cap_fmt.type = s->capture.type;
 
 ret = ioctl(s->fd, VIDIOC_G_FMT, _fmt);
 if (ret) {
@@ -201,11 +209,13 @@ static int v4l2_handle_event(V4L2Context *ctx)
 }
 
 if (v4l2_resolution_changed(>capture, _fmt)) {
+s->capture.format.fmt.pix_mp.pixelformat = 
cap_fmt.fmt.pix_mp.pixelformat;
 s->capture.height = v4l2_get_height(_fmt);
 s->capture.width = v4l2_get_width(_fmt);
 s->capture.sample_aspect_ratio = v4l2_get_sar(>capture);
 } else {
 v4l2_start_decode(ctx);
+ctx->pending_res_change = 0;
 return 0;
 }
 
@@ -222,10 +232,41 @@ static int v4l2_handle_event(V4L2Context *ctx)
 return AVERROR(EINVAL);
 }
 
+ctx->pending_res_change = 0;
 /* reinit executed */
 return 1;
 }
 
+/**
+ * capture resolution change event and end of stream event
+ * returns 1 or negative if it failed
+ * returns 0 if nothing went wrong
+ */
+static int v4l2_handle_event(V4L2Context *ctx)
+{
+V4L2m2mContext *s = ctx_to_m2mctx(ctx);
+struct v4l2_event evt = { 0 };
+int ret;
+
+ret = ioctl(s->fd, VIDIOC_DQEVENT, );
+if (ret < 0) {
+av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
+return errno;
+}
+
+if (evt.type == V4L2_EVENT_EOS) {
+ctx->done = 1;
+return 0;
+}
+
+if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
+return AVERROR(EINVAL);
+
+ctx->pending_res_change = 1;
+
+return 0;
+}
+
 static int v4l2_stop_decode(V4L2Context *ctx)
 {
 struct v4l2_decoder_cmd cmd = {
@@ -342,16 +383,19 @@ start:
 /* 1. handle resolution changes */
 if (pfd.revents & POLLPRI) {
 ret = 

[FFmpeg-devel] [PATCH] avcodec/v4l2_m2m_dec: resolve resolution change

2023-06-29 Thread Hsia-Jun Li

It shouldn't allocate buffer before the resolution
change event appeared in decoder setup.

And it should not apply to new resolution before
the buffer from the previous sequence is dequeued.

Change-Id: Id04550b0f17e1501b670a3bcbdd860d5836259bf
Signed-off-by: Hsia-Jun(Randy) Li
---
 libavcodec/v4l2_context.c | 89 ++-
 libavcodec/v4l2_context.h |  6 +++
 libavcodec/v4l2_m2m_dec.c | 14 +++---
 3 files changed, 73 insertions(+), 36 deletions(-)

diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index a40be94690..87771601a9 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -169,30 +169,17 @@ static int v4l2_start_decode(V4L2Context *ctx)
 }

 /**
- * handle resolution change event and end of stream event
+ * handle resolution change event
  * returns 1 if reinit was successful, negative if it failed
  * returns 0 if reinit was not executed
  */
-static int v4l2_handle_event(V4L2Context *ctx)
+static int v4l2_handle_dyn_res_change(V4L2Context *ctx)
 {
 V4L2m2mContext *s = ctx_to_m2mctx(ctx);
 struct v4l2_format cap_fmt = s->capture.format;
-    struct v4l2_event evt = { 0 };
 int ret;

-    ret = ioctl(s->fd, VIDIOC_DQEVENT, );
-    if (ret < 0) {
-    av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", 
ctx->name);

-    return 0;
-    }
-
-    if (evt.type == V4L2_EVENT_EOS) {
-    ctx->done = 1;
-    return 0;
-    }
-
-    if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
-    return 0;
+    cap_fmt.type = s->capture.type;

 ret = ioctl(s->fd, VIDIOC_G_FMT, _fmt);
 if (ret) {
@@ -201,11 +188,13 @@ static int v4l2_handle_event(V4L2Context *ctx)
 }

 if (v4l2_resolution_changed(>capture, _fmt)) {
+    s->capture.format.fmt.pix_mp.pixelformat = 
cap_fmt.fmt.pix_mp.pixelformat;

 s->capture.height = v4l2_get_height(_fmt);
 s->capture.width = v4l2_get_width(_fmt);
 s->capture.sample_aspect_ratio = v4l2_get_sar(>capture);
 } else {
 v4l2_start_decode(ctx);
+    ctx->pending_res_change = 0;
 return 0;
 }

@@ -222,10 +211,41 @@ static int v4l2_handle_event(V4L2Context *ctx)
 return AVERROR(EINVAL);
 }

+    ctx->pending_res_change = 0;
 /* reinit executed */
 return 1;
 }

+/**
+ * capture resolution change event and end of stream event
+ * returns 1 or negative if it failed
+ * returns 0 if nothing went wrong
+ */
+static int v4l2_handle_event(V4L2Context *ctx)
+{
+    V4L2m2mContext *s = ctx_to_m2mctx(ctx);
+    struct v4l2_event evt = { 0 };
+    int ret;
+
+    ret = ioctl(s->fd, VIDIOC_DQEVENT, );
+    if (ret < 0) {
+    av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", 
ctx->name);

+    return errno;
+    }
+
+    if (evt.type == V4L2_EVENT_EOS) {
+    ctx->done = 1;
+    return 0;
+    }
+
+    if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
+    return AVERROR(EINVAL);
+
+    ctx->pending_res_change = 1;
+
+    return 0;
+}
+
 static int v4l2_stop_decode(V4L2Context *ctx)
 {
 struct v4l2_decoder_cmd cmd = {
@@ -342,16 +362,19 @@ start:
 /* 1. handle resolution changes */
 if (pfd.revents & POLLPRI) {
 ret = v4l2_handle_event(ctx);
-    if (ret < 0) {
-    /* if re-init failed, abort */
-    ctx->done = 1;
-    return NULL;
-    }
 if (ret) {
-    /* if re-init was successful drop the buffer (if there was 
one)

- * since we had to reconfigure capture (unmap all buffers)
- */
+    /* if event handler failed, abort */
+    ctx->done = 1;
 return NULL;
+    } else if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+    if (!ctx->streamon)
+    ret = v4l2_handle_dyn_res_change(ctx);
+    if (ret == 1)
+    return NULL;
+    } else {
+    /* Poll the device again, we want the buffer with the flag
+ * that answer to the event */
+    return v4l2_dequeue_v4l2buf(ctx, timeout);
 }
 }

@@ -391,17 +414,23 @@ dequeue:
 return NULL;
 }

-    if (ctx_to_m2mctx(ctx)->draining && 
!V4L2_TYPE_IS_OUTPUT(ctx->type)) {

+    if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
 int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ?
 buf.m.planes[0].bytesused : buf.bytesused;
+
+#ifdef V4L2_BUF_FLAG_LAST
+    if (buf.flags & V4L2_BUF_FLAG_LAST) {
+    if (ctx_to_m2mctx(ctx)->draining)
+    ctx->done = 1;
+    if (ctx->pending_res_change)
+    ret = v4l2_handle_dyn_res_change(ctx);
+    }
+#endif
 if (bytesused == 0) {
-    ctx->done = 1;
+    if (ctx_to_m2mctx(ctx)->draining)
+    ctx->done = 1;
 return NULL;
 }
-#ifdef V4L2_BUF_FLAG_LAST
-    if (buf.flags & V4L2_BUF_FLAG_LAST)
-

[FFmpeg-devel] [PATCH v1] ffplay: remove unused code

2020-09-09 Thread Jun Li
Signed-off-by: Jun Li 
---
 fftools/ffplay.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 9ff0425163..04cbcfe0e3 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -1568,7 +1568,7 @@ static double vp_duration(VideoState *is, Frame *vp, 
Frame *nextvp) {
 }
 }
 
-static void update_video_pts(VideoState *is, double pts, int64_t pos, int 
serial) {
+static void update_video_pts(VideoState *is, double pts, int serial) {
 /* update current video pts */
 set_clock(>vidclk, pts, serial);
 sync_clock_to_slave(>extclk, >vidclk);
@@ -1633,7 +1633,7 @@ retry:
 
 SDL_LockMutex(is->pictq.mutex);
 if (!isnan(vp->pts))
-update_video_pts(is, vp->pts, vp->pos, vp->serial);
+update_video_pts(is, vp->pts, vp->serial);
 SDL_UnlockMutex(is->pictq.mutex);
 
 if (frame_queue_nb_remaining(>pictq) > 1) {
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [avfomat/rtp: source ips lost when specified as URL options] Patch for ffmpeg using rtp protocol where sources option is not retained

2020-02-25 Thread Jun Li
On Tue, Feb 25, 2020 at 5:01 AM Ross Nicholson  wrote:

> Hey Jun Li,
>
> I noticed you have submitted some patches which work around the same code
> area's that I submitted for. Your patches look quite tidy and well thought
> out so I was wondering if you could look at this patch and see if I'm going
> about it in the right way.
>
> I'm not sure this area of ffmpeg currently has a maintainer currently so
> the patches may be difficult to progress.
>
> Ross
>
> On Tue, 11 Feb 2020 at 22:42, Ross Nicholson  wrote:
>
>> The patch was created as a workaround to an issue from in kodi
>> (apologies, it's a rather long thread):
>> https://forum.kodi.tv/showthread.php?tid=350901=2923550#pid2923550
>>
>> As an example, here is a URL: rtp://87.141.215.251@232.0.10.234:1
>>
>> Taking this URL we should be able to either reformat it to: rtp://
>> 232.0.10.234:1?sources=87.141.215.251 or pass the sources as an
>> av_dict to avfomat_open_input.
>>
>> Neither option works however. Instead the above workaround was created
>> but it's not really the right way to fix this. Would be great to get some
>> guidance on the right place to fix this in the right way.
>>
>> Thanks in advance.
>>
>> On Tue, 11 Feb 2020 at 22:30, phunkyfish  wrote:
>>
>>> ---
>>>  libavformat/rtsp.c | 26 --
>>>  1 file changed, 24 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
>>> index 859defa592..f922055134 100644
>>> --- a/libavformat/rtsp.c
>>> +++ b/libavformat/rtsp.c
>>> @@ -2334,7 +2334,9 @@ static int sdp_read_header(AVFormatContext *s)
>>>  RTSPStream *rtsp_st;
>>>  int size, i, err;
>>>  char *content;
>>> +const char *p, *sp="", *sources="", *sp2, *sources2;
>>>  char url[1024];
>>> +char sources_buf[1024];
>>>
>>>  if (!ff_network_init())
>>>  return AVERROR(EIO);
>>> @@ -2360,6 +2362,16 @@ static int sdp_read_header(AVFormatContext *s)
>>>  av_freep();
>>>  if (err) goto fail;
>>>
>>> +/* Search for sources= tag in original URL for rtp protocol only */
>>> +if (strncmp(s->url, "rtp://", 6) == 0) {
>>> +p = strchr(s->url, '?');
>>> +if (p && av_find_info_tag(sources_buf, sizeof(sources_buf),
>>> "sources", p)) {
>>> +/* av_log(s, AV_LOG_VERBOSE, "sdp_read_header found sources
>>> %s\n", sources_buf);  */
>>> +sp = sources_buf;
>>> +sources = "=";
>>> +}
>>> +}
>>> +
>>>  /* open each RTP stream */
>>>  for (i = 0; i < rt->nb_rtsp_streams; i++) {
>>>  char namebuf[50];
>>> @@ -2377,12 +2389,22 @@ static int sdp_read_header(AVFormatContext *s)
>>>  av_dict_free();
>>>  goto fail;
>>>  }
>>> +
>>> +/* Prepare to add sources to the url to be opened.
>>> +   Otherwise the join to the source specific muliticast
>>> will be missing */
>>> +sources2 = sources;
>>> +sp2 = sp;
>>> +/* ignore sources from original URL, when sources are
>>> already set in rtsp_st */
>>> +if (rtsp_st->nb_include_source_addrs > 0)
>>> +sources2 = sp2 = "";
>>> +
>>>  ff_url_join(url, sizeof(url), "rtp", NULL,
>>>  namebuf, rtsp_st->sdp_port,
>>> -
>>> "?localport=%d=%d=%d_to_source=%d",
>>> +
>>> "?localport=%d=%d=%d_to_source=%d%s%s",
>>>  rtsp_st->sdp_port, rtsp_st->sdp_ttl,
>>>  rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
>>> -rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 :
>>> 0);
>>> +rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 :
>>> 0,
>>> +sources2, sp2);
>>>
>>>  append_source_addrs(url, sizeof(url), "sources",
>>>  rtsp_st->nb_include_source_addrs,
>>> --
>>> 2.20.1 (Apple Git-117)
>>>
>>>
Hi Ross,
I am not sure I understand your requirement clearly, an alternative way is
to save the url in sdp(maybe in rtp_read_header?) and read it out in
sdp_read_header. But I am not sure which field can carry this info (maybe
uri attribute ?).

Since you already have the code change, why now send it as a formal patch
so that FFmpeg maintainers/experts can have a review ?

-Jun
___
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".

Re: [FFmpeg-devel] [PATCH v1 1/2] avformat/rtsp: apply rtcp attribute from sdp file

2020-02-20 Thread Jun Li
Ping x 2

On Sun, Feb 9, 2020 at 3:01 PM Jun Li  wrote:

>
>
> On Mon, Feb 3, 2020 at 4:34 PM Jun Li  wrote:
>
>> Fix #8479
>> Apply rtcpport from sdp file if it contains rtcp attribute.
>>
>> Signed-off-by: Jun Li 
>> ---
>>  libavformat/rtsp.c | 12 ++--
>>  libavformat/rtsp.h |  1 +
>>  2 files changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
>> index cd6fc32a29..c892f21142 100644
>> --- a/libavformat/rtsp.c
>> +++ b/libavformat/rtsp.c
>> @@ -577,6 +577,10 @@ static void sdp_parse_line(AVFormatContext *s,
>> SDPParseState *s1,
>>  if (s1->seen_fmtp) {
>>  parse_fmtp(s, rt, payload_type, s1->delayed_fmtp);
>>  }
>> +} else if (av_strstart(p, "rtcp:", ) && s->nb_streams > 0) {
>> +rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
>> +get_word(buf1, sizeof(buf1), );
>> +rtsp_st->rtcp_port = strtol(buf1, NULL, 10);
>>  } else if (av_strstart(p, "fmtp:", ) ||
>> av_strstart(p, "framesize:", )) {
>>  // let dynamic protocol handlers have a stab at the line.
>> @@ -2367,6 +2371,7 @@ static int sdp_read_header(AVFormatContext *s)
>>
>>  if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
>>  AVDictionary *opts = map_to_opts(rt);
>> +int rtcp_port = rtsp_st->rtcp_port;
>>
>>  err = getnameinfo((struct sockaddr*) _st->sdp_ip,
>>sizeof(rtsp_st->sdp_ip),
>> @@ -2377,10 +2382,13 @@ static int sdp_read_header(AVFormatContext *s)
>>  av_dict_free();
>>  goto fail;
>>  }
>> +
>> +if (rtcp_port <= 0)
>> +rtcp_port = rtsp_st->sdp_port + 1;
>>  ff_url_join(url, sizeof(url), "rtp", NULL,
>>  namebuf, rtsp_st->sdp_port,
>> -
>> "?localport=%d=%d=%d_to_source=%d",
>> -rtsp_st->sdp_port, rtsp_st->sdp_ttl,
>> +
>> "?localport=%d=%d=%d=%d_to_source=%d",
>> +rtsp_st->sdp_port, rtcp_port, rtsp_st->sdp_ttl,
>>  rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
>>  rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 :
>> 0);
>>
>> diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
>> index 54a9a30c16..15747fe6d1 100644
>> --- a/libavformat/rtsp.h
>> +++ b/libavformat/rtsp.h
>> @@ -448,6 +448,7 @@ typedef struct RTSPStream {
>>  /** The following are used only in SDP, not RTSP */
>>  //@{
>>  int sdp_port; /**< port (from SDP content) */
>> +int rtcp_port;/**< rtcp port (from SDP content) */
>>  struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */
>>  int nb_include_source_addrs; /**< Number of source-specific
>> multicast include source IP addresses (from SDP content) */
>>  struct RTSPSource **include_source_addrs; /**< Source-specific
>> multicast include source IP addresses (from SDP content) */
>> --
>> 2.17.1
>>
>>
> Ping
>
___
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".

Re: [FFmpeg-devel] [PATCH v1 2/2] avformat/rtpproto, sdp: write rtcp port to sdp file

2020-02-20 Thread Jun Li
On Sun, Feb 9, 2020 at 3:01 PM Jun Li  wrote:

>
>
> On Mon, Feb 3, 2020 at 4:34 PM Jun Li  wrote:
>
>> Fix #8474
>> Write rtcp port attribute to sdp file when necessary.
>>
>> Signed-off-by: Jun Li 
>> ---
>>  libavformat/rtpproto.c | 11 +++
>>  libavformat/rtpproto.h |  2 ++
>>  libavformat/sdp.c  | 12 ++--
>>  3 files changed, 23 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
>> index 1f0a82ac7e..81a39cc3de 100644
>> --- a/libavformat/rtpproto.c
>> +++ b/libavformat/rtpproto.c
>> @@ -524,6 +524,17 @@ int ff_rtp_get_local_rtp_port(URLContext *h)
>>  return ff_udp_get_local_port(s->rtp_hd);
>>  }
>>
>> +/**
>> + * Return the remote rtcp port used by the RTP connection
>> + * @param h media file context
>> + * @return the remote port number
>> + */
>> +int ff_rtp_get_remote_rtcp_port(URLContext *h)
>> +{
>> +RTPContext *s = h->priv_data;
>> +return s->rtcp_port;
>> +}
>> +
>>  /**
>>   * Return the local rtcp port used by the RTP connection
>>   * @param h media file context
>> diff --git a/libavformat/rtpproto.h b/libavformat/rtpproto.h
>> index 131aac5f3c..d42327ea5c 100644
>> --- a/libavformat/rtpproto.h
>> +++ b/libavformat/rtpproto.h
>> @@ -27,4 +27,6 @@ int ff_rtp_set_remote_url(URLContext *h, const char
>> *uri);
>>
>>  int ff_rtp_get_local_rtp_port(URLContext *h);
>>
>> +int ff_rtp_get_remote_rtcp_port(URLContext *h);
>> +
>>  #endif /* AVFORMAT_RTPPROTO_H */
>> diff --git a/libavformat/sdp.c b/libavformat/sdp.c
>> index 34e9839b67..c3c2909090 100644
>> --- a/libavformat/sdp.c
>> +++ b/libavformat/sdp.c
>> @@ -26,11 +26,13 @@
>>  #include "libavutil/opt.h"
>>  #include "libavcodec/xiph.h"
>>  #include "libavcodec/mpeg4audio.h"
>> +#include "avio_internal.h"
>>  #include "avformat.h"
>>  #include "internal.h"
>>  #include "avc.h"
>>  #include "hevc.h"
>>  #include "rtp.h"
>> +#include "rtpproto.h"
>>  #if CONFIG_NETWORK
>>  #include "network.h"
>>  #endif
>> @@ -480,10 +482,16 @@ static char *latm_context2config(AVFormatContext
>> *s, AVCodecParameters *par)
>>  return config;
>>  }
>>
>> -static char *sdp_write_media_attributes(char *buff, int size, AVStream
>> *st, int payload_type, AVFormatContext *fmt)
>> +static char *sdp_write_media_attributes(char *buff, int size, AVStream
>> *st, int payload_type, AVFormatContext *fmt, int port)
>>  {
>>  char *config = NULL;
>>  AVCodecParameters *p = st->codecpar;
>> +URLContext* url_ctx = ffio_geturlcontext(fmt->pb);
>> +if (url_ctx) {
>> +int rtcp_port = ff_rtp_get_remote_rtcp_port(url_ctx);
>> +if (rtcp_port > 0 && rtcp_port != port+1)
>> +av_strlcatf(buff, size, "a=rtcp:%d\r\n", rtcp_port);
>> +}
>>
>>  switch (p->codec_id) {
>>  case AV_CODEC_ID_DIRAC:
>> @@ -766,7 +774,7 @@ void ff_sdp_write_media(char *buff, int size,
>> AVStream *st, int idx,
>>  av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate /
>> 1000);
>>  }
>>
>> -sdp_write_media_attributes(buff, size, st, payload_type, fmt);
>> +sdp_write_media_attributes(buff, size, st, payload_type, fmt, port);
>>  }
>>
>>  int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int
>> size)
>> --
>> 2.17.1
>>
>>
> Ping
>

Ping x 2
___
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".

Re: [FFmpeg-devel] [PATCH v1 2/2] avformat/rtpproto, sdp: write rtcp port to sdp file

2020-02-09 Thread Jun Li
On Mon, Feb 3, 2020 at 4:34 PM Jun Li  wrote:

> Fix #8474
> Write rtcp port attribute to sdp file when necessary.
>
> Signed-off-by: Jun Li 
> ---
>  libavformat/rtpproto.c | 11 +++
>  libavformat/rtpproto.h |  2 ++
>  libavformat/sdp.c  | 12 ++--
>  3 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
> index 1f0a82ac7e..81a39cc3de 100644
> --- a/libavformat/rtpproto.c
> +++ b/libavformat/rtpproto.c
> @@ -524,6 +524,17 @@ int ff_rtp_get_local_rtp_port(URLContext *h)
>  return ff_udp_get_local_port(s->rtp_hd);
>  }
>
> +/**
> + * Return the remote rtcp port used by the RTP connection
> + * @param h media file context
> + * @return the remote port number
> + */
> +int ff_rtp_get_remote_rtcp_port(URLContext *h)
> +{
> +RTPContext *s = h->priv_data;
> +return s->rtcp_port;
> +}
> +
>  /**
>   * Return the local rtcp port used by the RTP connection
>   * @param h media file context
> diff --git a/libavformat/rtpproto.h b/libavformat/rtpproto.h
> index 131aac5f3c..d42327ea5c 100644
> --- a/libavformat/rtpproto.h
> +++ b/libavformat/rtpproto.h
> @@ -27,4 +27,6 @@ int ff_rtp_set_remote_url(URLContext *h, const char
> *uri);
>
>  int ff_rtp_get_local_rtp_port(URLContext *h);
>
> +int ff_rtp_get_remote_rtcp_port(URLContext *h);
> +
>  #endif /* AVFORMAT_RTPPROTO_H */
> diff --git a/libavformat/sdp.c b/libavformat/sdp.c
> index 34e9839b67..c3c2909090 100644
> --- a/libavformat/sdp.c
> +++ b/libavformat/sdp.c
> @@ -26,11 +26,13 @@
>  #include "libavutil/opt.h"
>  #include "libavcodec/xiph.h"
>  #include "libavcodec/mpeg4audio.h"
> +#include "avio_internal.h"
>  #include "avformat.h"
>  #include "internal.h"
>  #include "avc.h"
>  #include "hevc.h"
>  #include "rtp.h"
> +#include "rtpproto.h"
>  #if CONFIG_NETWORK
>  #include "network.h"
>  #endif
> @@ -480,10 +482,16 @@ static char *latm_context2config(AVFormatContext *s,
> AVCodecParameters *par)
>  return config;
>  }
>
> -static char *sdp_write_media_attributes(char *buff, int size, AVStream
> *st, int payload_type, AVFormatContext *fmt)
> +static char *sdp_write_media_attributes(char *buff, int size, AVStream
> *st, int payload_type, AVFormatContext *fmt, int port)
>  {
>  char *config = NULL;
>  AVCodecParameters *p = st->codecpar;
> +URLContext* url_ctx = ffio_geturlcontext(fmt->pb);
> +if (url_ctx) {
> +int rtcp_port = ff_rtp_get_remote_rtcp_port(url_ctx);
> +if (rtcp_port > 0 && rtcp_port != port+1)
> +av_strlcatf(buff, size, "a=rtcp:%d\r\n", rtcp_port);
> +}
>
>  switch (p->codec_id) {
>  case AV_CODEC_ID_DIRAC:
> @@ -766,7 +774,7 @@ void ff_sdp_write_media(char *buff, int size, AVStream
> *st, int idx,
>  av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000);
>  }
>
> -sdp_write_media_attributes(buff, size, st, payload_type, fmt);
> +sdp_write_media_attributes(buff, size, st, payload_type, fmt, port);
>  }
>
>  int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
> --
> 2.17.1
>
>
Ping
___
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".

Re: [FFmpeg-devel] [PATCH v1 1/2] avformat/rtsp: apply rtcp attribute from sdp file

2020-02-09 Thread Jun Li
On Mon, Feb 3, 2020 at 4:34 PM Jun Li  wrote:

> Fix #8479
> Apply rtcpport from sdp file if it contains rtcp attribute.
>
> Signed-off-by: Jun Li 
> ---
>  libavformat/rtsp.c | 12 ++--
>  libavformat/rtsp.h |  1 +
>  2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
> index cd6fc32a29..c892f21142 100644
> --- a/libavformat/rtsp.c
> +++ b/libavformat/rtsp.c
> @@ -577,6 +577,10 @@ static void sdp_parse_line(AVFormatContext *s,
> SDPParseState *s1,
>  if (s1->seen_fmtp) {
>  parse_fmtp(s, rt, payload_type, s1->delayed_fmtp);
>  }
> +} else if (av_strstart(p, "rtcp:", ) && s->nb_streams > 0) {
> +rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
> +get_word(buf1, sizeof(buf1), );
> +rtsp_st->rtcp_port = strtol(buf1, NULL, 10);
>  } else if (av_strstart(p, "fmtp:", ) ||
> av_strstart(p, "framesize:", )) {
>  // let dynamic protocol handlers have a stab at the line.
> @@ -2367,6 +2371,7 @@ static int sdp_read_header(AVFormatContext *s)
>
>  if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
>  AVDictionary *opts = map_to_opts(rt);
> +int rtcp_port = rtsp_st->rtcp_port;
>
>  err = getnameinfo((struct sockaddr*) _st->sdp_ip,
>sizeof(rtsp_st->sdp_ip),
> @@ -2377,10 +2382,13 @@ static int sdp_read_header(AVFormatContext *s)
>  av_dict_free();
>  goto fail;
>  }
> +
> +if (rtcp_port <= 0)
> +rtcp_port = rtsp_st->sdp_port + 1;
>  ff_url_join(url, sizeof(url), "rtp", NULL,
>  namebuf, rtsp_st->sdp_port,
> -
> "?localport=%d=%d=%d_to_source=%d",
> -rtsp_st->sdp_port, rtsp_st->sdp_ttl,
> +
> "?localport=%d=%d=%d=%d_to_source=%d",
> +rtsp_st->sdp_port, rtcp_port, rtsp_st->sdp_ttl,
>  rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
>  rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 :
> 0);
>
> diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
> index 54a9a30c16..15747fe6d1 100644
> --- a/libavformat/rtsp.h
> +++ b/libavformat/rtsp.h
> @@ -448,6 +448,7 @@ typedef struct RTSPStream {
>  /** The following are used only in SDP, not RTSP */
>  //@{
>  int sdp_port; /**< port (from SDP content) */
> +int rtcp_port;/**< rtcp port (from SDP content) */
>  struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */
>  int nb_include_source_addrs; /**< Number of source-specific multicast
> include source IP addresses (from SDP content) */
>  struct RTSPSource **include_source_addrs; /**< Source-specific
> multicast include source IP addresses (from SDP content) */
> --
> 2.17.1
>
>
Ping
___
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".

[FFmpeg-devel] [PATCH v1 2/2] avformat/rtpproto, sdp: write rtcp port to sdp file

2020-02-03 Thread Jun Li
Fix #8474
Write rtcp port attribute to sdp file when necessary.

Signed-off-by: Jun Li 
---
 libavformat/rtpproto.c | 11 +++
 libavformat/rtpproto.h |  2 ++
 libavformat/sdp.c  | 12 ++--
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 1f0a82ac7e..81a39cc3de 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -524,6 +524,17 @@ int ff_rtp_get_local_rtp_port(URLContext *h)
 return ff_udp_get_local_port(s->rtp_hd);
 }
 
+/**
+ * Return the remote rtcp port used by the RTP connection
+ * @param h media file context
+ * @return the remote port number
+ */
+int ff_rtp_get_remote_rtcp_port(URLContext *h)
+{
+RTPContext *s = h->priv_data;
+return s->rtcp_port;
+}
+
 /**
  * Return the local rtcp port used by the RTP connection
  * @param h media file context
diff --git a/libavformat/rtpproto.h b/libavformat/rtpproto.h
index 131aac5f3c..d42327ea5c 100644
--- a/libavformat/rtpproto.h
+++ b/libavformat/rtpproto.h
@@ -27,4 +27,6 @@ int ff_rtp_set_remote_url(URLContext *h, const char *uri);
 
 int ff_rtp_get_local_rtp_port(URLContext *h);
 
+int ff_rtp_get_remote_rtcp_port(URLContext *h);
+
 #endif /* AVFORMAT_RTPPROTO_H */
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 34e9839b67..c3c2909090 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -26,11 +26,13 @@
 #include "libavutil/opt.h"
 #include "libavcodec/xiph.h"
 #include "libavcodec/mpeg4audio.h"
+#include "avio_internal.h"
 #include "avformat.h"
 #include "internal.h"
 #include "avc.h"
 #include "hevc.h"
 #include "rtp.h"
+#include "rtpproto.h"
 #if CONFIG_NETWORK
 #include "network.h"
 #endif
@@ -480,10 +482,16 @@ static char *latm_context2config(AVFormatContext *s, 
AVCodecParameters *par)
 return config;
 }
 
-static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, 
int payload_type, AVFormatContext *fmt)
+static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, 
int payload_type, AVFormatContext *fmt, int port)
 {
 char *config = NULL;
 AVCodecParameters *p = st->codecpar;
+URLContext* url_ctx = ffio_geturlcontext(fmt->pb);
+if (url_ctx) {
+int rtcp_port = ff_rtp_get_remote_rtcp_port(url_ctx);
+if (rtcp_port > 0 && rtcp_port != port+1)
+av_strlcatf(buff, size, "a=rtcp:%d\r\n", rtcp_port);
+}
 
 switch (p->codec_id) {
 case AV_CODEC_ID_DIRAC:
@@ -766,7 +774,7 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, 
int idx,
 av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000);
 }
 
-sdp_write_media_attributes(buff, size, st, payload_type, fmt);
+sdp_write_media_attributes(buff, size, st, payload_type, fmt, port);
 }
 
 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1 1/2] avformat/rtsp: apply rtcp attribute from sdp file

2020-02-03 Thread Jun Li
Fix #8479
Apply rtcpport from sdp file if it contains rtcp attribute.

Signed-off-by: Jun Li 
---
 libavformat/rtsp.c | 12 ++--
 libavformat/rtsp.h |  1 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index cd6fc32a29..c892f21142 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -577,6 +577,10 @@ static void sdp_parse_line(AVFormatContext *s, 
SDPParseState *s1,
 if (s1->seen_fmtp) {
 parse_fmtp(s, rt, payload_type, s1->delayed_fmtp);
 }
+} else if (av_strstart(p, "rtcp:", ) && s->nb_streams > 0) {
+rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+get_word(buf1, sizeof(buf1), );
+rtsp_st->rtcp_port = strtol(buf1, NULL, 10);
 } else if (av_strstart(p, "fmtp:", ) ||
av_strstart(p, "framesize:", )) {
 // let dynamic protocol handlers have a stab at the line.
@@ -2367,6 +2371,7 @@ static int sdp_read_header(AVFormatContext *s)
 
 if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
 AVDictionary *opts = map_to_opts(rt);
+int rtcp_port = rtsp_st->rtcp_port;
 
 err = getnameinfo((struct sockaddr*) _st->sdp_ip,
   sizeof(rtsp_st->sdp_ip),
@@ -2377,10 +2382,13 @@ static int sdp_read_header(AVFormatContext *s)
 av_dict_free();
 goto fail;
 }
+
+if (rtcp_port <= 0)
+rtcp_port = rtsp_st->sdp_port + 1;
 ff_url_join(url, sizeof(url), "rtp", NULL,
 namebuf, rtsp_st->sdp_port,
-"?localport=%d=%d=%d_to_source=%d",
-rtsp_st->sdp_port, rtsp_st->sdp_ttl,
+
"?localport=%d=%d=%d=%d_to_source=%d",
+rtsp_st->sdp_port, rtcp_port, rtsp_st->sdp_ttl,
 rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
 rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0);
 
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 54a9a30c16..15747fe6d1 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -448,6 +448,7 @@ typedef struct RTSPStream {
 /** The following are used only in SDP, not RTSP */
 //@{
 int sdp_port; /**< port (from SDP content) */
+int rtcp_port;/**< rtcp port (from SDP content) */
 struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */
 int nb_include_source_addrs; /**< Number of source-specific multicast 
include source IP addresses (from SDP content) */
 struct RTSPSource **include_source_addrs; /**< Source-specific multicast 
include source IP addresses (from SDP content) */
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avformat/sdp, rtsp: add rtcp attribute to sdp file

2020-02-01 Thread Jun Li
Fix #8479
1. write rtcpport to sdp file when rtpport is specified in url
2. apply rtcpport when sdp file contains rtcp attribute

Signed-off-by: Jun Li 
---
 libavformat/rtpproto.c | 11 +++
 libavformat/rtpproto.h |  2 ++
 libavformat/rtsp.c | 12 ++--
 libavformat/rtsp.h |  1 +
 libavformat/sdp.c  | 12 ++--
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 1f0a82ac7e..81a39cc3de 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -524,6 +524,17 @@ int ff_rtp_get_local_rtp_port(URLContext *h)
 return ff_udp_get_local_port(s->rtp_hd);
 }
 
+/**
+ * Return the remote rtcp port used by the RTP connection
+ * @param h media file context
+ * @return the remote port number
+ */
+int ff_rtp_get_remote_rtcp_port(URLContext *h)
+{
+RTPContext *s = h->priv_data;
+return s->rtcp_port;
+}
+
 /**
  * Return the local rtcp port used by the RTP connection
  * @param h media file context
diff --git a/libavformat/rtpproto.h b/libavformat/rtpproto.h
index 131aac5f3c..d42327ea5c 100644
--- a/libavformat/rtpproto.h
+++ b/libavformat/rtpproto.h
@@ -27,4 +27,6 @@ int ff_rtp_set_remote_url(URLContext *h, const char *uri);
 
 int ff_rtp_get_local_rtp_port(URLContext *h);
 
+int ff_rtp_get_remote_rtcp_port(URLContext *h);
+
 #endif /* AVFORMAT_RTPPROTO_H */
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index cd6fc32a29..c892f21142 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -577,6 +577,10 @@ static void sdp_parse_line(AVFormatContext *s, 
SDPParseState *s1,
 if (s1->seen_fmtp) {
 parse_fmtp(s, rt, payload_type, s1->delayed_fmtp);
 }
+} else if (av_strstart(p, "rtcp:", ) && s->nb_streams > 0) {
+rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+get_word(buf1, sizeof(buf1), );
+rtsp_st->rtcp_port = strtol(buf1, NULL, 10);
 } else if (av_strstart(p, "fmtp:", ) ||
av_strstart(p, "framesize:", )) {
 // let dynamic protocol handlers have a stab at the line.
@@ -2367,6 +2371,7 @@ static int sdp_read_header(AVFormatContext *s)
 
 if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
 AVDictionary *opts = map_to_opts(rt);
+int rtcp_port = rtsp_st->rtcp_port;
 
 err = getnameinfo((struct sockaddr*) _st->sdp_ip,
   sizeof(rtsp_st->sdp_ip),
@@ -2377,10 +2382,13 @@ static int sdp_read_header(AVFormatContext *s)
 av_dict_free();
 goto fail;
 }
+
+if (rtcp_port <= 0)
+rtcp_port = rtsp_st->sdp_port + 1;
 ff_url_join(url, sizeof(url), "rtp", NULL,
 namebuf, rtsp_st->sdp_port,
-"?localport=%d=%d=%d_to_source=%d",
-rtsp_st->sdp_port, rtsp_st->sdp_ttl,
+
"?localport=%d=%d=%d=%d_to_source=%d",
+rtsp_st->sdp_port, rtcp_port, rtsp_st->sdp_ttl,
 rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
 rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0);
 
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 54a9a30c16..15747fe6d1 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -448,6 +448,7 @@ typedef struct RTSPStream {
 /** The following are used only in SDP, not RTSP */
 //@{
 int sdp_port; /**< port (from SDP content) */
+int rtcp_port;/**< rtcp port (from SDP content) */
 struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */
 int nb_include_source_addrs; /**< Number of source-specific multicast 
include source IP addresses (from SDP content) */
 struct RTSPSource **include_source_addrs; /**< Source-specific multicast 
include source IP addresses (from SDP content) */
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 34e9839b67..c3c2909090 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -26,11 +26,13 @@
 #include "libavutil/opt.h"
 #include "libavcodec/xiph.h"
 #include "libavcodec/mpeg4audio.h"
+#include "avio_internal.h"
 #include "avformat.h"
 #include "internal.h"
 #include "avc.h"
 #include "hevc.h"
 #include "rtp.h"
+#include "rtpproto.h"
 #if CONFIG_NETWORK
 #include "network.h"
 #endif
@@ -480,10 +482,16 @@ static char *latm_context2config(AVFormatContext *s, 
AVCodecParameters *par)
 return config;
 }
 
-static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, 
int payload_type, AVFormatContext *fmt)
+static char *sdp_write_media_attributes(char *buff, int size

Re: [FFmpeg-devel] Append to fmp4

2019-12-19 Thread Jun Li
On Thu, Dec 19, 2019 at 4:00 AM Daniel Oberhoff <
danieloberh...@googlemail.com> wrote:

> Hello.
>
> I have been diving deep into the mp4 spec to understand fragmented mp4.
> From what I understand using moof atoms it is possible, given stream
> compatibility, to straight append to an mp4 file by appending moof+mdat
> pairs. Can ffmpeg or libavformat be somehow used to achieve that?


I use the command line like " ffmpeg -i test.mp4 -codec copy -f mp4
-movflags empty_moov+frag_keyframe+skip_trailer out.mp4".
It generates  fmp4 with atiom :   ftyp+moov+[moof+mdata]*


>
>
Gruß!
>
> Daniel Oberhoff
> ___
> 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".
___
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".

Re: [FFmpeg-devel] [PATCH v2] avformat/wavdec.c: copy id3 metadata to format metadata and stream side data

2019-11-22 Thread Jun Li
On Wed, Oct 23, 2019 at 6:25 PM Jun Li  wrote:

>
>
> On Sun, Oct 20, 2019 at 4:14 PM Jun Li  wrote:
>
>> Enhancement #7803
>> Copy id3 metadata to format meta data and stream side data.
>>
>> Signed-off-by: Jun Li 
>> ---
>>  libavformat/Makefile |  4 ++--
>>  libavformat/wavdec.c | 10 ++
>>  2 files changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavformat/Makefile b/libavformat/Makefile
>> index 615156c120..0ab6fe0793 100644
>> --- a/libavformat/Makefile
>> +++ b/libavformat/Makefile
>> @@ -535,9 +535,9 @@ OBJS-$(CONFIG_VOC_MUXER) += vocenc.o
>> voc.o
>>  OBJS-$(CONFIG_VPK_DEMUXER)   += vpk.o
>>  OBJS-$(CONFIG_VPLAYER_DEMUXER)   += vplayerdec.o subtitles.o
>>  OBJS-$(CONFIG_VQF_DEMUXER)   += vqf.o
>> -OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o
>> +OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o
>> replaygain.o
>>  OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o
>> -OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o
>> +OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o replaygain.o
>>  OBJS-$(CONFIG_WAV_MUXER) += wavenc.o
>>  OBJS-$(CONFIG_WC3_DEMUXER)   += wc3movie.o
>>  OBJS-$(CONFIG_WEBM_MUXER)+= matroskaenc.o matroska.o \
>> diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
>> index 52194f54ef..d82bdaaa66 100644
>> --- a/libavformat/wavdec.c
>> +++ b/libavformat/wavdec.c
>> @@ -41,6 +41,7 @@
>>  #include "riff.h"
>>  #include "w64.h"
>>  #include "spdif.h"
>> +#include "replaygain.h"
>>
>>  typedef struct WAVDemuxContext {
>>  const AVClass *class;
>> @@ -537,6 +538,15 @@ break_loop:
>>
>>  avio_seek(pb, data_ofs, SEEK_SET);
>>
>> +if (s->internal->id3v2_meta) {
>> +ret = av_dict_copy(>metadata, s->internal->id3v2_meta, 0);
>> +if (ret < 0)
>> +return ret;
>> +ret = ff_replaygain_export(st, s->internal->id3v2_meta);
>> +if (ret < 0)
>> +return ret;
>> +}
>> +
>>  if (data_size > (INT64_MAX>>3)) {
>>  av_log(s, AV_LOG_WARNING, "Data size %"PRId64" is too large\n",
>> data_size);
>>  data_size = 0;
>> --
>> 2.17.1
>>
>>
> Ping
>

Ping
___
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".

Re: [FFmpeg-devel] [PATCH v4] avformat/movenc: split empty text sample when duration overflow

2019-10-24 Thread Jun Li
On Fri, Oct 18, 2019 at 11:56 AM Jun Li  wrote:

>
>
> On Wed, Oct 9, 2019 at 3:42 PM Jun Li  wrote:
>
>>
>>
>> On Mon, Oct 7, 2019 at 6:36 PM Jun Li  wrote:
>>
>>>
>>>
>>> On Mon, Oct 7, 2019 at 6:34 PM Jun Li  wrote:
>>>
>>>> Fix #7637
>>>> One empty/end sample is created and inserted between two caption lines
>>>> when there is a gap.
>>>> This patch is to split the sample into multiple ones when its duration
>>>> is too long (>= INT_MAX)
>>>>
>>>> Signed-off-by: Jun Li 
>>>> ---
>>>>  libavformat/movenc.c  | 26 ++-
>>>>  tests/fate/subtitles.mak  |  6 +
>>>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>>>  4 files changed, 28 insertions(+), 6 deletions(-)
>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>>>
>>>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>>>> index 715bec1c2f..5dc2a19c3c 100644
>>>> --- a/libavformat/movenc.c
>>>> +++ b/libavformat/movenc.c
>>>> @@ -5750,7 +5750,8 @@ static int mov_write_packet(AVFormatContext *s,
>>>> AVPacket *pkt)
>>>>   *
>>>>   * 2) For each subtitle track, check if the current packet's
>>>>   * dts is past the duration of the last subtitle sample. If
>>>> - * so, we now need to write an end sample for that subtitle.
>>>> + * so, we now need to write one or multiple end samples for
>>>> + * that subtitle.
>>>>   *
>>>>   * This must be done conditionally to allow for subtitles that
>>>>   * immediately replace each other, in which case an end sample
>>>> @@ -5764,11 +5765,24 @@ static int mov_write_packet(AVFormatContext *s,
>>>> AVPacket *pkt)
>>>>  int ret;
>>>>
>>>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>>>> -trk->track_duration < pkt->dts &&
>>>> -(trk->entry == 0 ||
>>>> !trk->last_sample_is_subtitle_end)) {
>>>> -ret = mov_write_subtitle_end_packet(s, i,
>>>> trk->track_duration);
>>>> -if (ret < 0) return ret;
>>>> -trk->last_sample_is_subtitle_end = 1;
>>>> +trk->track_duration < pkt->dts) {
>>>> +int max_duration = INT_MAX - 1;
>>>> +if (trk->entry == 0 ||
>>>> !trk->last_sample_is_subtitle_end) {
>>>> +ret = mov_write_subtitle_end_packet(s, i,
>>>> trk->track_duration);
>>>> +if (ret < 0)
>>>> +return ret;
>>>> +trk->last_sample_is_subtitle_end = 1;
>>>> +}
>>>> +if (trk->last_sample_is_subtitle_end &&
>>>> +pkt->dts - trk->track_duration > max_duration) {
>>>> +int64_t dts = trk->track_duration;
>>>> +while(pkt->dts - dts > max_duration) {
>>>> +dts += max_duration;
>>>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>>>> +if (ret < 0)
>>>> +return ret;
>>>> +}
>>>> +}
>>>>  }
>>>>  }
>>>>
>>>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>>>> index 0042902161..4c2b34c431 100644
>>>> --- a/tests/fate/subtitles.mak
>>>> +++ b/tests/fate/subtitles.mak
>>>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>>>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>>>  fate-binsub-movtextenc: CMD = md5 -i
>>>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags 
>>>> frag_keyframe+empty_mo

Re: [FFmpeg-devel] [PATCH v2] avformat/wavdec.c: copy id3 metadata to format metadata and stream side data

2019-10-23 Thread Jun Li
On Sun, Oct 20, 2019 at 4:14 PM Jun Li  wrote:

> Enhancement #7803
> Copy id3 metadata to format meta data and stream side data.
>
> Signed-off-by: Jun Li 
> ---
>  libavformat/Makefile |  4 ++--
>  libavformat/wavdec.c | 10 ++
>  2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 615156c120..0ab6fe0793 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -535,9 +535,9 @@ OBJS-$(CONFIG_VOC_MUXER) += vocenc.o
> voc.o
>  OBJS-$(CONFIG_VPK_DEMUXER)   += vpk.o
>  OBJS-$(CONFIG_VPLAYER_DEMUXER)   += vplayerdec.o subtitles.o
>  OBJS-$(CONFIG_VQF_DEMUXER)   += vqf.o
> -OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o
> +OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o
> replaygain.o
>  OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o
> -OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o
> +OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o replaygain.o
>  OBJS-$(CONFIG_WAV_MUXER) += wavenc.o
>  OBJS-$(CONFIG_WC3_DEMUXER)   += wc3movie.o
>  OBJS-$(CONFIG_WEBM_MUXER)+= matroskaenc.o matroska.o \
> diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
> index 52194f54ef..d82bdaaa66 100644
> --- a/libavformat/wavdec.c
> +++ b/libavformat/wavdec.c
> @@ -41,6 +41,7 @@
>  #include "riff.h"
>  #include "w64.h"
>  #include "spdif.h"
> +#include "replaygain.h"
>
>  typedef struct WAVDemuxContext {
>  const AVClass *class;
> @@ -537,6 +538,15 @@ break_loop:
>
>  avio_seek(pb, data_ofs, SEEK_SET);
>
> +if (s->internal->id3v2_meta) {
> +ret = av_dict_copy(>metadata, s->internal->id3v2_meta, 0);
> +if (ret < 0)
> +return ret;
> +ret = ff_replaygain_export(st, s->internal->id3v2_meta);
> +if (ret < 0)
> +return ret;
> +}
> +
>  if (data_size > (INT64_MAX>>3)) {
>  av_log(s, AV_LOG_WARNING, "Data size %"PRId64" is too large\n",
> data_size);
>  data_size = 0;
> --
> 2.17.1
>
>
Ping
___
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".

Re: [FFmpeg-devel] [PATCH v1] avformat/wavdec.c: copy id3 metadata to format metadata and stream side data

2019-10-20 Thread Jun Li
On Sun, Oct 20, 2019 at 6:11 AM Moritz Barsnick  wrote:

> On Sat, Oct 19, 2019 at 22:33:55 -0700, Jun Li wrote:
> > +ret = ff_replaygain_export(st, s->internal->id3v2_meta);
>
> In libavformat/Makefile, CONFIG_W64_DEMUXER and CONFIG_WAV_DEMUXER now
> probably need to depend on replaygain.o.
>
> Thanks for review, Moritz.
Yes, it breaks the standalone build. Version 2 is sent out to fix it.
Thanks!

Best regards,
-Jun


> (I made the same mistake recently.)
>
> Cheers,
> Moritz
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v2] avformat/wavdec.c: copy id3 metadata to format metadata and stream side data

2019-10-20 Thread Jun Li
Enhancement #7803
Copy id3 metadata to format meta data and stream side data.

Signed-off-by: Jun Li 
---
 libavformat/Makefile |  4 ++--
 libavformat/wavdec.c | 10 ++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 615156c120..0ab6fe0793 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -535,9 +535,9 @@ OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o
 OBJS-$(CONFIG_VPK_DEMUXER)   += vpk.o
 OBJS-$(CONFIG_VPLAYER_DEMUXER)   += vplayerdec.o subtitles.o
 OBJS-$(CONFIG_VQF_DEMUXER)   += vqf.o
-OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o
+OBJS-$(CONFIG_W64_DEMUXER)   += wavdec.o w64.o pcm.o replaygain.o
 OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o
-OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o
+OBJS-$(CONFIG_WAV_DEMUXER)   += wavdec.o pcm.o replaygain.o
 OBJS-$(CONFIG_WAV_MUXER) += wavenc.o
 OBJS-$(CONFIG_WC3_DEMUXER)   += wc3movie.o
 OBJS-$(CONFIG_WEBM_MUXER)+= matroskaenc.o matroska.o \
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 52194f54ef..d82bdaaa66 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -41,6 +41,7 @@
 #include "riff.h"
 #include "w64.h"
 #include "spdif.h"
+#include "replaygain.h"
 
 typedef struct WAVDemuxContext {
 const AVClass *class;
@@ -537,6 +538,15 @@ break_loop:
 
 avio_seek(pb, data_ofs, SEEK_SET);
 
+if (s->internal->id3v2_meta) {
+ret = av_dict_copy(>metadata, s->internal->id3v2_meta, 0);
+if (ret < 0)
+return ret;
+ret = ff_replaygain_export(st, s->internal->id3v2_meta);
+if (ret < 0)
+return ret;
+}
+
 if (data_size > (INT64_MAX>>3)) {
 av_log(s, AV_LOG_WARNING, "Data size %"PRId64" is too large\n", 
data_size);
 data_size = 0;
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avformat/wavdec.c: copy id3 metadata to format metadata and stream side data

2019-10-20 Thread Jun Li
Enhancement #7803
Copy id3 metadata to format meta data and steams side data.

Signed-off-by: Jun Li 
---
 libavformat/wavdec.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 52194f54ef..d82bdaaa66 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -41,6 +41,7 @@
 #include "riff.h"
 #include "w64.h"
 #include "spdif.h"
+#include "replaygain.h"
 
 typedef struct WAVDemuxContext {
 const AVClass *class;
@@ -537,6 +538,15 @@ break_loop:
 
 avio_seek(pb, data_ofs, SEEK_SET);
 
+if (s->internal->id3v2_meta) {
+ret = av_dict_copy(>metadata, s->internal->id3v2_meta, 0);
+if (ret < 0)
+return ret;
+ret = ff_replaygain_export(st, s->internal->id3v2_meta);
+if (ret < 0)
+return ret;
+}
+
 if (data_size > (INT64_MAX>>3)) {
 av_log(s, AV_LOG_WARNING, "Data size %"PRId64" is too large\n", 
data_size);
 data_size = 0;
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v4] avformat/movenc: split empty text sample when duration overflow

2019-10-18 Thread Jun Li
On Wed, Oct 9, 2019 at 3:42 PM Jun Li  wrote:

>
>
> On Mon, Oct 7, 2019 at 6:36 PM Jun Li  wrote:
>
>>
>>
>> On Mon, Oct 7, 2019 at 6:34 PM Jun Li  wrote:
>>
>>> Fix #7637
>>> One empty/end sample is created and inserted between two caption lines
>>> when there is a gap.
>>> This patch is to split the sample into multiple ones when its duration
>>> is too long (>= INT_MAX)
>>>
>>> Signed-off-by: Jun Li 
>>> ---
>>>  libavformat/movenc.c  | 26 ++-
>>>  tests/fate/subtitles.mak  |  6 +
>>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>>  4 files changed, 28 insertions(+), 6 deletions(-)
>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>>
>>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>>> index 715bec1c2f..5dc2a19c3c 100644
>>> --- a/libavformat/movenc.c
>>> +++ b/libavformat/movenc.c
>>> @@ -5750,7 +5750,8 @@ static int mov_write_packet(AVFormatContext *s,
>>> AVPacket *pkt)
>>>   *
>>>   * 2) For each subtitle track, check if the current packet's
>>>   * dts is past the duration of the last subtitle sample. If
>>> - * so, we now need to write an end sample for that subtitle.
>>> + * so, we now need to write one or multiple end samples for
>>> + * that subtitle.
>>>   *
>>>   * This must be done conditionally to allow for subtitles that
>>>   * immediately replace each other, in which case an end sample
>>> @@ -5764,11 +5765,24 @@ static int mov_write_packet(AVFormatContext *s,
>>> AVPacket *pkt)
>>>  int ret;
>>>
>>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>>> -trk->track_duration < pkt->dts &&
>>> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end))
>>> {
>>> -ret = mov_write_subtitle_end_packet(s, i,
>>> trk->track_duration);
>>> -if (ret < 0) return ret;
>>> -trk->last_sample_is_subtitle_end = 1;
>>> +trk->track_duration < pkt->dts) {
>>> +int max_duration = INT_MAX - 1;
>>> +if (trk->entry == 0 ||
>>> !trk->last_sample_is_subtitle_end) {
>>> +ret = mov_write_subtitle_end_packet(s, i,
>>> trk->track_duration);
>>> +if (ret < 0)
>>> +return ret;
>>> +trk->last_sample_is_subtitle_end = 1;
>>> +}
>>> +if (trk->last_sample_is_subtitle_end &&
>>> +pkt->dts - trk->track_duration > max_duration) {
>>> +int64_t dts = trk->track_duration;
>>> +while(pkt->dts - dts > max_duration) {
>>> +dts += max_duration;
>>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>>> +if (ret < 0)
>>> +return ret;
>>> +}
>>> +}
>>>  }
>>>  }
>>>
>>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>>> index 0042902161..4c2b34c431 100644
>>> --- a/tests/fate/subtitles.mak
>>> +++ b/tests/fate/subtitles.mak
>>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>>  fate-binsub-movtextenc: CMD = md5 -i
>>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>>
>>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>>> fate-binsub-movtextenc-long-dur
>>> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
>>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>> +
>>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
&

Re: [FFmpeg-devel] [PATCH v2] avformat/tee.c: steal bsf option before passing to fifo muxer

2019-10-17 Thread Jun Li
On Sun, Oct 13, 2019 at 2:14 PM Jun Li  wrote:

> Fix #7620
> In the case tee muxer with both "bsf" and "use_fifo" parameters
> will trigger this bug. Tee muxer will first steal parameters (like "f",
> "select"...) and then "use_fifo" will try reading out remaining options
> and pass them to fifo as option "format_options".
> Current code miss the part of stealing "bsf" options.
> ---
>  libavformat/tee.c | 15 +++
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/libavformat/tee.c b/libavformat/tee.c
> index 89a4ceb280..d91993354b 100644
> --- a/libavformat/tee.c
> +++ b/libavformat/tee.c
> @@ -159,7 +159,7 @@ static void close_slaves(AVFormatContext *avf)
>  static int open_slave(AVFormatContext *avf, char *slave, TeeSlave
> *tee_slave)
>  {
>  int i, ret;
> -AVDictionary *options = NULL;
> +AVDictionary *options = NULL, *bsf_options = NULL;
>  AVDictionaryEntry *entry;
>  char *filename;
>  char *format = NULL, *select = NULL, *on_fail = NULL;
> @@ -186,6 +186,12 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
>  STEAL_OPTION("onfail", on_fail);
>  STEAL_OPTION("use_fifo", use_fifo);
>  STEAL_OPTION("fifo_options", fifo_options_str);
> +entry = NULL;
> +while ((entry = av_dict_get(options, "bsfs", entry,
> AV_DICT_IGNORE_SUFFIX))) {
> +/* trim out strlen("bsfs") characters from key */
> +av_dict_set(_options, entry->key + 4, entry->value, 0);
> +av_dict_set(, entry->key, NULL, 0);
> +}
>
>  ret = parse_slave_failure_policy_option(on_fail, tee_slave);
>  if (ret < 0) {
> @@ -311,8 +317,8 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
>  }
>
>  entry = NULL;
> -while (entry = av_dict_get(options, "bsfs", NULL,
> AV_DICT_IGNORE_SUFFIX)) {
> -const char *spec = entry->key + strlen("bsfs");
> +while (entry = av_dict_get(bsf_options, "", NULL,
> AV_DICT_IGNORE_SUFFIX)) {
> +const char *spec = entry->key;
>  if (*spec) {
>  if (strspn(spec, slave_bsfs_spec_sep) != 1) {
>  av_log(avf, AV_LOG_ERROR,
> @@ -352,7 +358,7 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
>  }
>  }
>
> -av_dict_set(, entry->key, NULL, 0);
> +av_dict_set(_options, entry->key, NULL, 0);
>  }
>
>  for (i = 0; i < avf->nb_streams; i++){
> @@ -399,6 +405,7 @@ end:
>  av_free(select);
>  av_free(on_fail);
>  av_dict_free();
> +av_dict_free(_options);
>  av_freep(_select);
>  return ret;
>  }
> --
> 2.17.1
>
>
Ping
___
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".

Re: [FFmpeg-devel] [PATCH v1] avformat/tee.c: steal bsf option before passing to fifo muxer

2019-10-13 Thread Jun Li
On Sun, Oct 13, 2019 at 10:39 AM Nicolas George  wrote:

> Jun Li (12019-10-05):
> > Fix #7620
> > In the case tee muxer with both "bsf" and "use_fifo" parameters
> > wil trigger this bug. Tee muxer will first steal parameters (like "f",
>
> will
>
> > "select"...) and then "use_fifo" will try reading out remaining options
> > and pass them to fifo as option "format_options".
> > Current code miss the part of stealing "bsf" options.
> > ---
> >  libavformat/tee.c | 12 +---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> >
> > diff --git a/libavformat/tee.c b/libavformat/tee.c
> > index 89a4ceb280..3530582dbd 100644
> > --- a/libavformat/tee.c
> > +++ b/libavformat/tee.c
> > @@ -159,7 +159,7 @@ static void close_slaves(AVFormatContext *avf)
> >  static int open_slave(AVFormatContext *avf, char *slave, TeeSlave
> *tee_slave)
> >  {
> >  int i, ret;
> > -AVDictionary *options = NULL;
> > +AVDictionary *options = NULL, *bsf_options = NULL;
> >  AVDictionaryEntry *entry;
> >  char *filename;
> >  char *format = NULL, *select = NULL, *on_fail = NULL;
> > @@ -186,6 +186,11 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
> >  STEAL_OPTION("onfail", on_fail);
> >  STEAL_OPTION("use_fifo", use_fifo);
> >  STEAL_OPTION("fifo_options", fifo_options_str);
> > +entry = NULL;
> > +while ((entry = av_dict_get(options, "bsfs", entry,
> AV_DICT_IGNORE_SUFFIX))) {
>
> > +av_dict_set(_options, entry->key, entry->value, 0);
>
> You could use entry->key + 4 to trim the "bsfs" prefix.


Thanks for review, version 2 is sent out for addressing it.
https://patchwork.ffmpeg.org/patch/15731/


>
>
> +av_dict_set(, entry->key, NULL, 0);
> > +}
> >
> >  ret = parse_slave_failure_policy_option(on_fail, tee_slave);
> >  if (ret < 0) {
> > @@ -311,7 +316,7 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
> >  }
> >
> >  entry = NULL;
> > -while (entry = av_dict_get(options, "bsfs", NULL,
> AV_DICT_IGNORE_SUFFIX)) {
> > +while (entry = av_dict_get(bsf_options, "bsfs", NULL,
> AV_DICT_IGNORE_SUFFIX)) {
> >  const char *spec = entry->key + strlen("bsfs");
> >  if (*spec) {
> >  if (strspn(spec, slave_bsfs_spec_sep) != 1) {
> > @@ -352,7 +357,7 @@ static int open_slave(AVFormatContext *avf, char
> *slave, TeeSlave *tee_slave)
> >  }
> >  }
> >
> > -av_dict_set(, entry->key, NULL, 0);
> > +av_dict_set(_options, entry->key, NULL, 0);
> >  }
> >
> >  for (i = 0; i < avf->nb_streams; i++){
> > @@ -399,6 +404,7 @@ end:
> >  av_free(select);
> >  av_free(on_fail);
> >  av_dict_free();
> > +av_dict_free(_options);
> >  av_freep(_select);
> >  return ret;
> >  }
>
> Apart from that, LGTM.
>
> Regards,
>
> --
>   Nicolas George
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v2] avformat/tee.c: steal bsf option before passing to fifo muxer

2019-10-13 Thread Jun Li
Fix #7620
In the case tee muxer with both "bsf" and "use_fifo" parameters
will trigger this bug. Tee muxer will first steal parameters (like "f",
"select"...) and then "use_fifo" will try reading out remaining options
and pass them to fifo as option "format_options".
Current code miss the part of stealing "bsf" options.
---
 libavformat/tee.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/libavformat/tee.c b/libavformat/tee.c
index 89a4ceb280..d91993354b 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -159,7 +159,7 @@ static void close_slaves(AVFormatContext *avf)
 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
 {
 int i, ret;
-AVDictionary *options = NULL;
+AVDictionary *options = NULL, *bsf_options = NULL;
 AVDictionaryEntry *entry;
 char *filename;
 char *format = NULL, *select = NULL, *on_fail = NULL;
@@ -186,6 +186,12 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 STEAL_OPTION("onfail", on_fail);
 STEAL_OPTION("use_fifo", use_fifo);
 STEAL_OPTION("fifo_options", fifo_options_str);
+entry = NULL;
+while ((entry = av_dict_get(options, "bsfs", entry, 
AV_DICT_IGNORE_SUFFIX))) {
+/* trim out strlen("bsfs") characters from key */
+av_dict_set(_options, entry->key + 4, entry->value, 0);
+av_dict_set(, entry->key, NULL, 0);
+}
 
 ret = parse_slave_failure_policy_option(on_fail, tee_slave);
 if (ret < 0) {
@@ -311,8 +317,8 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 }
 
 entry = NULL;
-while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) {
-const char *spec = entry->key + strlen("bsfs");
+while (entry = av_dict_get(bsf_options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
+const char *spec = entry->key;
 if (*spec) {
 if (strspn(spec, slave_bsfs_spec_sep) != 1) {
 av_log(avf, AV_LOG_ERROR,
@@ -352,7 +358,7 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 }
 }
 
-av_dict_set(, entry->key, NULL, 0);
+av_dict_set(_options, entry->key, NULL, 0);
 }
 
 for (i = 0; i < avf->nb_streams; i++){
@@ -399,6 +405,7 @@ end:
 av_free(select);
 av_free(on_fail);
 av_dict_free();
+av_dict_free(_options);
 av_freep(_select);
 return ret;
 }
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v2] avcodec/h264_parse: decode sps before pps

2019-10-09 Thread Jun Li
On Mon, Oct 7, 2019 at 8:33 PM Jun Li  wrote:

> Fix ticket #6422
> The content put pps before sps, which is not a common case. The change
> put decoding sps before pps, just for compability.
>
> Signed-off-by: Jun Li 
> ---
>  libavcodec/h264_parse.c | 19 ++-
>  1 file changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> index 352ffea948..eeda5a76e5 100644
> --- a/libavcodec/h264_parse.c
> +++ b/libavcodec/h264_parse.c
> @@ -373,35 +373,36 @@ static int decode_extradata_ps(const uint8_t *data,
> int size, H264ParamSets *ps,
>  goto fail;
>  }
>
> +/* decode sps before pps, just in case some bitstream put pps before
> sps. */
>  for (i = 0; i < pkt.nb_nals; i++) {
>  H2645NAL *nal = [i];
> -switch (nal->type) {
> -case H264_NAL_SPS: {
> +if (nal->type == H264_NAL_SPS) {
>  GetBitContext tmp_gb = nal->gb;
>  ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps,
> 0);
>  if (ret >= 0)
> -break;
> +continue;
>  av_log(logctx, AV_LOG_DEBUG,
> "SPS decoding failure, trying again with the complete
> NAL\n");
>  init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
>  ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps,
> 0);
>  if (ret >= 0)
> -break;
> +continue;
>  ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps,
> 1);
>  if (ret < 0)
>  goto fail;
> -break;
>  }
> -case H264_NAL_PPS:
> +}
> +
> +for (i = 0; i < pkt.nb_nals; i++) {
> +H2645NAL *nal = [i];
> +if (nal->type == H264_NAL_PPS) {
>  ret = ff_h264_decode_picture_parameter_set(>gb, logctx,
> ps,
> nal->size_bits);
>  if (ret < 0)
>  goto fail;
> -break;
> -default:
> +} else if (nal->type != H264_NAL_SPS) {
>  av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in
> extradata\n",
> nal->type);
> -break;
>  }
>  }
>
> --
> 2.17.1
>
>
Ping
___
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".

Re: [FFmpeg-devel] [PATCH v4] avformat/movenc: split empty text sample when duration overflow

2019-10-09 Thread Jun Li
On Mon, Oct 7, 2019 at 6:36 PM Jun Li  wrote:

>
>
> On Mon, Oct 7, 2019 at 6:34 PM Jun Li  wrote:
>
>> Fix #7637
>> One empty/end sample is created and inserted between two caption lines
>> when there is a gap.
>> This patch is to split the sample into multiple ones when its duration is
>> too long (>= INT_MAX)
>>
>> Signed-off-by: Jun Li 
>> ---
>>  libavformat/movenc.c  | 26 ++-
>>  tests/fate/subtitles.mak  |  6 +
>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>  4 files changed, 28 insertions(+), 6 deletions(-)
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>
>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> index 715bec1c2f..5dc2a19c3c 100644
>> --- a/libavformat/movenc.c
>> +++ b/libavformat/movenc.c
>> @@ -5750,7 +5750,8 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>   *
>>   * 2) For each subtitle track, check if the current packet's
>>   * dts is past the duration of the last subtitle sample. If
>> - * so, we now need to write an end sample for that subtitle.
>> + * so, we now need to write one or multiple end samples for
>> + * that subtitle.
>>   *
>>   * This must be done conditionally to allow for subtitles that
>>   * immediately replace each other, in which case an end sample
>> @@ -5764,11 +5765,24 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>  int ret;
>>
>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>> -trk->track_duration < pkt->dts &&
>> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
>> -ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> -if (ret < 0) return ret;
>> -trk->last_sample_is_subtitle_end = 1;
>> +trk->track_duration < pkt->dts) {
>> +int max_duration = INT_MAX - 1;
>> +if (trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end) {
>> +ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> +if (ret < 0)
>> +return ret;
>> +trk->last_sample_is_subtitle_end = 1;
>> +}
>> +if (trk->last_sample_is_subtitle_end &&
>> +pkt->dts - trk->track_duration > max_duration) {
>> +int64_t dts = trk->track_duration;
>> +while(pkt->dts - dts > max_duration) {
>> +dts += max_duration;
>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>> +if (ret < 0)
>> +return ret;
>> +}
>> +}
>>  }
>>  }
>>
>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>> index 0042902161..4c2b34c431 100644
>> --- a/tests/fate/subtitles.mak
>> +++ b/tests/fate/subtitles.mak
>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>  fate-binsub-movtextenc: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur
>> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>> +
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur-timebase
>> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
>> frag_keyframe+empty_moov
>> +
>>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>>  fate-sub-mpl2: CMD = f

[FFmpeg-devel] [PATCH v2] avcodec/h264_parse: decode sps before pps

2019-10-07 Thread Jun Li
Fix ticket #6422
The content put pps before sps, which is not a common case. The change
put decoding sps before pps, just for compability.

Signed-off-by: Jun Li 
---
 libavcodec/h264_parse.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index 352ffea948..eeda5a76e5 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -373,35 +373,36 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 goto fail;
 }
 
+/* decode sps before pps, just in case some bitstream put pps before sps. 
*/
 for (i = 0; i < pkt.nb_nals; i++) {
 H2645NAL *nal = [i];
-switch (nal->type) {
-case H264_NAL_SPS: {
+if (nal->type == H264_NAL_SPS) {
 GetBitContext tmp_gb = nal->gb;
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 av_log(logctx, AV_LOG_DEBUG,
"SPS decoding failure, trying again with the complete 
NAL\n");
 init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 1);
 if (ret < 0)
 goto fail;
-break;
 }
-case H264_NAL_PPS:
+}
+
+for (i = 0; i < pkt.nb_nals; i++) {
+H2645NAL *nal = [i];
+if (nal->type == H264_NAL_PPS) {
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
nal->size_bits);
 if (ret < 0)
 goto fail;
-break;
-default:
+} else if (nal->type != H264_NAL_SPS) {
 av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in 
extradata\n",
nal->type);
-break;
 }
 }
 
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v1] avcodec/h264_parse: decode sps before pps

2019-10-07 Thread Jun Li
On Mon, Oct 7, 2019 at 7:50 PM Fu, Linjie  wrote:

> > -Original Message-
> > From: ffmpeg-devel  On Behalf Of Jun
> > Li
> > Sent: Tuesday, October 8, 2019 05:42
> > To: ffmpeg-devel@ffmpeg.org
> > Subject: [FFmpeg-devel] [PATCH v1] avcodec/h264_parse: decode sps
> > before pps
> >
> > Fix ticket #6422
> > The content put pps before sps, which is not a common case. The change
> > just put decoding sps before pps, just for compability.
> >
> > Signed-off-by: Jun Li 
> > ---
> >  libavcodec/h264_parse.c | 21 +++--
> >  1 file changed, 11 insertions(+), 10 deletions(-)
> >
> > diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> > index 352ffea948..26aaa751ad 100644
> > --- a/libavcodec/h264_parse.c
> > +++ b/libavcodec/h264_parse.c
> > @@ -373,35 +373,36 @@ static int decode_extradata_ps(const uint8_t *data,
> > int size, H264ParamSets *ps,
> >  goto fail;
> >  }
> >
> > -for (i = 0; i < pkt.nb_nals; i++) {
> > +/* decode sps before pps, just in case some bitstream put pps
> before sps.
> > */
> > +for(i = 0; i < pkt.nb_nals; i++) {
>
> Nit: Missing space here.


Thanks, will fix in next iteration.


>
>
- linjie
> ___
> 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".
___
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".

Re: [FFmpeg-devel] [PATCH v4] avformat/movenc: split empty text sample when duration overflow

2019-10-07 Thread Jun Li
On Mon, Oct 7, 2019 at 6:34 PM Jun Li  wrote:

> Fix #7637
> One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> This patch is to split the sample into multiple ones when its duration is
> too long (>= INT_MAX)
>
> Signed-off-by: Jun Li 
> ---
>  libavformat/movenc.c  | 26 ++-
>  tests/fate/subtitles.mak  |  6 +
>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>  4 files changed, 28 insertions(+), 6 deletions(-)
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 715bec1c2f..5dc2a19c3c 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -5750,7 +5750,8 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>   *
>   * 2) For each subtitle track, check if the current packet's
>   * dts is past the duration of the last subtitle sample. If
> - * so, we now need to write an end sample for that subtitle.
> + * so, we now need to write one or multiple end samples for
> + * that subtitle.
>   *
>   * This must be done conditionally to allow for subtitles that
>   * immediately replace each other, in which case an end sample
> @@ -5764,11 +5765,24 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>  int ret;
>
>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> -trk->track_duration < pkt->dts &&
> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
> -ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> -if (ret < 0) return ret;
> -trk->last_sample_is_subtitle_end = 1;
> +trk->track_duration < pkt->dts) {
> +int max_duration = INT_MAX - 1;
> +if (trk->entry == 0 || !trk->last_sample_is_subtitle_end)
> {
> +ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> +if (ret < 0)
> +return ret;
> +trk->last_sample_is_subtitle_end = 1;
> +}
> +if (trk->last_sample_is_subtitle_end &&
> +pkt->dts - trk->track_duration > max_duration) {
> +int64_t dts = trk->track_duration;
> +while(pkt->dts - dts > max_duration) {
> +dts += max_duration;
> +ret = mov_write_subtitle_end_packet(s, i, dts);
> +if (ret < 0)
> +return ret;
> +}
> +}
>  }
>  }
>
> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
> index 0042902161..4c2b34c431 100644
> --- a/tests/fate/subtitles.mak
> +++ b/tests/fate/subtitles.mak
> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MovText_capabilit
>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>  fate-binsub-movtextenc: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur
> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
> +
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur-timebase
> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
> frag_keyframe+empty_moov
> +
>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>  fate-sub-mpl2: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
>
> diff --git a/tests/ref/fate/binsub-movtextenc-long-dur
> b/tests/ref/fate/binsub-movtextenc-long-dur
> new file mode 100644
> index 00..eb8a3f8fc7
> --- /dev/null
> +++ b/tests/ref/fate/binsub-movtextenc-long-dur
> @@ -0,0 +1 @@
> +7f78c11bb4a6b16335540ef31ba10219
> diff --git a/tests/ref/fate/binsub-movtextenc-long-du

[FFmpeg-devel] [PATCH v4] avformat/movenc: split empty text sample when duration overflow

2019-10-07 Thread Jun Li
Fix #7637
One empty/end sample is created and inserted between two caption lines when 
there is a gap.
This patch is to split the sample into multiple ones when its duration is too 
long (>= INT_MAX)

Signed-off-by: Jun Li 
---
 libavformat/movenc.c  | 26 ++-
 tests/fate/subtitles.mak  |  6 +
 tests/ref/fate/binsub-movtextenc-long-dur |  1 +
 .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
 4 files changed, 28 insertions(+), 6 deletions(-)
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 715bec1c2f..5dc2a19c3c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5750,7 +5750,8 @@ static int mov_write_packet(AVFormatContext *s, AVPacket 
*pkt)
  *
  * 2) For each subtitle track, check if the current packet's
  * dts is past the duration of the last subtitle sample. If
- * so, we now need to write an end sample for that subtitle.
+ * so, we now need to write one or multiple end samples for
+ * that subtitle.
  *
  * This must be done conditionally to allow for subtitles that
  * immediately replace each other, in which case an end sample
@@ -5764,11 +5765,24 @@ static int mov_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 int ret;
 
 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
-trk->track_duration < pkt->dts &&
-(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
-ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
-if (ret < 0) return ret;
-trk->last_sample_is_subtitle_end = 1;
+trk->track_duration < pkt->dts) {
+int max_duration = INT_MAX - 1;
+if (trk->entry == 0 || !trk->last_sample_is_subtitle_end) {
+ret = mov_write_subtitle_end_packet(s, i, 
trk->track_duration);
+if (ret < 0)
+return ret;
+trk->last_sample_is_subtitle_end = 1;
+}
+if (trk->last_sample_is_subtitle_end &&
+pkt->dts - trk->track_duration > max_duration) {
+int64_t dts = trk->track_duration;
+while(pkt->dts - dts > max_duration) {
+dts += max_duration;
+ret = mov_write_subtitle_end_packet(s, i, dts);
+if (ret < 0)
+return ret;
+}
+}
 }
 }
 
diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
index 0042902161..4c2b34c431 100644
--- a/tests/fate/subtitles.mak
+++ b/tests/fate/subtitles.mak
@@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MovText_capabilit
 FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
 fate-binsub-movtextenc: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
 
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc-long-dur
+fate-binsub-movtextenc-long-dur: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
+
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += 
fate-binsub-movtextenc-long-dur-timebase
+fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text 
-time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags 
frag_keyframe+empty_moov
+
 FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
 fate-sub-mpl2: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
 
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur 
b/tests/ref/fate/binsub-movtextenc-long-dur
new file mode 100644
index 00..eb8a3f8fc7
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur
@@ -0,0 +1 @@
+7f78c11bb4a6b16335540ef31ba10219
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur-timebase 
b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
new file mode 100644
index 00..185dcc0aab
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
@@ -0,0 +1 @@
+349d78698cc1226d33d4e6699dbf46d9
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avcodec/h264_parse: decode sps before pps

2019-10-07 Thread Jun Li
Fix ticket #6422
The content put pps before sps, which is not a common case. The change
just put decoding sps before pps, just for compability.

Signed-off-by: Jun Li 
---
 libavcodec/h264_parse.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index 352ffea948..26aaa751ad 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -373,35 +373,36 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 goto fail;
 }
 
-for (i = 0; i < pkt.nb_nals; i++) {
+/* decode sps before pps, just in case some bitstream put pps before sps. 
*/
+for(i = 0; i < pkt.nb_nals; i++) {
 H2645NAL *nal = [i];
-switch (nal->type) {
-case H264_NAL_SPS: {
+if (nal->type == H264_NAL_SPS) {
 GetBitContext tmp_gb = nal->gb;
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 av_log(logctx, AV_LOG_DEBUG,
"SPS decoding failure, trying again with the complete 
NAL\n");
 init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 1);
 if (ret < 0)
 goto fail;
-break;
 }
-case H264_NAL_PPS:
+}
+
+for (i = 0; i < pkt.nb_nals; i++) {
+H2645NAL *nal = [i];
+if (nal->type == H264_NAL_PPS) {
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
nal->size_bits);
 if (ret < 0)
 goto fail;
-break;
-default:
+} else if (nal->type != H264_NAL_SPS) {
 av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in 
extradata\n",
nal->type);
-break;
 }
 }
 
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avcodec/h264_parse: decode sps before pps Fix ticket #6422 The content put pps before sps, which is not a common case. The change just put decoding sps before pps, just for c

2019-10-07 Thread Jun Li
Signed-off-by: Jun Li 
---
 libavcodec/h264_parse.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index 352ffea948..26aaa751ad 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -373,35 +373,36 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 goto fail;
 }
 
-for (i = 0; i < pkt.nb_nals; i++) {
+/* decode sps before pps, just in case some bitstream put pps before sps. 
*/
+for(i = 0; i < pkt.nb_nals; i++) {
 H2645NAL *nal = [i];
-switch (nal->type) {
-case H264_NAL_SPS: {
+if (nal->type == H264_NAL_SPS) {
 GetBitContext tmp_gb = nal->gb;
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 av_log(logctx, AV_LOG_DEBUG,
"SPS decoding failure, trying again with the complete 
NAL\n");
 init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
 ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
 if (ret >= 0)
-break;
+continue;
 ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 1);
 if (ret < 0)
 goto fail;
-break;
 }
-case H264_NAL_PPS:
+}
+
+for (i = 0; i < pkt.nb_nals; i++) {
+H2645NAL *nal = [i];
+if (nal->type == H264_NAL_PPS) {
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
nal->size_bits);
 if (ret < 0)
 goto fail;
-break;
-default:
+} else if (nal->type != H264_NAL_SPS) {
 av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in 
extradata\n",
nal->type);
-break;
 }
 }
 
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avformat/tee.c: steal bsf option before passing to fifo muxer

2019-10-05 Thread Jun Li
Fix #7620
In the case tee muxer with both "bsf" and "use_fifo" parameters
wil trigger this bug. Tee muxer will first steal parameters (like "f",
"select"...) and then "use_fifo" will try reading out remaining options
and pass them to fifo as option "format_options".
Current code miss the part of stealing "bsf" options.
---
 libavformat/tee.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/libavformat/tee.c b/libavformat/tee.c
index 89a4ceb280..3530582dbd 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -159,7 +159,7 @@ static void close_slaves(AVFormatContext *avf)
 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
 {
 int i, ret;
-AVDictionary *options = NULL;
+AVDictionary *options = NULL, *bsf_options = NULL;
 AVDictionaryEntry *entry;
 char *filename;
 char *format = NULL, *select = NULL, *on_fail = NULL;
@@ -186,6 +186,11 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 STEAL_OPTION("onfail", on_fail);
 STEAL_OPTION("use_fifo", use_fifo);
 STEAL_OPTION("fifo_options", fifo_options_str);
+entry = NULL;
+while ((entry = av_dict_get(options, "bsfs", entry, 
AV_DICT_IGNORE_SUFFIX))) {
+av_dict_set(_options, entry->key, entry->value, 0);
+av_dict_set(, entry->key, NULL, 0);
+}
 
 ret = parse_slave_failure_policy_option(on_fail, tee_slave);
 if (ret < 0) {
@@ -311,7 +316,7 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 }
 
 entry = NULL;
-while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) {
+while (entry = av_dict_get(bsf_options, "bsfs", NULL, 
AV_DICT_IGNORE_SUFFIX)) {
 const char *spec = entry->key + strlen("bsfs");
 if (*spec) {
 if (strspn(spec, slave_bsfs_spec_sep) != 1) {
@@ -352,7 +357,7 @@ static int open_slave(AVFormatContext *avf, char *slave, 
TeeSlave *tee_slave)
 }
 }
 
-av_dict_set(, entry->key, NULL, 0);
+av_dict_set(_options, entry->key, NULL, 0);
 }
 
 for (i = 0; i < avf->nb_streams; i++){
@@ -399,6 +404,7 @@ end:
 av_free(select);
 av_free(on_fail);
 av_dict_free();
+av_dict_free(_options);
 av_freep(_select);
 return ret;
 }
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-10-03 Thread Jun Li
On Wed, Oct 2, 2019 at 3:42 PM Jun Li  wrote:

>
>
> On Wed, Oct 2, 2019 at 3:22 PM Carl Eugen Hoyos 
> wrote:
>
>> Am Mi., 2. Okt. 2019 um 02:21 Uhr schrieb Jun Li :
>> >
>> > On Tue, Oct 1, 2019 at 4:19 AM Carl Eugen Hoyos 
>> wrote:
>> >
>> > > Am Di., 10. Sept. 2019 um 21:12 Uhr schrieb Jun Li <
>> junli1...@gmail.com>:
>> > > >
>> > > > Fix #7637
>> > > > One empty/end sample is created and inserted between two caption
>> lines
>> > > when there is a gap.
>> > > > This patch is to split the sample into multiple ones when its
>> duration
>> > > is too long (>= INT_MAX).
>> > > > ---
>> > > >  libavformat/movenc.c  | 24
>> ++-
>> > > >  tests/fate/subtitles.mak  |  6 +
>> > > >  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>> > > >  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>> > > >  4 files changed, 26 insertions(+), 6 deletions(-)
>> > > >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>> > > >  create mode 100644
>> tests/ref/fate/binsub-movtextenc-long-dur-timebase
>> > > >
>> > > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> > > > index edddfeeb00..aeb7de351f 100644
>> > > > --- a/libavformat/movenc.c
>> > > > +++ b/libavformat/movenc.c
>> > > > @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext
>> *s,
>> > > AVPacket *pkt)
>> > > >   *
>> > > >   * 2) For each subtitle track, check if the current
>> packet's
>> > > >   * dts is past the duration of the last subtitle sample. If
>> > > > - * so, we now need to write an end sample for that
>> subtitle.
>> > > > + * so, we now need to write one or multiple end samples for
>> > > > + * that subtitle.
>> > > >   *
>> > > >   * This must be done conditionally to allow for subtitles
>> that
>> > > >   * immediately replace each other, in which case an end
>> sample
>> > > > @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext
>> *s,
>> > > AVPacket *pkt)
>> > > >  int ret;
>> > > >
>> > > >  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>> > > > -trk->track_duration < pkt->dts &&
>> > > > -(trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end))
>> > > {
>> > > > -ret = mov_write_subtitle_end_packet(s, i,
>> > > trk->track_duration);
>> > > > -if (ret < 0) return ret;
>> > > > -trk->last_sample_is_subtitle_end = 1;
>> > > > +trk->track_duration < pkt->dts) {
>> > > > +int max_duration = INT_MAX - 1;
>> > > > +if (trk->entry == 0 ||
>> > > !trk->last_sample_is_subtitle_end) {
>> > > > +ret = mov_write_subtitle_end_packet(s, i,
>> > > trk->track_duration);
>> > >
>> > > > +if (ret < 0) return ret;
>> > >
>> > > > +trk->last_sample_is_subtitle_end = 1;
>> > > > +}
>> > > > +if (trk->last_sample_is_subtitle_end &&
>> > > > +pkt->dts - trk->track_duration > max_duration)
>> {
>> > > > +int64_t dts = trk->track_duration;
>> > > > +while(pkt->dts - dts > max_duration) {
>> > > > +dts += max_duration;
>> > > > +ret = mov_write_subtitle_end_packet(s, i,
>> dts);
>> > >
>> > > > +if (ret < 0) return ret;
>> > >
>> > > Please add two CRLFs and I am threatening to push this.
>> > >
>> > > Carl Eugen
>> > > ___
>> > > 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".
>> >
>> >
>> > Thanks Carl for review. Code is updated as follows.
>>
>> git returns an error message ("corrupt line") when I try to
>> commit this patch.
>>
>> Thanks for your time, I rebased the code and re-generated a patch,
> together with the fate test file, in the attachments.
> Could you please help do a re-try ? Thanks.
>

Hi Carl, could you please help to try again ? It should work now. Thanks in
advance!


> -Jun
>
>
>> Carl Eugen
>> ___
>> 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".
>
>
___
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".

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-10-02 Thread Jun Li
On Wed, Oct 2, 2019 at 3:22 PM Carl Eugen Hoyos  wrote:

> Am Mi., 2. Okt. 2019 um 02:21 Uhr schrieb Jun Li :
> >
> > On Tue, Oct 1, 2019 at 4:19 AM Carl Eugen Hoyos 
> wrote:
> >
> > > Am Di., 10. Sept. 2019 um 21:12 Uhr schrieb Jun Li <
> junli1...@gmail.com>:
> > > >
> > > > Fix #7637
> > > > One empty/end sample is created and inserted between two caption
> lines
> > > when there is a gap.
> > > > This patch is to split the sample into multiple ones when its
> duration
> > > is too long (>= INT_MAX).
> > > > ---
> > > >  libavformat/movenc.c  | 24
> ++-
> > > >  tests/fate/subtitles.mak  |  6 +
> > > >  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
> > > >  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
> > > >  4 files changed, 26 insertions(+), 6 deletions(-)
> > > >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
> > > >  create mode 100644
> tests/ref/fate/binsub-movtextenc-long-dur-timebase
> > > >
> > > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> > > > index edddfeeb00..aeb7de351f 100644
> > > > --- a/libavformat/movenc.c
> > > > +++ b/libavformat/movenc.c
> > > > @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
> > > AVPacket *pkt)
> > > >   *
> > > >   * 2) For each subtitle track, check if the current packet's
> > > >   * dts is past the duration of the last subtitle sample. If
> > > > - * so, we now need to write an end sample for that subtitle.
> > > > + * so, we now need to write one or multiple end samples for
> > > > + * that subtitle.
> > > >   *
> > > >   * This must be done conditionally to allow for subtitles
> that
> > > >   * immediately replace each other, in which case an end
> sample
> > > > @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext
> *s,
> > > AVPacket *pkt)
> > > >  int ret;
> > > >
> > > >  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> > > > -trk->track_duration < pkt->dts &&
> > > > -(trk->entry == 0 ||
> !trk->last_sample_is_subtitle_end))
> > > {
> > > > -ret = mov_write_subtitle_end_packet(s, i,
> > > trk->track_duration);
> > > > -if (ret < 0) return ret;
> > > > -trk->last_sample_is_subtitle_end = 1;
> > > > +trk->track_duration < pkt->dts) {
> > > > +int max_duration = INT_MAX - 1;
> > > > +if (trk->entry == 0 ||
> > > !trk->last_sample_is_subtitle_end) {
> > > > +ret = mov_write_subtitle_end_packet(s, i,
> > > trk->track_duration);
> > >
> > > > +if (ret < 0) return ret;
> > >
> > > > +trk->last_sample_is_subtitle_end = 1;
> > > > +}
> > > > +if (trk->last_sample_is_subtitle_end &&
> > > > +pkt->dts - trk->track_duration > max_duration) {
> > > > +int64_t dts = trk->track_duration;
> > > > +while(pkt->dts - dts > max_duration) {
> > > > +dts += max_duration;
> > > > +ret = mov_write_subtitle_end_packet(s, i,
> dts);
> > >
> > > > +if (ret < 0) return ret;
> > >
> > > Please add two CRLFs and I am threatening to push this.
> > >
> > > Carl Eugen
> > > ___
> > > 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".
> >
> >
> > Thanks Carl for review. Code is updated as follows.
>
> git returns an error message ("corrupt line") when I try to
> commit this patch.
>
> Thanks for your time, I rebased the code and re-generated a patch,
together with t

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-10-02 Thread Jun Li
On Tue, Oct 1, 2019 at 5:20 PM Jun Li  wrote:

>
>
> On Tue, Oct 1, 2019 at 4:19 AM Carl Eugen Hoyos 
> wrote:
>
>> Am Di., 10. Sept. 2019 um 21:12 Uhr schrieb Jun Li :
>> >
>> > Fix #7637
>> > One empty/end sample is created and inserted between two caption lines
>> when there is a gap.
>> > This patch is to split the sample into multiple ones when its duration
>> is too long (>= INT_MAX).
>> > ---
>> >  libavformat/movenc.c  | 24 ++-
>> >  tests/fate/subtitles.mak  |  6 +
>> >  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>> >  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>> >  4 files changed, 26 insertions(+), 6 deletions(-)
>> >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>> >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>> >
>> > diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> > index edddfeeb00..aeb7de351f 100644
>> > --- a/libavformat/movenc.c
>> > +++ b/libavformat/movenc.c
>> > @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>> >   *
>> >   * 2) For each subtitle track, check if the current packet's
>> >   * dts is past the duration of the last subtitle sample. If
>> > - * so, we now need to write an end sample for that subtitle.
>> > + * so, we now need to write one or multiple end samples for
>> > + * that subtitle.
>> >   *
>> >   * This must be done conditionally to allow for subtitles that
>> >   * immediately replace each other, in which case an end sample
>> > @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>> >  int ret;
>> >
>> >  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>> > -trk->track_duration < pkt->dts &&
>> > -(trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end)) {
>> > -ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> > -if (ret < 0) return ret;
>> > -trk->last_sample_is_subtitle_end = 1;
>> > +trk->track_duration < pkt->dts) {
>> > +int max_duration = INT_MAX - 1;
>> > +if (trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end) {
>> > +ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>>
>> > +if (ret < 0) return ret;
>>
>> > +trk->last_sample_is_subtitle_end = 1;
>> > +}
>> > +if (trk->last_sample_is_subtitle_end &&
>> > +pkt->dts - trk->track_duration > max_duration) {
>> > +int64_t dts = trk->track_duration;
>> > +while(pkt->dts - dts > max_duration) {
>> > +dts += max_duration;
>> > +ret = mov_write_subtitle_end_packet(s, i, dts);
>>
>> > +if (ret < 0) return ret;
>>
>> Please add two CRLFs and I am threatening to push this.
>>
>> Carl Eugen
>> ___
>> 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".
>
>
> Thanks Carl for review. Code is updated as follows.
>
>
>
> Fix #7637
> One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> This patch is to split the sample into multiple ones when its duration is
> too long (>= INT_MAX)
> ---
>  libavformat/movenc.c  | 26 ++-
>  tests/fate/subtitles.mak  |  6 +
>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>  4 files changed, 28 insertions(+), 6 deletions(-)
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index edddfeeb00..db6f5afe

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-10-01 Thread Jun Li
On Tue, Oct 1, 2019 at 4:19 AM Carl Eugen Hoyos  wrote:

> Am Di., 10. Sept. 2019 um 21:12 Uhr schrieb Jun Li :
> >
> > Fix #7637
> > One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> > This patch is to split the sample into multiple ones when its duration
> is too long (>= INT_MAX).
> > ---
> >  libavformat/movenc.c  | 24 ++-
> >  tests/fate/subtitles.mak  |  6 +
> >  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
> >  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
> >  4 files changed, 26 insertions(+), 6 deletions(-)
> >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
> >  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
> >
> > diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> > index edddfeeb00..aeb7de351f 100644
> > --- a/libavformat/movenc.c
> > +++ b/libavformat/movenc.c
> > @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
> >   *
> >   * 2) For each subtitle track, check if the current packet's
> >   * dts is past the duration of the last subtitle sample. If
> > - * so, we now need to write an end sample for that subtitle.
> > + * so, we now need to write one or multiple end samples for
> > + * that subtitle.
> >   *
> >   * This must be done conditionally to allow for subtitles that
> >   * immediately replace each other, in which case an end sample
> > @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
> >  int ret;
> >
> >  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> > -trk->track_duration < pkt->dts &&
> > -(trk->entry == 0 || !trk->last_sample_is_subtitle_end))
> {
> > -ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> > -if (ret < 0) return ret;
> > -trk->last_sample_is_subtitle_end = 1;
> > +trk->track_duration < pkt->dts) {
> > +int max_duration = INT_MAX - 1;
> > +if (trk->entry == 0 ||
> !trk->last_sample_is_subtitle_end) {
> > +ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
>
> > +if (ret < 0) return ret;
>
> > +trk->last_sample_is_subtitle_end = 1;
> > +}
> > +if (trk->last_sample_is_subtitle_end &&
> > +pkt->dts - trk->track_duration > max_duration) {
> > +int64_t dts = trk->track_duration;
> > +while(pkt->dts - dts > max_duration) {
> > +dts += max_duration;
> > +ret = mov_write_subtitle_end_packet(s, i, dts);
>
> > +if (ret < 0) return ret;
>
> Please add two CRLFs and I am threatening to push this.
>
> Carl Eugen
> ___
> 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".


Thanks Carl for review. Code is updated as follows.



Fix #7637
One empty/end sample is created and inserted between two caption lines when
there is a gap.
This patch is to split the sample into multiple ones when its duration is
too long (>= INT_MAX)
---
 libavformat/movenc.c  | 26 ++-
 tests/fate/subtitles.mak  |  6 +
 tests/ref/fate/binsub-movtextenc-long-dur |  1 +
 .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
 4 files changed, 28 insertions(+), 6 deletions(-)
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index edddfeeb00..db6f5afefc 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
AVPacket *pkt)
  *
  * 2) For each subtitle track, check if the current packet's
  * dts is past the duration of the last subtitle sample. If
- * so, we now need to write an end sample for that subtitle.
+ * so, we now need to write one or multiple end samples for
+ * tha

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-10-01 Thread Jun Li
On Thu, Sep 26, 2019 at 6:07 PM Jun Li  wrote:

>
>
> On Fri, Sep 20, 2019 at 9:46 PM Jun Li  wrote:
>
>>
>> On Sat, Sep 14, 2019 at 2:06 PM Jun Li  wrote:
>>
>>>
>>>
>>> On Tue, Sep 10, 2019 at 12:16 PM Jun Li  wrote:
>>>
>>>>
>>>>
>>>> On Tue, Sep 10, 2019 at 12:12 PM Jun Li  wrote:
>>>>
>>>>> Fix #7637
>>>>> One empty/end sample is created and inserted between two caption lines
>>>>> when there is a gap.
>>>>> This patch is to split the sample into multiple ones when its duration
>>>>> is too long (>= INT_MAX).
>>>>> ---
>>>>>  libavformat/movenc.c  | 24 ++-
>>>>>  tests/fate/subtitles.mak  |  6 +
>>>>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>>>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>>>>  4 files changed, 26 insertions(+), 6 deletions(-)
>>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>>>>
>>>>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>>>>> index edddfeeb00..aeb7de351f 100644
>>>>> --- a/libavformat/movenc.c
>>>>> +++ b/libavformat/movenc.c
>>>>> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>>>>> AVPacket *pkt)
>>>>>   *
>>>>>   * 2) For each subtitle track, check if the current packet's
>>>>>   * dts is past the duration of the last subtitle sample. If
>>>>> - * so, we now need to write an end sample for that subtitle.
>>>>> + * so, we now need to write one or multiple end samples for
>>>>> + * that subtitle.
>>>>>   *
>>>>>   * This must be done conditionally to allow for subtitles that
>>>>>   * immediately replace each other, in which case an end sample
>>>>> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext
>>>>> *s, AVPacket *pkt)
>>>>>  int ret;
>>>>>
>>>>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>>>>> -trk->track_duration < pkt->dts &&
>>>>> -(trk->entry == 0 ||
>>>>> !trk->last_sample_is_subtitle_end)) {
>>>>> -ret = mov_write_subtitle_end_packet(s, i,
>>>>> trk->track_duration);
>>>>> -if (ret < 0) return ret;
>>>>> -trk->last_sample_is_subtitle_end = 1;
>>>>> +trk->track_duration < pkt->dts) {
>>>>> +int max_duration = INT_MAX - 1;
>>>>> +if (trk->entry == 0 ||
>>>>> !trk->last_sample_is_subtitle_end) {
>>>>> +ret = mov_write_subtitle_end_packet(s, i,
>>>>> trk->track_duration);
>>>>> +if (ret < 0) return ret;
>>>>> +trk->last_sample_is_subtitle_end = 1;
>>>>> +}
>>>>> +if (trk->last_sample_is_subtitle_end &&
>>>>> +pkt->dts - trk->track_duration > max_duration) {
>>>>> +int64_t dts = trk->track_duration;
>>>>> +while(pkt->dts - dts > max_duration) {
>>>>> +dts += max_duration;
>>>>> +ret = mov_write_subtitle_end_packet(s, i,
>>>>> dts);
>>>>> +if (ret < 0) return ret;
>>>>> +}
>>>>> +}
>>>>>  }
>>>>>  }
>>>>>
>>>>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>>>>> index 0042902161..4c2b34c431 100644
>>>>> --- a/tests/fate/subtitles.mak
>>>>> +++ b/tests/fate/subtitles.mak
>>>>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>>>>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>>>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-09-26 Thread Jun Li
On Fri, Sep 20, 2019 at 9:46 PM Jun Li  wrote:

>
> On Sat, Sep 14, 2019 at 2:06 PM Jun Li  wrote:
>
>>
>>
>> On Tue, Sep 10, 2019 at 12:16 PM Jun Li  wrote:
>>
>>>
>>>
>>> On Tue, Sep 10, 2019 at 12:12 PM Jun Li  wrote:
>>>
>>>> Fix #7637
>>>> One empty/end sample is created and inserted between two caption lines
>>>> when there is a gap.
>>>> This patch is to split the sample into multiple ones when its duration
>>>> is too long (>= INT_MAX).
>>>> ---
>>>>  libavformat/movenc.c  | 24 ++-
>>>>  tests/fate/subtitles.mak  |  6 +
>>>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>>>  4 files changed, 26 insertions(+), 6 deletions(-)
>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>>>
>>>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>>>> index edddfeeb00..aeb7de351f 100644
>>>> --- a/libavformat/movenc.c
>>>> +++ b/libavformat/movenc.c
>>>> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>>>> AVPacket *pkt)
>>>>   *
>>>>   * 2) For each subtitle track, check if the current packet's
>>>>   * dts is past the duration of the last subtitle sample. If
>>>> - * so, we now need to write an end sample for that subtitle.
>>>> + * so, we now need to write one or multiple end samples for
>>>> + * that subtitle.
>>>>   *
>>>>   * This must be done conditionally to allow for subtitles that
>>>>   * immediately replace each other, in which case an end sample
>>>> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
>>>> AVPacket *pkt)
>>>>  int ret;
>>>>
>>>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>>>> -trk->track_duration < pkt->dts &&
>>>> -(trk->entry == 0 ||
>>>> !trk->last_sample_is_subtitle_end)) {
>>>> -ret = mov_write_subtitle_end_packet(s, i,
>>>> trk->track_duration);
>>>> -if (ret < 0) return ret;
>>>> -trk->last_sample_is_subtitle_end = 1;
>>>> +trk->track_duration < pkt->dts) {
>>>> +int max_duration = INT_MAX - 1;
>>>> +if (trk->entry == 0 ||
>>>> !trk->last_sample_is_subtitle_end) {
>>>> +ret = mov_write_subtitle_end_packet(s, i,
>>>> trk->track_duration);
>>>> +if (ret < 0) return ret;
>>>> +trk->last_sample_is_subtitle_end = 1;
>>>> +}
>>>> +if (trk->last_sample_is_subtitle_end &&
>>>> +pkt->dts - trk->track_duration > max_duration) {
>>>> +int64_t dts = trk->track_duration;
>>>> +while(pkt->dts - dts > max_duration) {
>>>> +dts += max_duration;
>>>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>>>> +if (ret < 0) return ret;
>>>> +}
>>>> +}
>>>>  }
>>>>  }
>>>>
>>>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>>>> index 0042902161..4c2b34c431 100644
>>>> --- a/tests/fate/subtitles.mak
>>>> +++ b/tests/fate/subtitles.mak
>>>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>>>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>>>  fate-binsub-movtextenc: CMD = md5 -i
>>>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags 
>>>> frag_keyframe+empty_moov
>>>>
>>>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>>>> fate-binsub-movtextenc-long-dur
>>>> +fate-binsu

Re: [FFmpeg-devel] [PATCH v1] lavf/mov: Fix timestamp rescale on sidx atom

2019-09-23 Thread Jun Li
On Thu, Aug 15, 2019 at 1:02 AM myp...@gmail.com  wrote:

> On Thu, Aug 15, 2019 at 12:49 PM Jun Li  wrote:
> >
> > On Thu, Jun 20, 2019 at 2:02 AM Jun Li  wrote:
> >
> > >
> > >
> > > On Tue, May 21, 2019 at 1:05 AM Jun Li  wrote:
> > >
> > >>
> > >>
> > >> On Thu, May 16, 2019 at 1:00 AM Jun Li  wrote:
> > >>
> > >>>
> > >>>
> > >>> On Sun, May 12, 2019 at 7:44 PM Jun Li  wrote:
> > >>>
> > >>>>
> > >>>>
> > >>>> On Fri, May 10, 2019 at 7:25 PM Jun Li  wrote:
> > >>>>
> > >>>>>
> > >>>>> On Thu, May 9, 2019 at 2:08 AM Jun Li  wrote:
> > >>>>>
> > >>>>>> Fix #5090
> > >>>>>> Fix the timestamp rescale issue, from sidx timebase to
> > >>>>>> stream's timebase.
> > >>>>>> ---
> > >>>>>>  libavformat/mov.c | 2 +-
> > >>>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
> > >>>>>>
> > >>>>>> diff --git a/libavformat/mov.c b/libavformat/mov.c
> > >>>>>> index 78f692872b..d058855e6c 100644
> > >>>>>> --- a/libavformat/mov.c
> > >>>>>> +++ b/libavformat/mov.c
> > >>>>>> @@ -5017,7 +5017,7 @@ static int mov_read_sidx(MOVContext *c,
> > >>>>>> AVIOContext *pb, MOVAtom atom)
> > >>>>>>  return AVERROR_PATCHWELCOME;
> > >>>>>>  }
> > >>>>>>  avio_rb32(pb); // sap_flags
> > >>>>>> -timestamp = av_rescale_q(pts, st->time_base, timescale);
> > >>>>>> +timestamp = av_rescale_q(pts, timescale, st->time_base);
> > >>>>>>
> > >>>>>>  index = update_frag_index(c, offset);
> > >>>>>>  frag_stream_info = get_frag_stream_info(>frag_index,
> > >>>>>> index, track_id);
> > >>>>>> --
> > >>>>>> 2.17.1
> > >>>>>>
> > >>>>>
> > >>>>> Ping
> > >>>>>
> > >>>>
> > >>>> This change is for fix the issue of calculating sidx_pts.
> > >>>> Sidx box has "earliest_presentation_time", used as pts of  the
> referent
> > >>>> track, sidx also has timescale field.
> > >>>> So the operation should convert from sidx's timescale to track's
> > >>>> timescale, this patch is for addressing this, as well as fixing
> #5090.
> > >>>>
> > >>>> Of course this is based on my understanding, so please correct me
> if I
> > >>>> am wrong. Thanks !
> > >>>>
> > >>>>
> > >>> Ping.
> > >>> I believe this is a bug and triggered whenever sidx box's timescale
> is
> > >>> different from track's timescale.
> > >>> Created this kind of content and verified that ffplay couldn't play
> > >>> while VLC plays well.
> > >>> Then I checked VLC's implementation:
> > >>>
> > >>>
> https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
> > >>>
> > >>> Hope someone could help to have a review ? Thanks ! :)
> > >>>
> > >>> Best Regards,
> > >>> -Jun
> > >>>
> > >>>
> > >>>> Best Regards,
> > >>>> Jun
> > >>>>
> > >>>
> > >> Ping x 3
> > >>
> > >
> > > Ping x 4.
> > > I believe this is an obvious bug and happened whenever sidx box's
> > > timescale is different from track's timescale.
> > > I created this kind of content and verified that ffplay couldn't play
> > > while VLC plays well.
> > > This is  VLC's implementation:
> > >
> > >
> https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
> > >
> >
> > Ping x 5
> Tested and verified with ffplay/ffprobe, now the sample video DTS is
> monotonically increasing without wrap around.
> ___
> 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".


Ping x 6
___
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".

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-09-20 Thread Jun Li
On Sat, Sep 14, 2019 at 2:06 PM Jun Li  wrote:

>
>
> On Tue, Sep 10, 2019 at 12:16 PM Jun Li  wrote:
>
>>
>>
>> On Tue, Sep 10, 2019 at 12:12 PM Jun Li  wrote:
>>
>>> Fix #7637
>>> One empty/end sample is created and inserted between two caption lines
>>> when there is a gap.
>>> This patch is to split the sample into multiple ones when its duration
>>> is too long (>= INT_MAX).
>>> ---
>>>  libavformat/movenc.c  | 24 ++-
>>>  tests/fate/subtitles.mak  |  6 +
>>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>>  4 files changed, 26 insertions(+), 6 deletions(-)
>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>>
>>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>>> index edddfeeb00..aeb7de351f 100644
>>> --- a/libavformat/movenc.c
>>> +++ b/libavformat/movenc.c
>>> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>>> AVPacket *pkt)
>>>   *
>>>   * 2) For each subtitle track, check if the current packet's
>>>   * dts is past the duration of the last subtitle sample. If
>>> - * so, we now need to write an end sample for that subtitle.
>>> + * so, we now need to write one or multiple end samples for
>>> + * that subtitle.
>>>   *
>>>   * This must be done conditionally to allow for subtitles that
>>>   * immediately replace each other, in which case an end sample
>>> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
>>> AVPacket *pkt)
>>>  int ret;
>>>
>>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>>> -trk->track_duration < pkt->dts &&
>>> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end))
>>> {
>>> -ret = mov_write_subtitle_end_packet(s, i,
>>> trk->track_duration);
>>> -if (ret < 0) return ret;
>>> -trk->last_sample_is_subtitle_end = 1;
>>> +trk->track_duration < pkt->dts) {
>>> +int max_duration = INT_MAX - 1;
>>> +if (trk->entry == 0 ||
>>> !trk->last_sample_is_subtitle_end) {
>>> +ret = mov_write_subtitle_end_packet(s, i,
>>> trk->track_duration);
>>> +if (ret < 0) return ret;
>>> +trk->last_sample_is_subtitle_end = 1;
>>> +}
>>> +if (trk->last_sample_is_subtitle_end &&
>>> +pkt->dts - trk->track_duration > max_duration) {
>>> +int64_t dts = trk->track_duration;
>>> +while(pkt->dts - dts > max_duration) {
>>> +dts += max_duration;
>>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>>> +if (ret < 0) return ret;
>>> +}
>>> +}
>>>  }
>>>  }
>>>
>>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>>> index 0042902161..4c2b34c431 100644
>>> --- a/tests/fate/subtitles.mak
>>> +++ b/tests/fate/subtitles.mak
>>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>>  fate-binsub-movtextenc: CMD = md5 -i
>>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>>
>>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>>> fate-binsub-movtextenc-long-dur
>>> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
>>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>> +
>>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>>> fate-binsub-movtextenc-long-dur-timebase
>>> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-09-14 Thread Jun Li
On Tue, Sep 10, 2019 at 12:16 PM Jun Li  wrote:

>
>
> On Tue, Sep 10, 2019 at 12:12 PM Jun Li  wrote:
>
>> Fix #7637
>> One empty/end sample is created and inserted between two caption lines
>> when there is a gap.
>> This patch is to split the sample into multiple ones when its duration is
>> too long (>= INT_MAX).
>> ---
>>  libavformat/movenc.c  | 24 ++-
>>  tests/fate/subtitles.mak  |  6 +
>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>  4 files changed, 26 insertions(+), 6 deletions(-)
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>
>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> index edddfeeb00..aeb7de351f 100644
>> --- a/libavformat/movenc.c
>> +++ b/libavformat/movenc.c
>> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>   *
>>   * 2) For each subtitle track, check if the current packet's
>>   * dts is past the duration of the last subtitle sample. If
>> - * so, we now need to write an end sample for that subtitle.
>> + * so, we now need to write one or multiple end samples for
>> + * that subtitle.
>>   *
>>   * This must be done conditionally to allow for subtitles that
>>   * immediately replace each other, in which case an end sample
>> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>  int ret;
>>
>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>> -trk->track_duration < pkt->dts &&
>> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
>> -ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> -if (ret < 0) return ret;
>> -trk->last_sample_is_subtitle_end = 1;
>> +trk->track_duration < pkt->dts) {
>> +int max_duration = INT_MAX - 1;
>> +if (trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end) {
>> +ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> +if (ret < 0) return ret;
>> +trk->last_sample_is_subtitle_end = 1;
>> +}
>> +if (trk->last_sample_is_subtitle_end &&
>> +pkt->dts - trk->track_duration > max_duration) {
>> +int64_t dts = trk->track_duration;
>> +while(pkt->dts - dts > max_duration) {
>> +dts += max_duration;
>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>> +if (ret < 0) return ret;
>> +}
>> +}
>>  }
>>  }
>>
>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>> index 0042902161..4c2b34c431 100644
>> --- a/tests/fate/subtitles.mak
>> +++ b/tests/fate/subtitles.mak
>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>  fate-binsub-movtextenc: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur
>> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>> +
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur-timebase
>> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
>> frag_keyframe+empty_moov
>> +
>>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>>  fate-sub-mpl2: CMD = fmtstdout ass -i
>> $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
>>
>> diff --git a/tests

Re: [FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-09-10 Thread Jun Li
On Tue, Sep 10, 2019 at 12:12 PM Jun Li  wrote:

> Fix #7637
> One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> This patch is to split the sample into multiple ones when its duration is
> too long (>= INT_MAX).
> ---
>  libavformat/movenc.c  | 24 ++-
>  tests/fate/subtitles.mak  |  6 +
>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>  4 files changed, 26 insertions(+), 6 deletions(-)
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index edddfeeb00..aeb7de351f 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>   *
>   * 2) For each subtitle track, check if the current packet's
>   * dts is past the duration of the last subtitle sample. If
> - * so, we now need to write an end sample for that subtitle.
> + * so, we now need to write one or multiple end samples for
> + * that subtitle.
>   *
>   * This must be done conditionally to allow for subtitles that
>   * immediately replace each other, in which case an end sample
> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>  int ret;
>
>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> -trk->track_duration < pkt->dts &&
> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
> -ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> -if (ret < 0) return ret;
> -trk->last_sample_is_subtitle_end = 1;
> +trk->track_duration < pkt->dts) {
> +int max_duration = INT_MAX - 1;
> +if (trk->entry == 0 || !trk->last_sample_is_subtitle_end)
> {
> +ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> +if (ret < 0) return ret;
> +trk->last_sample_is_subtitle_end = 1;
> +}
> +if (trk->last_sample_is_subtitle_end &&
> +pkt->dts - trk->track_duration > max_duration) {
> +int64_t dts = trk->track_duration;
> +while(pkt->dts - dts > max_duration) {
> +dts += max_duration;
> +ret = mov_write_subtitle_end_packet(s, i, dts);
> +if (ret < 0) return ret;
> +}
> +}
>  }
>  }
>
> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
> index 0042902161..4c2b34c431 100644
> --- a/tests/fate/subtitles.mak
> +++ b/tests/fate/subtitles.mak
> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MovText_capabilit
>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>  fate-binsub-movtextenc: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur
> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
> +
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur-timebase
> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
> frag_keyframe+empty_moov
> +
>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>  fate-sub-mpl2: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
>
> diff --git a/tests/ref/fate/binsub-movtextenc-long-dur
> b/tests/ref/fate/binsub-movtextenc-long-dur
> new file mode 100644
> index 00..eb8a3f8fc7
> --- /dev/null
> +++ b/tests/ref/fate/binsub-movtextenc-long-dur
> @@ -0,0 +1 @@
> +7f78c11bb4a6b16335540ef31ba10219
> diff --git a/tests/ref/fate/binsub-movtextenc-long-dur-timebase
> b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
> new file mode 100644
&g

[FFmpeg-devel] [PATCH v3] avformat/movenc: split empty text sample when duration overflow

2019-09-10 Thread Jun Li
Fix #7637
One empty/end sample is created and inserted between two caption lines when 
there is a gap.
This patch is to split the sample into multiple ones when its duration is too 
long (>= INT_MAX).
---
 libavformat/movenc.c  | 24 ++-
 tests/fate/subtitles.mak  |  6 +
 tests/ref/fate/binsub-movtextenc-long-dur |  1 +
 .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
 4 files changed, 26 insertions(+), 6 deletions(-)
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index edddfeeb00..aeb7de351f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s, AVPacket 
*pkt)
  *
  * 2) For each subtitle track, check if the current packet's
  * dts is past the duration of the last subtitle sample. If
- * so, we now need to write an end sample for that subtitle.
+ * so, we now need to write one or multiple end samples for
+ * that subtitle.
  *
  * This must be done conditionally to allow for subtitles that
  * immediately replace each other, in which case an end sample
@@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 int ret;
 
 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
-trk->track_duration < pkt->dts &&
-(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
-ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
-if (ret < 0) return ret;
-trk->last_sample_is_subtitle_end = 1;
+trk->track_duration < pkt->dts) {
+int max_duration = INT_MAX - 1;
+if (trk->entry == 0 || !trk->last_sample_is_subtitle_end) {
+ret = mov_write_subtitle_end_packet(s, i, 
trk->track_duration);
+if (ret < 0) return ret;
+trk->last_sample_is_subtitle_end = 1;
+}
+if (trk->last_sample_is_subtitle_end &&
+pkt->dts - trk->track_duration > max_duration) {
+int64_t dts = trk->track_duration;
+while(pkt->dts - dts > max_duration) {
+dts += max_duration;
+ret = mov_write_subtitle_end_packet(s, i, dts);
+if (ret < 0) return ret;
+}
+}
 }
 }
 
diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
index 0042902161..4c2b34c431 100644
--- a/tests/fate/subtitles.mak
+++ b/tests/fate/subtitles.mak
@@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MovText_capabilit
 FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
 fate-binsub-movtextenc: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
 
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc-long-dur
+fate-binsub-movtextenc-long-dur: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
+
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += 
fate-binsub-movtextenc-long-dur-timebase
+fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text 
-time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags 
frag_keyframe+empty_moov
+
 FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
 fate-sub-mpl2: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
 
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur 
b/tests/ref/fate/binsub-movtextenc-long-dur
new file mode 100644
index 00..eb8a3f8fc7
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur
@@ -0,0 +1 @@
+7f78c11bb4a6b16335540ef31ba10219
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur-timebase 
b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
new file mode 100644
index 00..185dcc0aab
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
@@ -0,0 +1 @@
+349d78698cc1226d33d4e6699dbf46d9
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v2] avformat/movenc: split empty text sample when duration overflow

2019-09-08 Thread Jun Li
On Sun, Sep 8, 2019 at 5:59 PM Jun Li  wrote:

>
>
> On Sun, Sep 8, 2019 at 5:51 PM Jun Li  wrote:
>
>> Fix #7637
>> One empty/end sample is created and inserted between two caption lines
>> when there is a gap.
>> This patch is to split the sample into multiple ones when its duration is
>> too long (>= INT_MAX).
>> ---
>>  libavformat/movenc.c  | 24 ++-
>>  tests/fate/subtitles.mak  |  6 +
>>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>>  4 files changed, 26 insertions(+), 6 deletions(-)
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>>
>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> index edddfeeb00..aeb7de351f 100644
>> --- a/libavformat/movenc.c
>> +++ b/libavformat/movenc.c
>> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>   *
>>   * 2) For each subtitle track, check if the current packet's
>>   * dts is past the duration of the last subtitle sample. If
>> - * so, we now need to write an end sample for that subtitle.
>> + * so, we now need to write one or multiple end samples for
>> + * that subtitle.
>>   *
>>   * This must be done conditionally to allow for subtitles that
>>   * immediately replace each other, in which case an end sample
>> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>  int ret;
>>
>>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
>> -trk->track_duration < pkt->dts &&
>> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
>> -ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> -if (ret < 0) return ret;
>> -trk->last_sample_is_subtitle_end = 1;
>> +trk->track_duration < pkt->dts) {
>> +int max_duration = INT_MAX - 1;
>> +if (trk->entry == 0 ||
>> !trk->last_sample_is_subtitle_end) {
>> +ret = mov_write_subtitle_end_packet(s, i,
>> trk->track_duration);
>> +if (ret < 0) return ret;
>> +trk->last_sample_is_subtitle_end = 1;
>> +}
>> +if (trk->last_sample_is_subtitle_end &&
>> +pkt->dts - trk->track_duration > max_duration) {
>> +int64_t dts = trk->track_duration;
>> +while(pkt->dts - dts > max_duration) {
>> +dts += max_duration;
>> +ret = mov_write_subtitle_end_packet(s, i, dts);
>> +if (ret < 0) return ret;
>> +}
>> +}
>>  }
>>  }
>>
>> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
>> index 0042902161..59055e975c 100644
>> --- a/tests/fate/subtitles.mak
>> +++ b/tests/fate/subtitles.mak
>> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
>> $(TARGET_SAMPLES)/sub/MovText_capabilit
>>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>>  fate-binsub-movtextenc: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>>
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur
>> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -f mp4 -flags +bitexact -fflags +bitexact -movflags empty_moov
>> +
>> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
>> fate-binsub-movtextenc-long-dur-timebase
>> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
>> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
>> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
>> empty_moov
>> +
>>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>>  fate-sub-mpl2: CMD = fmtstdout ass -i
>> $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
>>
>> diff --git a/tests/ref/fate/binsub-movtextenc-l

Re: [FFmpeg-devel] [PATCH v2] avformat/movenc: split empty text sample when duration overflow

2019-09-08 Thread Jun Li
On Sun, Sep 8, 2019 at 5:51 PM Jun Li  wrote:

> Fix #7637
> One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> This patch is to split the sample into multiple ones when its duration is
> too long (>= INT_MAX).
> ---
>  libavformat/movenc.c  | 24 ++-
>  tests/fate/subtitles.mak  |  6 +
>  tests/ref/fate/binsub-movtextenc-long-dur |  1 +
>  .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
>  4 files changed, 26 insertions(+), 6 deletions(-)
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
>  create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index edddfeeb00..aeb7de351f 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>   *
>   * 2) For each subtitle track, check if the current packet's
>   * dts is past the duration of the last subtitle sample. If
> - * so, we now need to write an end sample for that subtitle.
> + * so, we now need to write one or multiple end samples for
> + * that subtitle.
>   *
>   * This must be done conditionally to allow for subtitles that
>   * immediately replace each other, in which case an end sample
> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>  int ret;
>
>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> -trk->track_duration < pkt->dts &&
> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
> -ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> -if (ret < 0) return ret;
> -trk->last_sample_is_subtitle_end = 1;
> +trk->track_duration < pkt->dts) {
> +int max_duration = INT_MAX - 1;
> +if (trk->entry == 0 || !trk->last_sample_is_subtitle_end)
> {
> +ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> +if (ret < 0) return ret;
> +trk->last_sample_is_subtitle_end = 1;
> +}
> +if (trk->last_sample_is_subtitle_end &&
> +pkt->dts - trk->track_duration > max_duration) {
> +int64_t dts = trk->track_duration;
> +while(pkt->dts - dts > max_duration) {
> +dts += max_duration;
> +ret = mov_write_subtitle_end_packet(s, i, dts);
> +if (ret < 0) return ret;
> +}
> +}
>  }
>  }
>
> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
> index 0042902161..59055e975c 100644
> --- a/tests/fate/subtitles.mak
> +++ b/tests/fate/subtitles.mak
> @@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MovText_capabilit
>  FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
>  fate-binsub-movtextenc: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
>
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur
> +fate-binsub-movtextenc-long-dur: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -f mp4 -flags +bitexact -fflags +bitexact -movflags empty_moov
> +
> +FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) +=
> fate-binsub-movtextenc-long-dur-timebase
> +fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i
> $(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text
> -time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags
> empty_moov
> +
>  FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
>  fate-sub-mpl2: CMD = fmtstdout ass -i
> $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
>
> diff --git a/tests/ref/fate/binsub-movtextenc-long-dur
> b/tests/ref/fate/binsub-movtextenc-long-dur
> new file mode 100644
> index 00..4db0be514b
> --- /dev/null
> +++ b/tests/ref/fate/binsub-movtextenc-long-dur
> @@ -0,0 +1 @@
> +043848a72c3ae75744115fe8d06c8bf1
> diff --git a/tests/ref/fate/binsub-movtextenc-long-dur-timebase
> b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
> new file mode 100644
> index 00..14b

[FFmpeg-devel] [PATCH v2] avformat/movenc: split empty text sample when duration overflow

2019-09-08 Thread Jun Li
Fix #7637
One empty/end sample is created and inserted between two caption lines when 
there is a gap.
This patch is to split the sample into multiple ones when its duration is too 
long (>= INT_MAX).
---
 libavformat/movenc.c  | 24 ++-
 tests/fate/subtitles.mak  |  6 +
 tests/ref/fate/binsub-movtextenc-long-dur |  1 +
 .../fate/binsub-movtextenc-long-dur-timebase  |  1 +
 4 files changed, 26 insertions(+), 6 deletions(-)
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur
 create mode 100644 tests/ref/fate/binsub-movtextenc-long-dur-timebase

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index edddfeeb00..aeb7de351f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s, AVPacket 
*pkt)
  *
  * 2) For each subtitle track, check if the current packet's
  * dts is past the duration of the last subtitle sample. If
- * so, we now need to write an end sample for that subtitle.
+ * so, we now need to write one or multiple end samples for
+ * that subtitle.
  *
  * This must be done conditionally to allow for subtitles that
  * immediately replace each other, in which case an end sample
@@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 int ret;
 
 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
-trk->track_duration < pkt->dts &&
-(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
-ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
-if (ret < 0) return ret;
-trk->last_sample_is_subtitle_end = 1;
+trk->track_duration < pkt->dts) {
+int max_duration = INT_MAX - 1;
+if (trk->entry == 0 || !trk->last_sample_is_subtitle_end) {
+ret = mov_write_subtitle_end_packet(s, i, 
trk->track_duration);
+if (ret < 0) return ret;
+trk->last_sample_is_subtitle_end = 1;
+}
+if (trk->last_sample_is_subtitle_end &&
+pkt->dts - trk->track_duration > max_duration) {
+int64_t dts = trk->track_duration;
+while(pkt->dts - dts > max_duration) {
+dts += max_duration;
+ret = mov_write_subtitle_end_packet(s, i, dts);
+if (ret < 0) return ret;
+}
+}
 }
 }
 
diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
index 0042902161..59055e975c 100644
--- a/tests/fate/subtitles.mak
+++ b/tests/fate/subtitles.mak
@@ -34,6 +34,12 @@ fate-sub-movtext: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MovText_capabilit
 FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc
 fate-binsub-movtextenc: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov
 
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc-long-dur
+fate-binsub-movtextenc-long-dur: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text -f 
mp4 -flags +bitexact -fflags +bitexact -movflags empty_moov
+
+FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += 
fate-binsub-movtextenc-long-dur-timebase
+fate-binsub-movtextenc-long-dur-timebase: CMD = md5 -i 
$(TARGET_SAMPLES)/sub/WebVTT_movtext_long_dur.vtt -map 0 -scodec mov_text 
-time_base 1000 -f mp4 -flags +bitexact -fflags +bitexact -movflags empty_moov
+
 FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
 fate-sub-mpl2: CMD = fmtstdout ass -i 
$(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt
 
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur 
b/tests/ref/fate/binsub-movtextenc-long-dur
new file mode 100644
index 00..4db0be514b
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur
@@ -0,0 +1 @@
+043848a72c3ae75744115fe8d06c8bf1
diff --git a/tests/ref/fate/binsub-movtextenc-long-dur-timebase 
b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
new file mode 100644
index 00..14b2f0167b
--- /dev/null
+++ b/tests/ref/fate/binsub-movtextenc-long-dur-timebase
@@ -0,0 +1 @@
+043848a72c3ae75744115fe8d06c8bf1
\ No newline at end of file
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v1] avformat/movenc: split empty text sample when duration overflow

2019-09-07 Thread Jun Li
On Fri, Sep 6, 2019 at 4:10 PM Jun Li  wrote:

> Fix #7637
> One empty/end sample is created and inserted between two caption lines
> when there is a gap.
> This patch is to split the sample into multiple ones when its duration is
> too long (>= INT_MAX).
> ---
>  libavformat/movenc.c | 24 ++--
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index edddfeeb00..aeb7de351f 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>   *
>   * 2) For each subtitle track, check if the current packet's
>   * dts is past the duration of the last subtitle sample. If
> - * so, we now need to write an end sample for that subtitle.
> + * so, we now need to write one or multiple end samples for
> + * that subtitle.
>   *
>   * This must be done conditionally to allow for subtitles that
>   * immediately replace each other, in which case an end sample
> @@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>  int ret;
>
>  if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
> -trk->track_duration < pkt->dts &&
> -(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
> -ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> -if (ret < 0) return ret;
> -trk->last_sample_is_subtitle_end = 1;
> +trk->track_duration < pkt->dts) {
> +int max_duration = INT_MAX - 1;
> +if (trk->entry == 0 || !trk->last_sample_is_subtitle_end)
> {
> +ret = mov_write_subtitle_end_packet(s, i,
> trk->track_duration);
> +if (ret < 0) return ret;
> +trk->last_sample_is_subtitle_end = 1;
> +}
> +if (trk->last_sample_is_subtitle_end &&
> +pkt->dts - trk->track_duration > max_duration) {
> +int64_t dts = trk->track_duration;
> +while(pkt->dts - dts > max_duration) {
> +dts += max_duration;
> +ret = mov_write_subtitle_end_packet(s, i, dts);
> +if (ret < 0) return ret;
> +}
> +}
>  }
>  }
>
> --
> 2.17.1
>
>
Some details:
Current implementation will insert one empty sample whenever there is a gap
between two captions lines. But when the gap's duration is way too big, the
sample's duration will exceed MP4's limitation, thus mov muxer will fail on
function check_pkt.

This patch is to guarantee that, every empty samples' duration not exceed
INT_MAX-1, and insert multiple ones when the gap is bigger than INT_MAX-1.

Test results:
Fate test passed. Also tested with following SRT file with cmd:

ffmpeg -i input.mp4 -i input.srt -c copy -c:s mov_text test.mp4 -y

I used Apple's QuickTime player, confirmed that the caption shows up at the
correct time.

"input. srt" as follows
1
00:35:47.484 --> 00:35:50.000
Durations that exceed the signed
int max value break the program

2
00:40:47.484 --> 00:40:50.000
Durations2 that exceed the signed
int max value break the program

3
00:50:47.484 --> 00:50:50.000
Durations3 that exceed the signed
int max value break the program

4
02:50:47.484 --> 02:50:50.000
Durations4 that exceed the signed
int max value break the program

5
03:50:47.484 --> 03:50:50.000
Durations5 that exceed the signed
int max value break the program
___
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".

[FFmpeg-devel] [PATCH v1] avformat/movenc: split empty text sample when duration overflow

2019-09-06 Thread Jun Li
Fix #7637
One empty/end sample is created and inserted between two caption lines when 
there is a gap.
This patch is to split the sample into multiple ones when its duration is too 
long (>= INT_MAX).
---
 libavformat/movenc.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index edddfeeb00..aeb7de351f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5746,7 +5746,8 @@ static int mov_write_packet(AVFormatContext *s, AVPacket 
*pkt)
  *
  * 2) For each subtitle track, check if the current packet's
  * dts is past the duration of the last subtitle sample. If
- * so, we now need to write an end sample for that subtitle.
+ * so, we now need to write one or multiple end samples for
+ * that subtitle.
  *
  * This must be done conditionally to allow for subtitles that
  * immediately replace each other, in which case an end sample
@@ -5760,11 +5761,22 @@ static int mov_write_packet(AVFormatContext *s, 
AVPacket *pkt)
 int ret;
 
 if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
-trk->track_duration < pkt->dts &&
-(trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
-ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
-if (ret < 0) return ret;
-trk->last_sample_is_subtitle_end = 1;
+trk->track_duration < pkt->dts) {
+int max_duration = INT_MAX - 1;
+if (trk->entry == 0 || !trk->last_sample_is_subtitle_end) {
+ret = mov_write_subtitle_end_packet(s, i, 
trk->track_duration);
+if (ret < 0) return ret;
+trk->last_sample_is_subtitle_end = 1;
+}
+if (trk->last_sample_is_subtitle_end &&
+pkt->dts - trk->track_duration > max_duration) {
+int64_t dts = trk->track_duration;
+while(pkt->dts - dts > max_duration) {
+dts += max_duration;
+ret = mov_write_subtitle_end_packet(s, i, dts);
+if (ret < 0) return ret;
+}
+}
 }
 }
 
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] libavformat/rtspdec: Don't send teardown if rtsp_hd_out is null

2019-08-28 Thread Jun Li
On Wed, Aug 28, 2019 at 3:09 PM Carl Eugen Hoyos  wrote:

> Am Mo., 5. Aug. 2019 um 09:19 Uhr schrieb Ross Nicholson <
> phunkyf...@gmail.com>:
> >
> > Example stream that does not work: rtsp://
> > 184.72.239.149/vod/mp4:BigBuckBunny_115k.mov
>
> Is this still valid?
>
>
Carl, you can try this one for validation: rtsp://
wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov

Hi Ross,
Just curious, is there any case the rt->rtsp_hd_out is NULL ?
Looks like the hd_out is either TCP or HTTP(http tunnel case) for RTSP
connection. And I only see it is set to NULL in ff_rtsp_close_connections,
which is called after your check.

-Jun

I get a time-out both with and without your patch.
>
> Carl Eugen
> ___
> 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".
___
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".

Re: [FFmpeg-devel] [PATCH v2] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-22 Thread Jun Li
On Thu, Aug 22, 2019 at 12:00 PM James Almer  wrote:

> On 8/19/2019 11:24 PM, Jun Li wrote:
> > Fix #6591
> > The content has no rbsp_stop_one_bit for ending the SPS, that
> > causes the decoding SPS failure, results decoding frame failure as well.
> >
> > The patch is just adding a retry with complete NALU, copied from the
> retry in decode_nal_unit()
> > ---
> >  libavcodec/h264_parse.c | 11 +--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> > index ac31f54e07..ea7a958dd9 100644
> > --- a/libavcodec/h264_parse.c
> > +++ b/libavcodec/h264_parse.c
> > @@ -376,8 +376,15 @@ static int decode_extradata_ps(const uint8_t *data,
> int size, H264ParamSets *ps,
> >  switch (nal->type) {
> >  case H264_NAL_SPS:
> >  ret = ff_h264_decode_seq_parameter_set(>gb, logctx,
> ps, 0);
> > -if (ret < 0)
> > -goto fail;
> > +if (ret < 0) {
> > +GetBitContext tmp_gb = nal->gb;
>
> nal->gb will already be changed here and will not be pointing to the
> start of the SPS.
>
> > +av_log(logctx, AV_LOG_DEBUG,
> > +   "SPS decoding failure, trying again with the
> complete NAL\n");
> > +init_get_bits8(_gb, nal->raw_data + 1,
> nal->raw_size - 1);
>
> And you're overwriting it here, so the above assignment was pointless.
>
> > +if ((ret = ff_h264_decode_seq_parameter_set(_gb,
> logctx, ps, 0)) < 0 &&
> > +(ret = ff_h264_decode_seq_parameter_set(_gb,
> logctx, ps, 1)) < 0)
>
> Similarly, tmp_gb will be not be pointing to the start of the SPS if the
> second ff_h264_decode_seq_parameter_set() call (with truncation enabled)
> is ever executed.
>
> > +goto fail;
> > +}
> >  break;
> >  case H264_NAL_PPS:
> >  ret = ff_h264_decode_picture_parameter_set(>gb,
> logctx, ps,
> >
>
> ___
> 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".


Thanks a lot James for pointing it out. Sorry about those obvious bugs.
I updated the version accordingly https://patchwork.ffmpeg.org/patch/14660/

-Jun
___
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".

[FFmpeg-devel] [PATCH v3] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-22 Thread Jun Li
Fix #6591
The content has no rbsp_stop_one_bit for ending the SPS, that
causes the decoding SPS failure, results decoding frame failure as well.

The patch is just adding a retry with complete NALU, copied from the retry in 
decode_nal_unit()
---
 libavcodec/h264_parse.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index ac31f54e07..baf8246cdc 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -374,11 +374,23 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 for (i = 0; i < pkt.nb_nals; i++) {
 H2645NAL *nal = [i];
 switch (nal->type) {
-case H264_NAL_SPS:
-ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 0);
-if (ret < 0)
-goto fail;
+case H264_NAL_SPS: {
+GetBitContext tmp_gb = nal->gb;
+ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
+if (ret < 0) {
+av_log(logctx, AV_LOG_DEBUG,
+  "SPS decoding failure, trying again with the complete 
NAL\n");
+init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
+ret = ff_h264_decode_seq_parameter_set(_gb, logctx, ps, 0);
+if (ret >= 0)
+break;
+
+ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 
1);
+if (ret < 0)
+goto fail;
+}
 break;
+}
 case H264_NAL_PPS:
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
nal->size_bits);
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v2] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-22 Thread Jun Li
On Tue, Aug 20, 2019 at 5:52 PM Jun Li  wrote:

>
>
> On Mon, Aug 19, 2019 at 7:24 PM Jun Li  wrote:
>
>> Fix #6591
>> The content has no rbsp_stop_one_bit for ending the SPS, that
>> causes the decoding SPS failure, results decoding frame failure as well.
>>
>> The patch is just adding a retry with complete NALU, copied from the
>> retry in decode_nal_unit()
>> ---
>>  libavcodec/h264_parse.c | 11 +--
>>  1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
>> index ac31f54e07..ea7a958dd9 100644
>> --- a/libavcodec/h264_parse.c
>> +++ b/libavcodec/h264_parse.c
>> @@ -376,8 +376,15 @@ static int decode_extradata_ps(const uint8_t *data,
>> int size, H264ParamSets *ps,
>>  switch (nal->type) {
>>  case H264_NAL_SPS:
>>  ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps,
>> 0);
>> -if (ret < 0)
>> -goto fail;
>> +if (ret < 0) {
>> +GetBitContext tmp_gb = nal->gb;
>> +av_log(logctx, AV_LOG_DEBUG,
>> +   "SPS decoding failure, trying again with the complete
>> NAL\n");
>> +init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size
>> - 1);
>> +if ((ret = ff_h264_decode_seq_parameter_set(_gb,
>> logctx, ps, 0)) < 0 &&
>> +(ret = ff_h264_decode_seq_parameter_set(_gb,
>> logctx, ps, 1)) < 0)
>> +goto fail;
>> +}
>>  break;
>>  case H264_NAL_PPS:
>>  ret = ff_h264_decode_picture_parameter_set(>gb, logctx,
>> ps,
>> --
>> 2.17.1
>>
>>
> Ping
>

Ping :)
___
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".

Re: [FFmpeg-devel] [PATCH v2] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-20 Thread Jun Li
On Mon, Aug 19, 2019 at 7:24 PM Jun Li  wrote:

> Fix #6591
> The content has no rbsp_stop_one_bit for ending the SPS, that
> causes the decoding SPS failure, results decoding frame failure as well.
>
> The patch is just adding a retry with complete NALU, copied from the retry
> in decode_nal_unit()
> ---
>  libavcodec/h264_parse.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> index ac31f54e07..ea7a958dd9 100644
> --- a/libavcodec/h264_parse.c
> +++ b/libavcodec/h264_parse.c
> @@ -376,8 +376,15 @@ static int decode_extradata_ps(const uint8_t *data,
> int size, H264ParamSets *ps,
>  switch (nal->type) {
>  case H264_NAL_SPS:
>  ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps,
> 0);
> -if (ret < 0)
> -goto fail;
> +if (ret < 0) {
> +GetBitContext tmp_gb = nal->gb;
> +av_log(logctx, AV_LOG_DEBUG,
> +   "SPS decoding failure, trying again with the complete
> NAL\n");
> +init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size
> - 1);
> +if ((ret = ff_h264_decode_seq_parameter_set(_gb,
> logctx, ps, 0)) < 0 &&
> +(ret = ff_h264_decode_seq_parameter_set(_gb,
> logctx, ps, 1)) < 0)
> +goto fail;
> +}
>  break;
>  case H264_NAL_PPS:
>  ret = ff_h264_decode_picture_parameter_set(>gb, logctx,
> ps,
> --
> 2.17.1
>
>
Ping
___
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".

Re: [FFmpeg-devel] [PATCH v1] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-19 Thread Jun Li
On Mon, Aug 19, 2019 at 6:55 PM James Almer  wrote:

> On 8/19/2019 10:39 PM, Jun Li wrote:
> > On Mon, Aug 19, 2019 at 3:45 PM James Almer  wrote:
> >
> >> On 8/18/2019 10:41 PM, Jun Li wrote:
> >>> Fix #6591
> >>> The content has no rbsp_stop_one_bit for ending the SPS, that
> >>> causes the decoding SPS failure, results decoding frame failure as
> well.
> >>> The patch is just adding a retry with complete NALU.
> >>> ---
> >>>  libavcodec/h264_parse.c | 10 --
> >>>  1 file changed, 8 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> >>> index ac31f54e07..a2267a0610 100644
> >>> --- a/libavcodec/h264_parse.c
> >>> +++ b/libavcodec/h264_parse.c
> >>> @@ -376,8 +376,14 @@ static int decode_extradata_ps(const uint8_t
> *data,
> >> int size, H264ParamSets *ps,
> >>>  switch (nal->type) {
> >>>  case H264_NAL_SPS:
> >>>  ret = ff_h264_decode_seq_parameter_set(>gb, logctx,
> >> ps, 0);
> >>> -if (ret < 0)
> >>> -goto fail;
> >>> +if (ret < 0) {
> >>> +GetBitContext tmp_gb = nal->gb;
> >>> +av_log(logctx, AV_LOG_DEBUG,
> >>> +   "SPS decoding failure (maybe missing
> >> rbsp_stop_one_bit), trying again with the complete NAL\n");
> >>> +init_get_bits8(_gb, nal->raw_data + 1,
> >> nal->raw_size - 1);
> >>> +if ((ret = ff_h264_decode_seq_parameter_set(_gb,
> >> logctx, ps, 0)) < 0)
> >>> +goto fail;
> >>> +}
> >>>  break;
> >>>  case H264_NAL_PPS:
> >>>  ret = ff_h264_decode_picture_parameter_set(>gb,
> >> logctx, ps,
> >>
> >> Copy instead the code from decode_nal_units() in h264dec.c, which checks
> >> first with the complete NAL, and then calls
> >> ff_h264_decode_seq_parameter_set() with the ignore_truncation parameter
> >> set to 1 as a last resort.
> >>
> >
> > Hi James,
> > My first try was set the ignore_truncation to 1 but then found that
> > decode_nal_units is already handling this using a different approach.
> > So I just copied the code here, but without last try ignore_truncation=1.
> >
> > Are you suggesting modifying the commit message or comment identifying
> the
> > code is copied from decide_nal_units, or extract them to one function and
> > reuse two places ?
>
> My suggestion was to copy the decode_nal_units approach here including
> the last try ignore_truncation=1 call.


Thanks for the input, I updated version 2 accordingly.
https://patchwork.ffmpeg.org/patch/14604/


>
>
> > -Jun
> >
> >
> >> ___
> >> 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".
> > ___
> > 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".
> >
>
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v2] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-19 Thread Jun Li
Fix #6591
The content has no rbsp_stop_one_bit for ending the SPS, that
causes the decoding SPS failure, results decoding frame failure as well.

The patch is just adding a retry with complete NALU, copied from the retry in 
decode_nal_unit()
---
 libavcodec/h264_parse.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index ac31f54e07..ea7a958dd9 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -376,8 +376,15 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 switch (nal->type) {
 case H264_NAL_SPS:
 ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 0);
-if (ret < 0)
-goto fail;
+if (ret < 0) {
+GetBitContext tmp_gb = nal->gb;
+av_log(logctx, AV_LOG_DEBUG,
+   "SPS decoding failure, trying again with the complete 
NAL\n");
+init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
+if ((ret = ff_h264_decode_seq_parameter_set(_gb, logctx, 
ps, 0)) < 0 &&
+(ret = ff_h264_decode_seq_parameter_set(_gb, logctx, 
ps, 1)) < 0)
+goto fail;
+}
 break;
 case H264_NAL_PPS:
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v1] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-19 Thread Jun Li
On Mon, Aug 19, 2019 at 3:45 PM James Almer  wrote:

> On 8/18/2019 10:41 PM, Jun Li wrote:
> > Fix #6591
> > The content has no rbsp_stop_one_bit for ending the SPS, that
> > causes the decoding SPS failure, results decoding frame failure as well.
> > The patch is just adding a retry with complete NALU.
> > ---
> >  libavcodec/h264_parse.c | 10 --
> >  1 file changed, 8 insertions(+), 2 deletions(-)
> >
> > diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
> > index ac31f54e07..a2267a0610 100644
> > --- a/libavcodec/h264_parse.c
> > +++ b/libavcodec/h264_parse.c
> > @@ -376,8 +376,14 @@ static int decode_extradata_ps(const uint8_t *data,
> int size, H264ParamSets *ps,
> >  switch (nal->type) {
> >  case H264_NAL_SPS:
> >  ret = ff_h264_decode_seq_parameter_set(>gb, logctx,
> ps, 0);
> > -if (ret < 0)
> > -goto fail;
> > +if (ret < 0) {
> > +GetBitContext tmp_gb = nal->gb;
> > +av_log(logctx, AV_LOG_DEBUG,
> > +   "SPS decoding failure (maybe missing
> rbsp_stop_one_bit), trying again with the complete NAL\n");
> > +init_get_bits8(_gb, nal->raw_data + 1,
> nal->raw_size - 1);
> > +if ((ret = ff_h264_decode_seq_parameter_set(_gb,
> logctx, ps, 0)) < 0)
> > +goto fail;
> > +}
> >  break;
> >  case H264_NAL_PPS:
> >  ret = ff_h264_decode_picture_parameter_set(>gb,
> logctx, ps,
>
> Copy instead the code from decode_nal_units() in h264dec.c, which checks
> first with the complete NAL, and then calls
> ff_h264_decode_seq_parameter_set() with the ignore_truncation parameter
> set to 1 as a last resort.
>

Hi James,
My first try was set the ignore_truncation to 1 but then found that
decode_nal_units is already handling this using a different approach.
So I just copied the code here, but without last try ignore_truncation=1.

Are you suggesting modifying the commit message or comment identifying the
code is copied from decide_nal_units, or extract them to one function and
reuse two places ?

-Jun


> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v1] avcodec/h264_parse: retry decoding SPS with complete NAL

2019-08-18 Thread Jun Li
Fix #6591
The content has no rbsp_stop_one_bit for ending the SPS, that
causes the decoding SPS failure, results decoding frame failure as well.
The patch is just adding a retry with complete NALU.
---
 libavcodec/h264_parse.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index ac31f54e07..a2267a0610 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -376,8 +376,14 @@ static int decode_extradata_ps(const uint8_t *data, int 
size, H264ParamSets *ps,
 switch (nal->type) {
 case H264_NAL_SPS:
 ret = ff_h264_decode_seq_parameter_set(>gb, logctx, ps, 0);
-if (ret < 0)
-goto fail;
+if (ret < 0) {
+GetBitContext tmp_gb = nal->gb;
+av_log(logctx, AV_LOG_DEBUG,
+   "SPS decoding failure (maybe missing rbsp_stop_one_bit), 
trying again with the complete NAL\n");
+init_get_bits8(_gb, nal->raw_data + 1, nal->raw_size - 1);
+if ((ret = ff_h264_decode_seq_parameter_set(_gb, logctx, 
ps, 0)) < 0)
+goto fail;
+}
 break;
 case H264_NAL_PPS:
 ret = ff_h264_decode_picture_parameter_set(>gb, logctx, ps,
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avcodec/h264_mp4toannexb_bsf: force sps/pps writing before the first pict

2019-08-16 Thread Jun Li
Fix #6869, write sps/pps before the first picture nal, no matter what type
of picture it is.
---
 libavcodec/h264_mp4toannexb_bsf.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libavcodec/h264_mp4toannexb_bsf.c 
b/libavcodec/h264_mp4toannexb_bsf.c
index fb3f24ea40..e616c4c210 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -36,6 +36,7 @@ typedef struct H264BSFContext {
 uint8_t  idr_sps_seen;
 uint8_t  idr_pps_seen;
 int  extradata_parsed;
+int  first_pict;
 } H264BSFContext;
 
 static int alloc_and_copy(AVPacket *out,
@@ -160,6 +161,7 @@ static int h264_mp4toannexb_init(AVBSFContext *ctx)
 s->idr_sps_seen = 0;
 s->idr_pps_seen = 0;
 s->extradata_parsed = 1;
+s->first_pict   = 0;
 } else {
 av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
 return AVERROR_INVALIDDATA;
@@ -207,6 +209,9 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, 
AVPacket *out)
 buf += s->length_size;
 unit_type = *buf & 0x1f;
 
+if (!s->first_pict && (unit_type == H264_NAL_IDR_SLICE || unit_type == 
H264_NAL_SLICE))
+s->first_pict = 1;
+
 if (nal_size > buf_end - buf || nal_size < 0)
 goto fail;
 
@@ -236,15 +241,15 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, 
AVPacket *out)
 if (!s->new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80))
 s->new_idr = 1;
 
-/* prepend only to the first type 5 NAL unit of an IDR picture, if no 
sps/pps are already present */
-if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && !s->idr_sps_seen 
&& !s->idr_pps_seen) {
+/* prepend only to the first type 5 NAL unit of an IDR picture or the 
first pict NAL of the entire stream, if no sps/pps are already present */
+if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || s->first_pict == 
1) && !s->idr_sps_seen && !s->idr_pps_seen) {
 if ((ret=alloc_and_copy(out,
ctx->par_out->extradata, 
ctx->par_out->extradata_size,
buf, nal_size, 1)) < 0)
 goto fail;
 s->new_idr = 0;
 /* if only SPS has been seen, also insert PPS */
-} else if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && 
s->idr_sps_seen && !s->idr_pps_seen) {
+} else if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || 
s->first_pict == 1) && s->idr_sps_seen && !s->idr_pps_seen) {
 if (s->pps_offset == -1) {
 av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, 
nor in AVCC, stream may be unreadable\n");
 if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size, 0)) < 0)
@@ -263,6 +268,10 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, 
AVPacket *out)
 }
 }
 
+/* first picture has been found, set the flag to -1 */
+if (s->first_pict == 1)
+s->first_pict = -1;
+
 next_nal:
 buf+= nal_size;
 cumul_size += nal_size + s->length_size;
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v1] avcodec/h264_mp4toannexb_bsf: force sps/pps writing before the first pict

2019-08-16 Thread Jun Li
Hi,
This patch is trying to fix #6869.
The ticket has a h264 stream NOT starting with IDR, and all frames are I
frames.
And the mp4toannexb filter insert SPS/PPS before IDR, so leads to the
result that the output has no SPS/PPS.

The fix is just simply insert SPS/PPS before first picture, no matter what
type it is. Thanks.

Best Regards
-Jun
From 052674e9d4e2e6cf29141858b6cdc707fb75ecb1 Mon Sep 17 00:00:00 2001
From: Jun Li 
Date: Fri, 16 Aug 2019 15:08:23 -0700
Subject: [PATCH v1] avcodec/h264_mp4toannexb_bsf: force sps/pps writing before
 the first pict

Fix #6869, write sps/pps before the first picture nal, no matter what type
of picture it is.
---
 libavcodec/h264_mp4toannexb_bsf.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c
index fb3f24ea40..e616c4c210 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -36,6 +36,7 @@ typedef struct H264BSFContext {
 uint8_t  idr_sps_seen;
 uint8_t  idr_pps_seen;
 int  extradata_parsed;
+int  first_pict;
 } H264BSFContext;
 
 static int alloc_and_copy(AVPacket *out,
@@ -160,6 +161,7 @@ static int h264_mp4toannexb_init(AVBSFContext *ctx)
 s->idr_sps_seen = 0;
 s->idr_pps_seen = 0;
 s->extradata_parsed = 1;
+s->first_pict   = 0;
 } else {
 av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
 return AVERROR_INVALIDDATA;
@@ -207,6 +209,9 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 buf += s->length_size;
 unit_type = *buf & 0x1f;
 
+if (!s->first_pict && (unit_type == H264_NAL_IDR_SLICE || unit_type == H264_NAL_SLICE))
+s->first_pict = 1;
+
 if (nal_size > buf_end - buf || nal_size < 0)
 goto fail;
 
@@ -236,15 +241,15 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 if (!s->new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80))
 s->new_idr = 1;
 
-/* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
-if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && !s->idr_sps_seen && !s->idr_pps_seen) {
+/* prepend only to the first type 5 NAL unit of an IDR picture or the first pict NAL of the entire stream, if no sps/pps are already present */
+if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || s->first_pict == 1) && !s->idr_sps_seen && !s->idr_pps_seen) {
 if ((ret=alloc_and_copy(out,
ctx->par_out->extradata, ctx->par_out->extradata_size,
buf, nal_size, 1)) < 0)
 goto fail;
 s->new_idr = 0;
 /* if only SPS has been seen, also insert PPS */
-} else if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && s->idr_sps_seen && !s->idr_pps_seen) {
+} else if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || s->first_pict == 1) && s->idr_sps_seen && !s->idr_pps_seen) {
 if (s->pps_offset == -1) {
 av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
 if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size, 0)) < 0)
@@ -263,6 +268,10 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 }
 }
 
+/* first picture has been found, set the flag to -1 */
+if (s->first_pict == 1)
+s->first_pict = -1;
+
 next_nal:
 buf+= nal_size;
 cumul_size += nal_size + s->length_size;
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH v1] lavf/mov: Fix timestamp rescale on sidx atom

2019-08-14 Thread Jun Li
On Thu, Jun 20, 2019 at 2:02 AM Jun Li  wrote:

>
>
> On Tue, May 21, 2019 at 1:05 AM Jun Li  wrote:
>
>>
>>
>> On Thu, May 16, 2019 at 1:00 AM Jun Li  wrote:
>>
>>>
>>>
>>> On Sun, May 12, 2019 at 7:44 PM Jun Li  wrote:
>>>
>>>>
>>>>
>>>> On Fri, May 10, 2019 at 7:25 PM Jun Li  wrote:
>>>>
>>>>>
>>>>> On Thu, May 9, 2019 at 2:08 AM Jun Li  wrote:
>>>>>
>>>>>> Fix #5090
>>>>>> Fix the timestamp rescale issue, from sidx timebase to
>>>>>> stream's timebase.
>>>>>> ---
>>>>>>  libavformat/mov.c | 2 +-
>>>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/libavformat/mov.c b/libavformat/mov.c
>>>>>> index 78f692872b..d058855e6c 100644
>>>>>> --- a/libavformat/mov.c
>>>>>> +++ b/libavformat/mov.c
>>>>>> @@ -5017,7 +5017,7 @@ static int mov_read_sidx(MOVContext *c,
>>>>>> AVIOContext *pb, MOVAtom atom)
>>>>>>  return AVERROR_PATCHWELCOME;
>>>>>>  }
>>>>>>  avio_rb32(pb); // sap_flags
>>>>>> -timestamp = av_rescale_q(pts, st->time_base, timescale);
>>>>>> +timestamp = av_rescale_q(pts, timescale, st->time_base);
>>>>>>
>>>>>>  index = update_frag_index(c, offset);
>>>>>>  frag_stream_info = get_frag_stream_info(>frag_index,
>>>>>> index, track_id);
>>>>>> --
>>>>>> 2.17.1
>>>>>>
>>>>>
>>>>> Ping
>>>>>
>>>>
>>>> This change is for fix the issue of calculating sidx_pts.
>>>> Sidx box has "earliest_presentation_time", used as pts of  the referent
>>>> track, sidx also has timescale field.
>>>> So the operation should convert from sidx's timescale to track's
>>>> timescale, this patch is for addressing this, as well as fixing #5090.
>>>>
>>>> Of course this is based on my understanding, so please correct me if I
>>>> am wrong. Thanks !
>>>>
>>>>
>>> Ping.
>>> I believe this is a bug and triggered whenever sidx box's timescale is
>>> different from track's timescale.
>>> Created this kind of content and verified that ffplay couldn't play
>>> while VLC plays well.
>>> Then I checked VLC's implementation:
>>>
>>> https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
>>>
>>> Hope someone could help to have a review ? Thanks ! :)
>>>
>>> Best Regards,
>>> -Jun
>>>
>>>
>>>> Best Regards,
>>>> Jun
>>>>
>>>
>> Ping x 3
>>
>
> Ping x 4.
> I believe this is an obvious bug and happened whenever sidx box's
> timescale is different from track's timescale.
> I created this kind of content and verified that ffplay couldn't play
> while VLC plays well.
> This is  VLC's implementation:
>
> https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
>

Ping x 5
___
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".

[FFmpeg-devel] [PATCH v11 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-29 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c|  5 +++--
 fftools/ffmpeg.h|  8 
 fftools/ffmpeg_filter.c | 40 +++-
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..bc0cece59d 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
ifilter->channel_layout != frame->channel_layout;
 break;
 case AVMEDIA_TYPE_VIDEO:
-need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+need_reinit |= ifilter->width   != frame->width ||
+   ifilter->height  != frame->height ||
+   ifilter->orientation != get_frame_orientation(frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7b6f802082..7324813ce3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -232,6 +232,12 @@ typedef struct OptionsContext {
 intnb_enc_time_bases;
 } OptionsContext;
 
+enum OrientationType {
+ORIENTATION_NONE,
+ORIENTATION_AUTO_FLIP,
+ORIENTATION_AUTO_TRANSPOSE
+};
+
 typedef struct InputFilter {
 AVFilterContext*filter;
 struct InputStream *ist;
@@ -245,6 +251,7 @@ typedef struct InputFilter {
 int format;
 
 int width, height;
+enum OrientationType orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+enum OrientationType get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..eebb624116 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,32 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+enum OrientationType get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+
+// exif defines orientation in range [1, 8]
+if (orientation > 8 || orientation < 1) {
+if (entry && entry->value) {
+av_log(NULL, AV_LOG_WARNING,
+"Invalid frame orientation: %s, skip it.\n", entry->value);
+}
+return ORIENTATION_NONE;
+} else if (orientation == 1) {
+return ORIENTATION_NONE;
+} else if (orientation <= 4) {
+return ORIENTATION_AUTO_FLIP;
+} else {
+return ORIENTATION_AUTO_TRANSPOSE;
+}
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +835,16 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation == ORIENTATION_AUTO_FLIP) { 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation == ORIENTATION_AUTO_TRANSPOSE) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1220,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-29 Thread Jun Li
On Sat, Jun 29, 2019 at 12:07 AM Steven Liu  wrote:

>
>
> > 在 2019年6月26日,19:32,Steven Liu  写道:
> >
> > Jun Li  于2019年6月25日周二 上午9:26写道:
> >>
> >> On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:
> >>
> >>>
> >>>
> >>> On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
> >>>
> >>>>
> >>>>
> >>>> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
> >>>>
> >>>>>
> >>>>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
> >>>>>
> >>>>>> Add exif orientation support and expose an option.
> >>>>>> ---
> >>>>>> libavfilter/hflip.h|   2 +
> >>>>>> libavfilter/transpose.h|  14 
> >>>>>> libavfilter/vf_hflip.c |  40 ++---
> >>>>>> libavfilter/vf_transpose.c | 168
> -
> >>>>>> 4 files changed, 192 insertions(+), 32 deletions(-)
> >>>>>>
> >>>>>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> >>>>>> index 204090dbb4..4e89bae3fc 100644
> >>>>>> --- a/libavfilter/hflip.h
> >>>>>> +++ b/libavfilter/hflip.h
> >>>>>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
> >>>>>>
> >>>>>> int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >>>>>> void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> >>>>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> >>>>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame
> *out,
> >>>>>> int job, int nb_jobs, int vlifp);
> >>>>>>
> >>>>>> #endif /* AVFILTER_HFLIP_H */
> >>>>>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> >>>>>> index aa262b9487..5da08bddc0 100644
> >>>>>> --- a/libavfilter/transpose.h
> >>>>>> +++ b/libavfilter/transpose.h
> >>>>>> @@ -34,4 +34,18 @@ enum TransposeDir {
> >>>>>> TRANSPOSE_VFLIP,
> >>>>>> };
> >>>>>>
> >>>>>> +enum OrientationType {
> >>>>>> +ORIENTATION_AUTO_TRANSPOSE = -2,
> >>>>>> +ORIENTATION_AUTO_FLIP = -1,
> >>>>>> +ORIENTATION_NONE = 0,
> >>>>>> +ORIENTATION_NORMAL,
> >>>>>> +ORIENTATION_HFLIP,
> >>>>>> +ORIENTATION_ROTATE180,
> >>>>>> +ORIENTATION_VFLIP,
> >>>>>> +ORIENTATION_HFLIP_ROTATE270CW,
> >>>>>> +ORIENTATION_ROTATE90CW,
> >>>>>> +ORIENTATION_HFLIP_ROTATE90CW,
> >>>>>> +ORIENTATION_ROTATE270CW
> >>>>>> +};
> >>>>>> +
> >>>>>> #endif
> >>>>>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> >>>>>> index b77afc77fc..d24ca5c2e7 100644
> >>>>>> --- a/libavfilter/vf_hflip.c
> >>>>>> +++ b/libavfilter/vf_hflip.c
> >>>>>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> >>>>>> uint8_t *ddst, int w)
> >>>>>> dst[j] = src[-j];
> >>>>>> }
> >>>>>>
> >>>>>> -static int config_props(AVFilterLink *inlink)
> >>>>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >>>>>> {
> >>>>>> -FlipContext *s = inlink->dst->priv;
> >>>>>> const AVPixFmtDescriptor *pix_desc =
> >>>>>> av_pix_fmt_desc_get(inlink->format);
> >>>>>> const int hsub = pix_desc->log2_chroma_w;
> >>>>>> const int vsub = pix_desc->log2_chroma_h;
> >>>>>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
> >>>>>> return ff_hflip_init(s, s->max_step, nb_planes);
> >>>>>> }
> >>>>>>
> >>>>>> +static int config_props(AVFilterLink *inlink)
> >>>>>> +{
> >>>>>> +FlipContext *s = inlink->dst->priv;
> >>>>>> +return ff_hflip_config_props(s, inlink);
> &

[FFmpeg-devel] [PATCH v11 1/2] lavf/vf_transpose: add exif orientation support

2019-06-29 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 +++
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 170 -
 4 files changed, 194 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..cbe6e53155 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];
+} 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-24 Thread Jun Li
On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:

>
>
> On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
>
>>
>>
>> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
>>
>>>
>>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>>>
>>>> Add exif orientation support and expose an option.
>>>> ---
>>>>  libavfilter/hflip.h|   2 +
>>>>  libavfilter/transpose.h|  14 
>>>>  libavfilter/vf_hflip.c |  40 ++---
>>>>  libavfilter/vf_transpose.c | 168 -
>>>>  4 files changed, 192 insertions(+), 32 deletions(-)
>>>>
>>>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>>>> index 204090dbb4..4e89bae3fc 100644
>>>> --- a/libavfilter/hflip.h
>>>> +++ b/libavfilter/hflip.h
>>>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>>>
>>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>>> int job, int nb_jobs, int vlifp);
>>>>
>>>>  #endif /* AVFILTER_HFLIP_H */
>>>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>>>> index aa262b9487..5da08bddc0 100644
>>>> --- a/libavfilter/transpose.h
>>>> +++ b/libavfilter/transpose.h
>>>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>>>  TRANSPOSE_VFLIP,
>>>>  };
>>>>
>>>> +enum OrientationType {
>>>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>>>> +ORIENTATION_AUTO_FLIP = -1,
>>>> +ORIENTATION_NONE = 0,
>>>> +ORIENTATION_NORMAL,
>>>> +ORIENTATION_HFLIP,
>>>> +ORIENTATION_ROTATE180,
>>>> +ORIENTATION_VFLIP,
>>>> +ORIENTATION_HFLIP_ROTATE270CW,
>>>> +ORIENTATION_ROTATE90CW,
>>>> +ORIENTATION_HFLIP_ROTATE90CW,
>>>> +ORIENTATION_ROTATE270CW
>>>> +};
>>>> +
>>>>  #endif
>>>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>>>> index b77afc77fc..d24ca5c2e7 100644
>>>> --- a/libavfilter/vf_hflip.c
>>>> +++ b/libavfilter/vf_hflip.c
>>>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>>>> uint8_t *ddst, int w)
>>>>  dst[j] = src[-j];
>>>>  }
>>>>
>>>> -static int config_props(AVFilterLink *inlink)
>>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>>>  {
>>>> -FlipContext *s = inlink->dst->priv;
>>>>  const AVPixFmtDescriptor *pix_desc =
>>>> av_pix_fmt_desc_get(inlink->format);
>>>>  const int hsub = pix_desc->log2_chroma_w;
>>>>  const int vsub = pix_desc->log2_chroma_h;
>>>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>>>  }
>>>>
>>>> +static int config_props(AVFilterLink *inlink)
>>>> +{
>>>> +FlipContext *s = inlink->dst->priv;
>>>> +return ff_hflip_config_props(s, inlink);
>>>> +}
>>>> +
>>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>>>  {
>>>>  int i;
>>>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>>>  AVFrame *in, *out;
>>>>  } ThreadData;
>>>>
>>>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>>>> nb_jobs)
>>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>>> int job, int nb_jobs, int vflip)
>>>>  {
>>>> -FlipContext *s = ctx->priv;
>>>> -ThreadData *td = arg;
>>>> -AVFrame *in = td->in;
>>>> -AVFrame *out = td->out;
>>>>  uint8_t *inrow, *outrow;
>>>> -int i, plane, step;
>>>> +int i, plane, step, outlinesize;
>>>>
>>>>  for (plane = 0; plane < 4 && in->data[plane] &&
>>>> in->linesize[plane]; plane++) {
>>>>  const int width  = s->planewidth[plane];
>>>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterCont

Re: [FFmpeg-devel] [PATCH v1] lavf/mov: Fix timestamp rescale on sidx atom

2019-06-20 Thread Jun Li
On Tue, May 21, 2019 at 1:05 AM Jun Li  wrote:

>
>
> On Thu, May 16, 2019 at 1:00 AM Jun Li  wrote:
>
>>
>>
>> On Sun, May 12, 2019 at 7:44 PM Jun Li  wrote:
>>
>>>
>>>
>>> On Fri, May 10, 2019 at 7:25 PM Jun Li  wrote:
>>>
>>>>
>>>> On Thu, May 9, 2019 at 2:08 AM Jun Li  wrote:
>>>>
>>>>> Fix #5090
>>>>> Fix the timestamp rescale issue, from sidx timebase to
>>>>> stream's timebase.
>>>>> ---
>>>>>  libavformat/mov.c | 2 +-
>>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/libavformat/mov.c b/libavformat/mov.c
>>>>> index 78f692872b..d058855e6c 100644
>>>>> --- a/libavformat/mov.c
>>>>> +++ b/libavformat/mov.c
>>>>> @@ -5017,7 +5017,7 @@ static int mov_read_sidx(MOVContext *c,
>>>>> AVIOContext *pb, MOVAtom atom)
>>>>>  return AVERROR_PATCHWELCOME;
>>>>>  }
>>>>>  avio_rb32(pb); // sap_flags
>>>>> -timestamp = av_rescale_q(pts, st->time_base, timescale);
>>>>> +timestamp = av_rescale_q(pts, timescale, st->time_base);
>>>>>
>>>>>  index = update_frag_index(c, offset);
>>>>>  frag_stream_info = get_frag_stream_info(>frag_index,
>>>>> index, track_id);
>>>>> --
>>>>> 2.17.1
>>>>>
>>>>
>>>> Ping
>>>>
>>>
>>> This change is for fix the issue of calculating sidx_pts.
>>> Sidx box has "earliest_presentation_time", used as pts of  the referent
>>> track, sidx also has timescale field.
>>> So the operation should convert from sidx's timescale to track's
>>> timescale, this patch is for addressing this, as well as fixing #5090.
>>>
>>> Of course this is based on my understanding, so please correct me if I
>>> am wrong. Thanks !
>>>
>>>
>> Ping.
>> I believe this is a bug and triggered whenever sidx box's timescale is
>> different from track's timescale.
>> Created this kind of content and verified that ffplay couldn't play while
>> VLC plays well.
>> Then I checked VLC's implementation:
>>
>> https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
>>
>> Hope someone could help to have a review ? Thanks ! :)
>>
>> Best Regards,
>> -Jun
>>
>>
>>> Best Regards,
>>> Jun
>>>
>>
> Ping x 3
>

Ping x 4.
I believe this is an obvious bug and happened whenever sidx box's timescale
is different from track's timescale.
I created this kind of content and verified that ffplay couldn't play while
VLC plays well.
This is  VLC's implementation:
https://github.com/videolan/vlc/blob/5609c1b41d6fbca6323103619c6139caf7bc9e6e/modules/demux/mp4/mp4.c#L4735
___
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".

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-17 Thread Jun Li
On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:

>
>
> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
>
>>
>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>>
>>> Add exif orientation support and expose an option.
>>> ---
>>>  libavfilter/hflip.h|   2 +
>>>  libavfilter/transpose.h|  14 
>>>  libavfilter/vf_hflip.c |  40 ++---
>>>  libavfilter/vf_transpose.c | 168 -
>>>  4 files changed, 192 insertions(+), 32 deletions(-)
>>>
>>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>>> index 204090dbb4..4e89bae3fc 100644
>>> --- a/libavfilter/hflip.h
>>> +++ b/libavfilter/hflip.h
>>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>>
>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>> int job, int nb_jobs, int vlifp);
>>>
>>>  #endif /* AVFILTER_HFLIP_H */
>>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>>> index aa262b9487..5da08bddc0 100644
>>> --- a/libavfilter/transpose.h
>>> +++ b/libavfilter/transpose.h
>>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>>  TRANSPOSE_VFLIP,
>>>  };
>>>
>>> +enum OrientationType {
>>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>>> +ORIENTATION_AUTO_FLIP = -1,
>>> +ORIENTATION_NONE = 0,
>>> +ORIENTATION_NORMAL,
>>> +ORIENTATION_HFLIP,
>>> +ORIENTATION_ROTATE180,
>>> +ORIENTATION_VFLIP,
>>> +ORIENTATION_HFLIP_ROTATE270CW,
>>> +ORIENTATION_ROTATE90CW,
>>> +ORIENTATION_HFLIP_ROTATE90CW,
>>> +ORIENTATION_ROTATE270CW
>>> +};
>>> +
>>>  #endif
>>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>>> index b77afc77fc..d24ca5c2e7 100644
>>> --- a/libavfilter/vf_hflip.c
>>> +++ b/libavfilter/vf_hflip.c
>>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>>> uint8_t *ddst, int w)
>>>  dst[j] = src[-j];
>>>  }
>>>
>>> -static int config_props(AVFilterLink *inlink)
>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>>  {
>>> -FlipContext *s = inlink->dst->priv;
>>>  const AVPixFmtDescriptor *pix_desc =
>>> av_pix_fmt_desc_get(inlink->format);
>>>  const int hsub = pix_desc->log2_chroma_w;
>>>  const int vsub = pix_desc->log2_chroma_h;
>>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>>  }
>>>
>>> +static int config_props(AVFilterLink *inlink)
>>> +{
>>> +FlipContext *s = inlink->dst->priv;
>>> +return ff_hflip_config_props(s, inlink);
>>> +}
>>> +
>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>>  {
>>>  int i;
>>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>>  AVFrame *in, *out;
>>>  } ThreadData;
>>>
>>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>>> nb_jobs)
>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>> int job, int nb_jobs, int vflip)
>>>  {
>>> -FlipContext *s = ctx->priv;
>>> -ThreadData *td = arg;
>>> -AVFrame *in = td->in;
>>> -AVFrame *out = td->out;
>>>  uint8_t *inrow, *outrow;
>>> -int i, plane, step;
>>> +int i, plane, step, outlinesize;
>>>
>>>  for (plane = 0; plane < 4 && in->data[plane] &&
>>> in->linesize[plane]; plane++) {
>>>  const int width  = s->planewidth[plane];
>>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
>>> *arg, int job, int nb_jobs)
>>>
>>>  step = s->max_step[plane];
>>>
>>> -outrow = out->data[plane] + start * out->linesize[plane];
>>> -inrow  = in ->data[plane] + start * in->linesize[plane] +
>>> (width - 1) * step;
>>> +if (vflip) {
>>> +outrow = out->data[plane] + (height - start - 1)*
>>> out->

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-15 Thread Jun Li
On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:

>
> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>
>> Add exif orientation support and expose an option.
>> ---
>>  libavfilter/hflip.h|   2 +
>>  libavfilter/transpose.h|  14 
>>  libavfilter/vf_hflip.c |  40 ++---
>>  libavfilter/vf_transpose.c | 168 -
>>  4 files changed, 192 insertions(+), 32 deletions(-)
>>
>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>> index 204090dbb4..4e89bae3fc 100644
>> --- a/libavfilter/hflip.h
>> +++ b/libavfilter/hflip.h
>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vlifp);
>>
>>  #endif /* AVFILTER_HFLIP_H */
>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>> index aa262b9487..5da08bddc0 100644
>> --- a/libavfilter/transpose.h
>> +++ b/libavfilter/transpose.h
>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>  TRANSPOSE_VFLIP,
>>  };
>>
>> +enum OrientationType {
>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>> +ORIENTATION_AUTO_FLIP = -1,
>> +ORIENTATION_NONE = 0,
>> +ORIENTATION_NORMAL,
>> +ORIENTATION_HFLIP,
>> +ORIENTATION_ROTATE180,
>> +ORIENTATION_VFLIP,
>> +ORIENTATION_HFLIP_ROTATE270CW,
>> +ORIENTATION_ROTATE90CW,
>> +ORIENTATION_HFLIP_ROTATE90CW,
>> +ORIENTATION_ROTATE270CW
>> +};
>> +
>>  #endif
>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>> index b77afc77fc..d24ca5c2e7 100644
>> --- a/libavfilter/vf_hflip.c
>> +++ b/libavfilter/vf_hflip.c
>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>> uint8_t *ddst, int w)
>>  dst[j] = src[-j];
>>  }
>>
>> -static int config_props(AVFilterLink *inlink)
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>  {
>> -FlipContext *s = inlink->dst->priv;
>>  const AVPixFmtDescriptor *pix_desc =
>> av_pix_fmt_desc_get(inlink->format);
>>  const int hsub = pix_desc->log2_chroma_w;
>>  const int vsub = pix_desc->log2_chroma_h;
>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>  }
>>
>> +static int config_props(AVFilterLink *inlink)
>> +{
>> +FlipContext *s = inlink->dst->priv;
>> +return ff_hflip_config_props(s, inlink);
>> +}
>> +
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>  {
>>  int i;
>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>  AVFrame *in, *out;
>>  } ThreadData;
>>
>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>> nb_jobs)
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vflip)
>>  {
>> -FlipContext *s = ctx->priv;
>> -ThreadData *td = arg;
>> -AVFrame *in = td->in;
>> -AVFrame *out = td->out;
>>  uint8_t *inrow, *outrow;
>> -int i, plane, step;
>> +int i, plane, step, outlinesize;
>>
>>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
>> plane++) {
>>  const int width  = s->planewidth[plane];
>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
>> *arg, int job, int nb_jobs)
>>
>>  step = s->max_step[plane];
>>
>> -outrow = out->data[plane] + start * out->linesize[plane];
>> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
>> - 1) * step;
>> +if (vflip) {
>> +outrow = out->data[plane] + (height - start - 1)*
>> out->linesize[plane];
>> +outlinesize = -out->linesize[plane];
>> +} else {
>> +outrow = out->data[plane] + start * out->linesize[plane];
>> +outlinesize = out->linesize[plane];
>> +}
>> +
>> +inrow = in->data[plane] + start * in->linesize[plane] +  (width
>> - 1) * step;
>> +
>>  for (i = start; i < end; i++) {
>>  s->flip_line[plane

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-11 Thread Jun Li
On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:

> Add exif orientation support and expose an option.
> ---
>  libavfilter/hflip.h|   2 +
>  libavfilter/transpose.h|  14 
>  libavfilter/vf_hflip.c |  40 ++---
>  libavfilter/vf_transpose.c | 168 -
>  4 files changed, 192 insertions(+), 32 deletions(-)
>
> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> index 204090dbb4..4e89bae3fc 100644
> --- a/libavfilter/hflip.h
> +++ b/libavfilter/hflip.h
> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vlifp);
>
>  #endif /* AVFILTER_HFLIP_H */
> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> index aa262b9487..5da08bddc0 100644
> --- a/libavfilter/transpose.h
> +++ b/libavfilter/transpose.h
> @@ -34,4 +34,18 @@ enum TransposeDir {
>  TRANSPOSE_VFLIP,
>  };
>
> +enum OrientationType {
> +ORIENTATION_AUTO_TRANSPOSE = -2,
> +ORIENTATION_AUTO_FLIP = -1,
> +ORIENTATION_NONE = 0,
> +ORIENTATION_NORMAL,
> +ORIENTATION_HFLIP,
> +ORIENTATION_ROTATE180,
> +ORIENTATION_VFLIP,
> +ORIENTATION_HFLIP_ROTATE270CW,
> +ORIENTATION_ROTATE90CW,
> +ORIENTATION_HFLIP_ROTATE90CW,
> +ORIENTATION_ROTATE270CW
> +};
> +
>  #endif
> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> index b77afc77fc..d24ca5c2e7 100644
> --- a/libavfilter/vf_hflip.c
> +++ b/libavfilter/vf_hflip.c
> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t
> *ddst, int w)
>  dst[j] = src[-j];
>  }
>
> -static int config_props(AVFilterLink *inlink)
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>  {
> -FlipContext *s = inlink->dst->priv;
>  const AVPixFmtDescriptor *pix_desc =
> av_pix_fmt_desc_get(inlink->format);
>  const int hsub = pix_desc->log2_chroma_w;
>  const int vsub = pix_desc->log2_chroma_h;
> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>  return ff_hflip_init(s, s->max_step, nb_planes);
>  }
>
> +static int config_props(AVFilterLink *inlink)
> +{
> +FlipContext *s = inlink->dst->priv;
> +return ff_hflip_config_props(s, inlink);
> +}
> +
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>  {
>  int i;
> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>  AVFrame *in, *out;
>  } ThreadData;
>
> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vflip)
>  {
> -FlipContext *s = ctx->priv;
> -ThreadData *td = arg;
> -AVFrame *in = td->in;
> -AVFrame *out = td->out;
>  uint8_t *inrow, *outrow;
> -int i, plane, step;
> +int i, plane, step, outlinesize;
>
>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> plane++) {
>  const int width  = s->planewidth[plane];
> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
> *arg, int job, int nb_jobs)
>
>  step = s->max_step[plane];
>
> -outrow = out->data[plane] + start * out->linesize[plane];
> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
> - 1) * step;
> +if (vflip) {
> +outrow = out->data[plane] + (height - start - 1)*
> out->linesize[plane];
> +outlinesize = -out->linesize[plane];
> +} else {
> +outrow = out->data[plane] + start * out->linesize[plane];
> +outlinesize = out->linesize[plane];
> +}
> +
> +inrow = in->data[plane] + start * in->linesize[plane] +  (width -
> 1) * step;
> +
>  for (i = start; i < end; i++) {
>  s->flip_line[plane](inrow, outrow, width);
>
>  inrow  += in ->linesize[plane];
> -outrow += out->linesize[plane];
> +outrow += outlinesize;
>  }
>  }
>
>  return 0;
>  }
>
> +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +{
> +FlipContext *s = ctx->priv;
> +ThreadData *td = arg;
> +AVFrame *in = td->in;
> +AVFrame *out = td->out;
> +return ff_hflip_filter_sl

[FFmpeg-devel] [PATCH v10 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-09 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c|  5 +++--
 fftools/ffmpeg.h|  8 
 fftools/ffmpeg_filter.c | 40 +++-
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..bc0cece59d 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
ifilter->channel_layout != frame->channel_layout;
 break;
 case AVMEDIA_TYPE_VIDEO:
-need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+need_reinit |= ifilter->width   != frame->width ||
+   ifilter->height  != frame->height ||
+   ifilter->orientation != get_frame_orientation(frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7b6f802082..7324813ce3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -232,6 +232,12 @@ typedef struct OptionsContext {
 intnb_enc_time_bases;
 } OptionsContext;
 
+enum OrientationType {
+ORIENTATION_NONE,
+ORIENTATION_AUTO_FLIP,
+ORIENTATION_AUTO_TRANSPOSE
+};
+
 typedef struct InputFilter {
 AVFilterContext*filter;
 struct InputStream *ist;
@@ -245,6 +251,7 @@ typedef struct InputFilter {
 int format;
 
 int width, height;
+enum OrientationType orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+enum OrientationType get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..eebb624116 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,32 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+enum OrientationType get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+
+// exif defines orientation in range [1, 8]
+if (orientation > 8 || orientation < 1) {
+if (entry && entry->value) {
+av_log(NULL, AV_LOG_WARNING,
+"Invalid frame orientation: %s, skip it.\n", entry->value);
+}
+return ORIENTATION_NONE;
+} else if (orientation == 1) {
+return ORIENTATION_NONE;
+} else if (orientation <= 4) {
+return ORIENTATION_AUTO_FLIP;
+} else {
+return ORIENTATION_AUTO_TRANSPOSE;
+}
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +835,16 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation == ORIENTATION_AUTO_FLIP) { 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation == ORIENTATION_AUTO_TRANSPOSE) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1220,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org

Re: [FFmpeg-devel] [PATCH v9 1/2] lavf/vf_transpose: add exif orientation support

2019-06-09 Thread Jun Li
On Sun, Jun 9, 2019 at 1:52 AM Paul B Mahol  wrote:

> On 6/9/19, Jun Li  wrote:
> > On Sun, Jun 9, 2019 at 12:49 AM Paul B Mahol  wrote:
> >
> >> On 6/9/19, Jun Li  wrote:
> >> > Add exif orientation support and expose an option.
> >> > ---
> >> >  libavfilter/hflip.h|   2 +
> >> >  libavfilter/transpose.h|  14 
> >> >  libavfilter/vf_hflip.c |  40 ++---
> >> >  libavfilter/vf_transpose.c | 168
> -
> >> >  4 files changed, 192 insertions(+), 32 deletions(-)
> >> >
> >> > diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> >> > index 204090dbb4..4e89bae3fc 100644
> >> > --- a/libavfilter/hflip.h
> >> > +++ b/libavfilter/hflip.h
> >> > @@ -35,5 +35,7 @@ typedef struct FlipContext {
> >> >
> >> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >> >  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> >> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> >> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
> >> > int
> >> > job, int nb_jobs, int vlifp);
> >> >
> >> >  #endif /* AVFILTER_HFLIP_H */
> >> > diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> >> > index aa262b9487..5da08bddc0 100644
> >> > --- a/libavfilter/transpose.h
> >> > +++ b/libavfilter/transpose.h
> >> > @@ -34,4 +34,18 @@ enum TransposeDir {
> >> >  TRANSPOSE_VFLIP,
> >> >  };
> >> >
> >> > +enum OrientationType {
> >> > +ORIENTATION_AUTO_TRANSPOSE = -2,
> >> > +ORIENTATION_AUTO_FLIP = -1,
> >> > +ORIENTATION_NONE = 0,
> >> > +ORIENTATION_NORMAL,
> >> > +ORIENTATION_HFLIP,
> >> > +ORIENTATION_ROTATE180,
> >> > +ORIENTATION_VFLIP,
> >> > +ORIENTATION_HFLIP_ROTATE270CW,
> >> > +ORIENTATION_ROTATE90CW,
> >> > +ORIENTATION_HFLIP_ROTATE90CW,
> >> > +ORIENTATION_ROTATE270CW
> >> > +};
> >> > +
> >> >  #endif
> >> > diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> >> > index b77afc77fc..d24ca5c2e7 100644
> >> > --- a/libavfilter/vf_hflip.c
> >> > +++ b/libavfilter/vf_hflip.c
> >> > @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> >> uint8_t
> >> > *ddst, int w)
> >> >  dst[j] = src[-j];
> >> >  }
> >> >
> >> > -static int config_props(AVFilterLink *inlink)
> >> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >> >  {
> >> > -FlipContext *s = inlink->dst->priv;
> >> >  const AVPixFmtDescriptor *pix_desc =
> >> > av_pix_fmt_desc_get(inlink->format);
> >> >  const int hsub = pix_desc->log2_chroma_w;
> >> >  const int vsub = pix_desc->log2_chroma_h;
> >> > @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
> >> >  return ff_hflip_init(s, s->max_step, nb_planes);
> >> >  }
> >> >
> >> > +static int config_props(AVFilterLink *inlink)
> >> > +{
> >> > +FlipContext *s = inlink->dst->priv;
> >> > +return ff_hflip_config_props(s, inlink);
> >> > +}
> >> > +
> >> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
> >> >  {
> >> >  int i;
> >> > @@ -170,14 +175,10 @@ typedef struct ThreadData {
> >> >  AVFrame *in, *out;
> >> >  } ThreadData;
> >> >
> >> > -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> >> > nb_jobs)
> >> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
> >> > int
> >> > job, int nb_jobs, int vflip)
> >> >  {
> >> > -FlipContext *s = ctx->priv;
> >> > -ThreadData *td = arg;
> >> > -AVFrame *in = td->in;
> >> > -AVFrame *out = td->out;
> >> >  uint8_t *inrow, *outrow;
> >> > -int i, plane, step;
> >> > +int i, plane, step, outlinesize;
> >> >
> >> >  for (plane = 0; plane < 4 && in->data[plane

[FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-09 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 168 -
 4 files changed, 192 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..05dc04a89f 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];

Re: [FFmpeg-devel] [PATCH v9 1/2] lavf/vf_transpose: add exif orientation support

2019-06-09 Thread Jun Li
On Sun, Jun 9, 2019 at 12:49 AM Paul B Mahol  wrote:

> On 6/9/19, Jun Li  wrote:
> > Add exif orientation support and expose an option.
> > ---
> >  libavfilter/hflip.h|   2 +
> >  libavfilter/transpose.h|  14 
> >  libavfilter/vf_hflip.c |  40 ++---
> >  libavfilter/vf_transpose.c | 168 -
> >  4 files changed, 192 insertions(+), 32 deletions(-)
> >
> > diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> > index 204090dbb4..4e89bae3fc 100644
> > --- a/libavfilter/hflip.h
> > +++ b/libavfilter/hflip.h
> > @@ -35,5 +35,7 @@ typedef struct FlipContext {
> >
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vlifp);
> >
> >  #endif /* AVFILTER_HFLIP_H */
> > diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> > index aa262b9487..5da08bddc0 100644
> > --- a/libavfilter/transpose.h
> > +++ b/libavfilter/transpose.h
> > @@ -34,4 +34,18 @@ enum TransposeDir {
> >  TRANSPOSE_VFLIP,
> >  };
> >
> > +enum OrientationType {
> > +ORIENTATION_AUTO_TRANSPOSE = -2,
> > +ORIENTATION_AUTO_FLIP = -1,
> > +ORIENTATION_NONE = 0,
> > +ORIENTATION_NORMAL,
> > +ORIENTATION_HFLIP,
> > +ORIENTATION_ROTATE180,
> > +ORIENTATION_VFLIP,
> > +ORIENTATION_HFLIP_ROTATE270CW,
> > +ORIENTATION_ROTATE90CW,
> > +ORIENTATION_HFLIP_ROTATE90CW,
> > +ORIENTATION_ROTATE270CW
> > +};
> > +
> >  #endif
> > diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> > index b77afc77fc..d24ca5c2e7 100644
> > --- a/libavfilter/vf_hflip.c
> > +++ b/libavfilter/vf_hflip.c
> > @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> uint8_t
> > *ddst, int w)
> >  dst[j] = src[-j];
> >  }
> >
> > -static int config_props(AVFilterLink *inlink)
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >  {
> > -FlipContext *s = inlink->dst->priv;
> >  const AVPixFmtDescriptor *pix_desc =
> > av_pix_fmt_desc_get(inlink->format);
> >  const int hsub = pix_desc->log2_chroma_w;
> >  const int vsub = pix_desc->log2_chroma_h;
> > @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
> >  return ff_hflip_init(s, s->max_step, nb_planes);
> >  }
> >
> > +static int config_props(AVFilterLink *inlink)
> > +{
> > +FlipContext *s = inlink->dst->priv;
> > +return ff_hflip_config_props(s, inlink);
> > +}
> > +
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
> >  {
> >  int i;
> > @@ -170,14 +175,10 @@ typedef struct ThreadData {
> >  AVFrame *in, *out;
> >  } ThreadData;
> >
> > -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> > nb_jobs)
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vflip)
> >  {
> > -FlipContext *s = ctx->priv;
> > -ThreadData *td = arg;
> > -AVFrame *in = td->in;
> > -AVFrame *out = td->out;
> >  uint8_t *inrow, *outrow;
> > -int i, plane, step;
> > +int i, plane, step, outlinesize;
> >
> >  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> > plane++) {
> >  const int width  = s->planewidth[plane];
> > @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
> > *arg, int job, int nb_jobs)
> >
> >  step = s->max_step[plane];
> >
> > -outrow = out->data[plane] + start * out->linesize[plane];
> > -inrow  = in ->data[plane] + start * in->linesize[plane] +
> (width -
> > 1) * step;
> > +if (vflip) {
> > +outrow = out->data[plane] + (height - start - 1)*
> > out->linesize[plane];
> > +outlinesize = -out->linesize[plane];
> > +} else {
> > +outrow = out->data[plane] + start * out->linesize[plane];
> > +outlinesize = out->linesize[plane];
> > +}
> > +
> > +inrow = in->data[plane] + start * in->linesize[plane] +  (width
> -
> > 1) *

Re: [FFmpeg-devel] [PATCH v8 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-08 Thread Jun Li
On Sat, Jun 8, 2019 at 2:25 AM Nicolas George  wrote:

> Jun Li (12019-06-07):
> > I think a complete validation should be creating a function like
> "atodigit"
> > , string to digit, instead of using atoi,
>
> The problem of validation is a common one, and as such it already has a
> solution.
>
> APPLICATION USAGE
>
> The atoi() function is subsumed by strtol() but is retained because it
> is
> used extensively in existing code. If the number is not known to be in
> range, strtol() should be used because atoi() is not required to
> perform
> any error checking.


Thanks Nicolas and Michael, it is very helpful.
After reread the exif orientation doc, I realized that the correct value
should be in range [1,8], that is, 0 is considered as invalid.

So the new version is still using "atoi", since it return 0 for either
input  "0" or "This is a test", and 0 considered as invalid in any case.
https://patchwork.ffmpeg.org/patch/13471/
I am not against using strtol, which is a superset of atoi. Let me know if
there is a code preference in ffmpeg since I see strtol is more widely used.

Best Regards,
Jun


>
>
Regards,
>
> --
>   Nicolas George
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v9 1/2] lavf/vf_transpose: add exif orientation support

2019-06-08 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 168 -
 4 files changed, 192 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..7a122ba8a9 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];

[FFmpeg-devel] [PATCH v9 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-08 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c|  5 +++--
 fftools/ffmpeg.h|  8 
 fftools/ffmpeg_filter.c | 40 +++-
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..bc0cece59d 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
ifilter->channel_layout != frame->channel_layout;
 break;
 case AVMEDIA_TYPE_VIDEO:
-need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+need_reinit |= ifilter->width   != frame->width ||
+   ifilter->height  != frame->height ||
+   ifilter->orientation != get_frame_orientation(frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7b6f802082..7324813ce3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -232,6 +232,12 @@ typedef struct OptionsContext {
 intnb_enc_time_bases;
 } OptionsContext;
 
+enum OrientationType {
+ORIENTATION_NONE,
+ORIENTATION_AUTO_FLIP,
+ORIENTATION_AUTO_TRANSPOSE
+};
+
 typedef struct InputFilter {
 AVFilterContext*filter;
 struct InputStream *ist;
@@ -245,6 +251,7 @@ typedef struct InputFilter {
 int format;
 
 int width, height;
+enum OrientationType orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+enum OrientationType get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..8fe17c8013 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,32 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+enum OrientationType get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+
+//exif defines orientation in range [1, 8]
+if (orientation > 8 || orientation < 1) {
+if (entry && entry->value) {
+av_log(NULL, AV_LOG_WARNING,
+"Invalid frame orientation: %s, skip it.\n", entry->value);
+}
+return ORIENTATION_NONE;
+} else if (orientation == 1) {
+return ORIENTATION_NONE;
+} else if (orientation <= 4) {
+return ORIENTATION_AUTO_FLIP;
+} else {
+return ORIENTATION_AUTO_TRANSPOSE;
+}
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +835,16 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation == ORIENTATION_AUTO_FLIP) { 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation == ORIENTATION_AUTO_TRANSPOSE) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1220,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org

Re: [FFmpeg-devel] [PATCH v8 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-07 Thread Jun Li
On Fri, Jun 7, 2019 at 11:54 AM Michael Niedermayer 
wrote:

> On Thu, Jun 06, 2019 at 08:28:15PM -0700, Jun Li wrote:
> > Fix #6945
> > Rotate or/and flip frame according to frame's metadata orientation
> > ---
> >  fftools/ffmpeg.c|  5 +++--
> >  fftools/ffmpeg.h|  8 
> >  fftools/ffmpeg_filter.c | 36 +++-
> >  3 files changed, 42 insertions(+), 7 deletions(-)
> >
> > diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> > index 01f04103cf..bc0cece59d 100644
> > --- a/fftools/ffmpeg.c
> > +++ b/fftools/ffmpeg.c
> > @@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter
> *ifilter, AVFrame *frame)
> > ifilter->channel_layout != frame->channel_layout;
> >  break;
> >  case AVMEDIA_TYPE_VIDEO:
> > -need_reinit |= ifilter->width  != frame->width ||
> > -   ifilter->height != frame->height;
> > +need_reinit |= ifilter->width   != frame->width ||
> > +   ifilter->height  != frame->height ||
> > +   ifilter->orientation !=
> get_frame_orientation(frame);
> >  break;
> >  }
> >
> > diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> > index 7b6f802082..7324813ce3 100644
> > --- a/fftools/ffmpeg.h
> > +++ b/fftools/ffmpeg.h
> > @@ -232,6 +232,12 @@ typedef struct OptionsContext {
> >  intnb_enc_time_bases;
> >  } OptionsContext;
> >
> > +enum OrientationType {
> > +ORIENTATION_NONE,
> > +ORIENTATION_AUTO_FLIP,
> > +ORIENTATION_AUTO_TRANSPOSE
> > +};
> > +
> >  typedef struct InputFilter {
> >  AVFilterContext*filter;
> >  struct InputStream *ist;
> > @@ -245,6 +251,7 @@ typedef struct InputFilter {
> >  int format;
> >
> >  int width, height;
> > +enum OrientationType orientation;
> >  AVRational sample_aspect_ratio;
> >
> >  int sample_rate;
> > @@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
> >  void sub2video_update(InputStream *ist, AVSubtitle *sub);
> >
> >  int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame
> *frame);
> > +enum OrientationType get_frame_orientation(const AVFrame* frame);
> >
> >  int ffmpeg_parse_options(int argc, char **argv);
> >
> > diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
> > index 72838de1e2..790751f47f 100644
> > --- a/fftools/ffmpeg_filter.c
> > +++ b/fftools/ffmpeg_filter.c
> > @@ -743,6 +743,28 @@ static int sub2video_prepare(InputStream *ist,
> InputFilter *ifilter)
> >  return 0;
> >  }
> >
> > +enum OrientationType get_frame_orientation(const AVFrame *frame)
> > +{
> > +AVDictionaryEntry *entry = NULL;
> > +int orientation = 0;
> > +
> > +// read exif orientation data
> > +entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
> > +if (entry && entry->value)
> > +orientation = atoi(entry->value);
>
> what if entry->value equals "The cow says moo" ?
> This is of course a silly example but the following code would not detect
> it as an error
> as atoi would return 0
> or is there something that prevents this case ?
>

Hi Michael,
The question is like how to validate a integer number, or maybe partially
validate a number.
In this case, I can do a simple check before call atoi,  but need to cover
the following case:
  "  +2"   // start with space,  with or without sign

Something might be like:
  int i = 0;
  char *pos = NULL;
  if (entry && entry->value) {
  while(entry->value[i] && entry->value[i] == ' ') // eat white-space
   i++;
  if (entry->value[i]) {
  if (entry->value[i] == '+')   // eat '+'
 i++;

  if (entry->value[i] && entry->value[i] >= '0' && entry->value <=
'8')
  pos = entry->value + i;
  }
  }

  if (pos) {
 orientation = atoi(pos);
  }

But the validation is *NOT COMPLETE* although it covers the case your
mentioned.
Like "3.4" is valid and converted to orientation 3, even "3 4" is a
valid orientation.
I think a complete validation should be creating a function like "atodigit"
, string to digit, instead of using atoi,

If you prefer a complete solution, I can send a new version to validate the
value.
What do you think ?

Best Regards,
Jun


> > +
&g

Re: [FFmpeg-devel] [PATCH v7 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-06 Thread Jun Li
On Thu, Jun 6, 2019 at 4:02 AM Michael Niedermayer 
wrote:

> On Tue, Jun 04, 2019 at 06:12:28PM -0700, Jun Li wrote:
> > Fix #6945
> > Rotate or/and flip frame according to frame's metadata orientation
> [..]
>
> > +
> > +return filterst != framest;
> > +}
> > +
> >  static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
> >  {
> >  FilterGraph *fg = ifilter->graph;
> > @@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter
> *ifilter, AVFrame *frame)
> >  break;
> >  case AVMEDIA_TYPE_VIDEO:
> >  need_reinit |= ifilter->width  != frame->width ||
> > -   ifilter->height != frame->height;
> > +   ifilter->height != frame->height ||
> > +   orientation_need_update(ifilter, frame);
> >  break;
> >  }
> >
> > diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> > index 7b6f802082..64278b6ab1 100644
> > --- a/fftools/ffmpeg.h
> > +++ b/fftools/ffmpeg.h
> > @@ -244,7 +244,7 @@ typedef struct InputFilter {
> >  // parameters configured for this input
> >  int format;
> >
> > -int width, height;
> > +int width, height, orientation;
>
> orientation should probably be an enum not an int
>

Agree, thanks for the input. I updated the version
https://patchwork.ffmpeg.org/patch/13446/

Best Regards,
Jun


> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> If you think the mosad wants you dead since a long time then you are either
> wrong or dead since a long time.
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v8 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-06 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c|  5 +++--
 fftools/ffmpeg.h|  8 
 fftools/ffmpeg_filter.c | 36 +++-
 3 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..bc0cece59d 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
ifilter->channel_layout != frame->channel_layout;
 break;
 case AVMEDIA_TYPE_VIDEO:
-need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+need_reinit |= ifilter->width   != frame->width ||
+   ifilter->height  != frame->height ||
+   ifilter->orientation != get_frame_orientation(frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7b6f802082..7324813ce3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -232,6 +232,12 @@ typedef struct OptionsContext {
 intnb_enc_time_bases;
 } OptionsContext;
 
+enum OrientationType {
+ORIENTATION_NONE,
+ORIENTATION_AUTO_FLIP,
+ORIENTATION_AUTO_TRANSPOSE
+};
+
 typedef struct InputFilter {
 AVFilterContext*filter;
 struct InputStream *ist;
@@ -245,6 +251,7 @@ typedef struct InputFilter {
 int format;
 
 int width, height;
+enum OrientationType orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+enum OrientationType get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..790751f47f 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,28 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+enum OrientationType get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+
+if (orientation > 8 || orientation < 0) {
+av_log(NULL, AV_LOG_WARNING, "Invalid frame orientation: %i, skip 
it.\n", orientation);
+return ORIENTATION_NONE;
+} else if (orientation <= 1) {
+return ORIENTATION_NONE;
+} else if (orientation <= 4) {
+return ORIENTATION_AUTO_FLIP;
+} else {
+return ORIENTATION_AUTO_TRANSPOSE;
+}
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +831,16 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation == ORIENTATION_AUTO_FLIP) { 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation == ORIENTATION_AUTO_TRANSPOSE) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1216,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.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-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH v8 1/2] lavf/vf_transpose: add exif orientation support

2019-06-06 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 163 -
 4 files changed, 187 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..d0b5709d1f 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];

[FFmpeg-devel] [PATCH v7 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-06-04 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c| 16 +++-
 fftools/ffmpeg.h|  3 ++-
 fftools/ffmpeg_filter.c | 28 +++-
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..2f4229a9d0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2126,6 +2126,19 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
 return 1;
 }
 
+static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
+{
+int orientaion = get_frame_orientation(frame);
+int filterst = ifilter->orientation <= 1 ? 0 : // not set
+   ifilter->orientation <= 4 ? 1 : // auto flip
+   2; // auto transpose
+int framest = orientaion <= 1 ? 0 : // not set
+  orientaion <= 4 ? 1 : // auto flip
+  2; // auto transpose
+
+return filterst != framest;
+}
+
 static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
 {
 FilterGraph *fg = ifilter->graph;
@@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
 break;
 case AVMEDIA_TYPE_VIDEO:
 need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+   ifilter->height != frame->height ||
+   orientation_need_update(ifilter, frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7b6f802082..64278b6ab1 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -244,7 +244,7 @@ typedef struct InputFilter {
 // parameters configured for this input
 int format;
 
-int width, height;
+int width, height, orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..1fcadb1871 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+int get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+return orientation;
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +821,18 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation < 0 || ifilter->orientation > 8) {
+av_log(NULL, AV_LOG_ERROR, "Invalid frame orientation: %i\n", 
ifilter->orientation);
+} else if (ifilter->orientation > 1 && ifilter->orientation <= 4) 
{ // skip 0 (not set) and 1 (orientaion 'Normal') 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation > 4) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1208,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

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

To unsubscribe, visit link 

Re: [FFmpeg-devel] [PATCH v6 1/2] lavf/vf_transpose: add exif orientation support

2019-06-04 Thread Jun Li
On Tue, Jun 4, 2019 at 12:50 AM Paul B Mahol  wrote:

> On 5/31/19, Jun Li  wrote:
> > Add exif orientation support and expose an option.
> > ---
> >  libavfilter/hflip.h|   2 +
> >  libavfilter/transpose.h|  14 
> >  libavfilter/vf_hflip.c |  40 ++---
> >  libavfilter/vf_transpose.c | 161 -
> >  4 files changed, 185 insertions(+), 32 deletions(-)
> >
> > diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> > index 204090dbb4..4e89bae3fc 100644
> > --- a/libavfilter/hflip.h
> > +++ b/libavfilter/hflip.h
> > @@ -35,5 +35,7 @@ typedef struct FlipContext {
> >
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vlifp);
> >
> >  #endif /* AVFILTER_HFLIP_H */
> > diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> > index aa262b9487..5da08bddc0 100644
> > --- a/libavfilter/transpose.h
> > +++ b/libavfilter/transpose.h
> > @@ -34,4 +34,18 @@ enum TransposeDir {
> >  TRANSPOSE_VFLIP,
> >  };
> >
> > +enum OrientationType {
> > +ORIENTATION_AUTO_TRANSPOSE = -2,
> > +ORIENTATION_AUTO_FLIP = -1,
> > +ORIENTATION_NONE = 0,
> > +ORIENTATION_NORMAL,
> > +ORIENTATION_HFLIP,
> > +ORIENTATION_ROTATE180,
> > +ORIENTATION_VFLIP,
> > +ORIENTATION_HFLIP_ROTATE270CW,
> > +ORIENTATION_ROTATE90CW,
> > +ORIENTATION_HFLIP_ROTATE90CW,
> > +ORIENTATION_ROTATE270CW
> > +};
> > +
> >  #endif
> > diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> > index b77afc77fc..d24ca5c2e7 100644
> > --- a/libavfilter/vf_hflip.c
> > +++ b/libavfilter/vf_hflip.c
> > @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> uint8_t
> > *ddst, int w)
> >  dst[j] = src[-j];
> >  }
> >
> > -static int config_props(AVFilterLink *inlink)
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >  {
> > -FlipContext *s = inlink->dst->priv;
> >  const AVPixFmtDescriptor *pix_desc =
> > av_pix_fmt_desc_get(inlink->format);
> >  const int hsub = pix_desc->log2_chroma_w;
> >  const int vsub = pix_desc->log2_chroma_h;
> > @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
> >  return ff_hflip_init(s, s->max_step, nb_planes);
> >  }
> >
> > +static int config_props(AVFilterLink *inlink)
> > +{
> > +FlipContext *s = inlink->dst->priv;
> > +return ff_hflip_config_props(s, inlink);
> > +}
> > +
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
> >  {
> >  int i;
> > @@ -170,14 +175,10 @@ typedef struct ThreadData {
> >  AVFrame *in, *out;
> >  } ThreadData;
> >
> > -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> > nb_jobs)
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vflip)
> >  {
> > -FlipContext *s = ctx->priv;
> > -ThreadData *td = arg;
> > -AVFrame *in = td->in;
> > -AVFrame *out = td->out;
> >  uint8_t *inrow, *outrow;
> > -int i, plane, step;
> > +int i, plane, step, outlinesize;
> >
> >  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> > plane++) {
> >  const int width  = s->planewidth[plane];
> > @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
> > *arg, int job, int nb_jobs)
> >
> >  step = s->max_step[plane];
> >
> > -outrow = out->data[plane] + start * out->linesize[plane];
> > -inrow  = in ->data[plane] + start * in->linesize[plane] +
> (width -
> > 1) * step;
> > +if (vflip) {
> > +outrow = out->data[plane] + (height - start - 1)*
> > out->linesize[plane];
> > +outlinesize = -out->linesize[plane];
> > +} else {
> > +outrow = out->data[plane] + start * out->linesize[plane];
> > +outlinesize = out->linesize[plane];
> > +}
> > +
> > +inrow = in->data[plane] + start * in->linesize[plane] +  (width
> -
> > 1) *

[FFmpeg-devel] [PATCH v7 1/2] lavf/vf_transpose: add exif orientation support

2019-06-04 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 163 -
 4 files changed, 187 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..d0b5709d1f 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];

Re: [FFmpeg-devel] [PATCH v6 1/2] lavf/vf_transpose: add exif orientation support

2019-06-03 Thread Jun Li
On Fri, May 31, 2019 at 6:15 PM Jun Li  wrote:

>
> On Thu, May 30, 2019 at 5:29 PM Jun Li  wrote:
>
>> Add exif orientation support and expose an option.
>> ---
>>  libavfilter/hflip.h|   2 +
>>  libavfilter/transpose.h|  14 
>>  libavfilter/vf_hflip.c |  40 ++---
>>  libavfilter/vf_transpose.c | 161 -
>>  4 files changed, 185 insertions(+), 32 deletions(-)
>>
>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>> index 204090dbb4..4e89bae3fc 100644
>> --- a/libavfilter/hflip.h
>> +++ b/libavfilter/hflip.h
>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vlifp);
>>
>>  #endif /* AVFILTER_HFLIP_H */
>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>> index aa262b9487..5da08bddc0 100644
>> --- a/libavfilter/transpose.h
>> +++ b/libavfilter/transpose.h
>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>  TRANSPOSE_VFLIP,
>>  };
>>
>> +enum OrientationType {
>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>> +ORIENTATION_AUTO_FLIP = -1,
>> +ORIENTATION_NONE = 0,
>> +ORIENTATION_NORMAL,
>> +ORIENTATION_HFLIP,
>> +ORIENTATION_ROTATE180,
>> +ORIENTATION_VFLIP,
>> +ORIENTATION_HFLIP_ROTATE270CW,
>> +ORIENTATION_ROTATE90CW,
>> +ORIENTATION_HFLIP_ROTATE90CW,
>> +ORIENTATION_ROTATE270CW
>> +};
>> +
>>  #endif
>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>> index b77afc77fc..d24ca5c2e7 100644
>> --- a/libavfilter/vf_hflip.c
>> +++ b/libavfilter/vf_hflip.c
>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>> uint8_t *ddst, int w)
>>  dst[j] = src[-j];
>>  }
>>
>> -static int config_props(AVFilterLink *inlink)
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>  {
>> -FlipContext *s = inlink->dst->priv;
>>  const AVPixFmtDescriptor *pix_desc =
>> av_pix_fmt_desc_get(inlink->format);
>>  const int hsub = pix_desc->log2_chroma_w;
>>  const int vsub = pix_desc->log2_chroma_h;
>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>  }
>>
>> +static int config_props(AVFilterLink *inlink)
>> +{
>> +FlipContext *s = inlink->dst->priv;
>> +return ff_hflip_config_props(s, inlink);
>> +}
>> +
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>  {
>>  int i;
>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>  AVFrame *in, *out;
>>  } ThreadData;
>>
>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>> nb_jobs)
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vflip)
>>  {
>> -FlipContext *s = ctx->priv;
>> -ThreadData *td = arg;
>> -AVFrame *in = td->in;
>> -AVFrame *out = td->out;
>>  uint8_t *inrow, *outrow;
>> -int i, plane, step;
>> +int i, plane, step, outlinesize;
>>
>>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
>> plane++) {
>>  const int width  = s->planewidth[plane];
>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
>> *arg, int job, int nb_jobs)
>>
>>  step = s->max_step[plane];
>>
>> -outrow = out->data[plane] + start * out->linesize[plane];
>> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
>> - 1) * step;
>> +if (vflip) {
>> +outrow = out->data[plane] + (height - start - 1)*
>> out->linesize[plane];
>> +outlinesize = -out->linesize[plane];
>> +} else {
>> +outrow = out->data[plane] + start * out->linesize[plane];
>> +outlinesize = out->linesize[plane];
>> +}
>> +
>> +inrow = in->data[plane] + start * in->linesize[plane] +  (width
>> - 1) * step;
>> +
>>  for (i = start; i < end; i++) {
>>  s->flip_line[plane

Re: [FFmpeg-devel] [PATCH v6 1/2] lavf/vf_transpose: add exif orientation support

2019-05-31 Thread Jun Li
On Thu, May 30, 2019 at 5:29 PM Jun Li  wrote:

> Add exif orientation support and expose an option.
> ---
>  libavfilter/hflip.h|   2 +
>  libavfilter/transpose.h|  14 
>  libavfilter/vf_hflip.c |  40 ++---
>  libavfilter/vf_transpose.c | 161 -
>  4 files changed, 185 insertions(+), 32 deletions(-)
>
> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> index 204090dbb4..4e89bae3fc 100644
> --- a/libavfilter/hflip.h
> +++ b/libavfilter/hflip.h
> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vlifp);
>
>  #endif /* AVFILTER_HFLIP_H */
> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> index aa262b9487..5da08bddc0 100644
> --- a/libavfilter/transpose.h
> +++ b/libavfilter/transpose.h
> @@ -34,4 +34,18 @@ enum TransposeDir {
>  TRANSPOSE_VFLIP,
>  };
>
> +enum OrientationType {
> +ORIENTATION_AUTO_TRANSPOSE = -2,
> +ORIENTATION_AUTO_FLIP = -1,
> +ORIENTATION_NONE = 0,
> +ORIENTATION_NORMAL,
> +ORIENTATION_HFLIP,
> +ORIENTATION_ROTATE180,
> +ORIENTATION_VFLIP,
> +ORIENTATION_HFLIP_ROTATE270CW,
> +ORIENTATION_ROTATE90CW,
> +ORIENTATION_HFLIP_ROTATE90CW,
> +ORIENTATION_ROTATE270CW
> +};
> +
>  #endif
> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> index b77afc77fc..d24ca5c2e7 100644
> --- a/libavfilter/vf_hflip.c
> +++ b/libavfilter/vf_hflip.c
> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t
> *ddst, int w)
>  dst[j] = src[-j];
>  }
>
> -static int config_props(AVFilterLink *inlink)
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>  {
> -FlipContext *s = inlink->dst->priv;
>  const AVPixFmtDescriptor *pix_desc =
> av_pix_fmt_desc_get(inlink->format);
>  const int hsub = pix_desc->log2_chroma_w;
>  const int vsub = pix_desc->log2_chroma_h;
> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>  return ff_hflip_init(s, s->max_step, nb_planes);
>  }
>
> +static int config_props(AVFilterLink *inlink)
> +{
> +FlipContext *s = inlink->dst->priv;
> +return ff_hflip_config_props(s, inlink);
> +}
> +
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>  {
>  int i;
> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>  AVFrame *in, *out;
>  } ThreadData;
>
> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vflip)
>  {
> -FlipContext *s = ctx->priv;
> -ThreadData *td = arg;
> -AVFrame *in = td->in;
> -AVFrame *out = td->out;
>  uint8_t *inrow, *outrow;
> -int i, plane, step;
> +int i, plane, step, outlinesize;
>
>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> plane++) {
>  const int width  = s->planewidth[plane];
> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
> *arg, int job, int nb_jobs)
>
>  step = s->max_step[plane];
>
> -outrow = out->data[plane] + start * out->linesize[plane];
> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
> - 1) * step;
> +if (vflip) {
> +outrow = out->data[plane] + (height - start - 1)*
> out->linesize[plane];
> +outlinesize = -out->linesize[plane];
> +} else {
> +outrow = out->data[plane] + start * out->linesize[plane];
> +outlinesize = out->linesize[plane];
> +}
> +
> +inrow = in->data[plane] + start * in->linesize[plane] +  (width -
> 1) * step;
> +
>  for (i = start; i < end; i++) {
>  s->flip_line[plane](inrow, outrow, width);
>
>  inrow  += in ->linesize[plane];
> -outrow += out->linesize[plane];
> +outrow += outlinesize;
>  }
>  }
>
>  return 0;
>  }
>
> +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +{
> +FlipContext *s = ctx->priv;
> +ThreadData *td = arg;
> +AVFrame *in = td->in;
> +AVFrame *out = td->out;
> +return ff_hflip_filter_sl

[FFmpeg-devel] [PATCH v6 1/2] lavf/vf_transpose: add exif orientation support

2019-05-30 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 161 -
 4 files changed, 185 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..8b5c8d3f50 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,24 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];

[FFmpeg-devel] [PATCH v6 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-30 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c| 16 +++-
 fftools/ffmpeg.h|  3 ++-
 fftools/ffmpeg_filter.c | 28 +++-
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..2f4229a9d0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2126,6 +2126,19 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
 return 1;
 }
 
+static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
+{
+int orientaion = get_frame_orientation(frame);
+int filterst = ifilter->orientation <= 1 ? 0 : // not set
+   ifilter->orientation <= 4 ? 1 : // auto flip
+   2; // auto transpose
+int framest = orientaion <= 1 ? 0 : // not set
+  orientaion <= 4 ? 1 : // auto flip
+  2; // auto transpose
+
+return filterst != framest;
+}
+
 static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
 {
 FilterGraph *fg = ifilter->graph;
@@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
 break;
 case AVMEDIA_TYPE_VIDEO:
 need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+   ifilter->height != frame->height ||
+   orientation_need_update(ifilter, frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index eb1eaf6363..54532ef0eb 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -244,7 +244,7 @@ typedef struct InputFilter {
 // parameters configured for this input
 int format;
 
-int width, height;
+int width, height, orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..1fcadb1871 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+int get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+return orientation;
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +821,18 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation < 0 || ifilter->orientation > 8) {
+av_log(NULL, AV_LOG_ERROR, "Invalid frame orientation: %i\n", 
ifilter->orientation);
+} else if (ifilter->orientation > 1 && ifilter->orientation <= 4) 
{ // skip 0 (not set) and 1 (orientaion 'Normal') 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation > 4) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1208,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

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

To unsubscribe, visit link 

Re: [FFmpeg-devel] [PATCH v3 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-28 Thread Jun Li
On Tue, May 28, 2019 at 1:50 PM Michael Niedermayer 
wrote:

> On Mon, May 27, 2019 at 11:18:26PM -0700, Jun Li wrote:
> > Fix #6945
> > Rotate or/and flip frame according to frame's metadata orientation
> > ---
> >  fftools/ffmpeg.c| 16 +++-
> >  fftools/ffmpeg.h|  3 ++-
> >  fftools/ffmpeg_filter.c | 28 +++-
> >  3 files changed, 40 insertions(+), 7 deletions(-)
> >
> > diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> > index 01f04103cf..2f4229a9d0 100644
> > --- a/fftools/ffmpeg.c
> > +++ b/fftools/ffmpeg.c
> > @@ -2126,6 +2126,19 @@ static int
> ifilter_has_all_input_formats(FilterGraph *fg)
> >  return 1;
> >  }
> >
> > +static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
> > +{
> > +int orientaion = get_frame_orientation(frame);
> > +int filterst = ifilter->orientation <= 1 ? 0 : // not set
> > +   ifilter->orientation <= 4 ? 1 : // auto flip
> > +   2; // auto transpose
> > +int framest = orientaion <= 1 ? 0 : // not set
> > +  orientaion <= 4 ? 1 : // auto flip
> > +  2; // auto transpose
> > +
> > +return filterst != framest;
> > +}
> > +
> >  static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
> >  {
> >  FilterGraph *fg = ifilter->graph;
> > @@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter
> *ifilter, AVFrame *frame)
> >  break;
> >  case AVMEDIA_TYPE_VIDEO:
> >  need_reinit |= ifilter->width  != frame->width ||
> > -   ifilter->height != frame->height;
> > +   ifilter->height != frame->height ||
> > +   orientation_need_update(ifilter, frame);
> >  break;
> >  }
> >
> > diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> > index eb1eaf6363..54532ef0eb 100644
> > --- a/fftools/ffmpeg.h
> > +++ b/fftools/ffmpeg.h
> > @@ -244,7 +244,7 @@ typedef struct InputFilter {
> >  // parameters configured for this input
> >  int format;
> >
> > -int width, height;
> > +int width, height, orientation;
> >  AVRational sample_aspect_ratio;
> >
> >  int sample_rate;
> > @@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
> >  void sub2video_update(InputStream *ist, AVSubtitle *sub);
> >
> >  int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame
> *frame);
> > +int get_frame_orientation(const AVFrame* frame);
> >
> >  int ffmpeg_parse_options(int argc, char **argv);
> >
> > diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
> > index 72838de1e2..ff63540906 100644
> > --- a/fftools/ffmpeg_filter.c
> > +++ b/fftools/ffmpeg_filter.c
> > @@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist,
> InputFilter *ifilter)
> >  return 0;
> >  }
> >
> > +int get_frame_orientation(const AVFrame *frame)
> > +{
> > +AVDictionaryEntry *entry = NULL;
> > +int orientation = 0;
> > +
> > +// read exif orientation data
> > +entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
>
> > +if (entry)
> > +orientation = atoi(entry->value);
>
> this probably should be checking the validity of the string unless
> it has been checked already elsewhere


Thanks Michael for the catch. I updated to version 5:
https://patchwork.ffmpeg.org/patch/13321/
https://patchwork.ffmpeg.org/patch/13322/

Best Regards,
Jun


> thx
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> I have never wished to cater to the crowd; for what I know they do not
> approve, and what they approve I do not know. -- Epicurus
> ___
> 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".
___
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".

Re: [FFmpeg-devel] [PATCH v3 1/2] lavf/vf_transpose: add exif orientation support

2019-05-28 Thread Jun Li
On Tue, May 28, 2019 at 7:21 AM Paul B Mahol  wrote:

> On 5/28/19, Jun Li  wrote:
> > Add exif orientation support and expose an option.
> > ---
> >  libavfilter/hflip.h|   3 +
> >  libavfilter/vf_hflip.c |  43 ++---
> >  libavfilter/vf_transpose.c | 173 +
> >  3 files changed, 171 insertions(+), 48 deletions(-)
> >
> > diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> > index 204090dbb4..3d837f01b0 100644
> > --- a/libavfilter/hflip.h
> > +++ b/libavfilter/hflip.h
> > @@ -35,5 +35,8 @@ typedef struct FlipContext {
> >
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vlifp);
> > +
> >
> >  #endif /* AVFILTER_HFLIP_H */
> > diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> > index b77afc77fc..84fd8975b1 100644
> > --- a/libavfilter/vf_hflip.c
> > +++ b/libavfilter/vf_hflip.c
> > @@ -37,6 +37,7 @@
> >  #include "libavutil/intreadwrite.h"
> >  #include "libavutil/imgutils.h"
> >
> > +
> >  static const AVOption hflip_options[] = {
> >  { NULL }
> >  };
> > @@ -125,9 +126,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> uint8_t
> > *ddst, int w)
> >  dst[j] = src[-j];
> >  }
> >
> > -static int config_props(AVFilterLink *inlink)
> > +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >  {
> > -FlipContext *s = inlink->dst->priv;
> >  const AVPixFmtDescriptor *pix_desc =
> > av_pix_fmt_desc_get(inlink->format);
> >  const int hsub = pix_desc->log2_chroma_w;
> >  const int vsub = pix_desc->log2_chroma_h;
> > @@ -140,10 +140,15 @@ static int config_props(AVFilterLink *inlink)
> >  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h,
> > vsub);
> >
> >  nb_planes = av_pix_fmt_count_planes(inlink->format);
> > -
> >  return ff_hflip_init(s, s->max_step, nb_planes);
> >  }
> >
> > +static int config_props(AVFilterLink *inlink)
> > +{
> > +FlipContext *s = inlink->dst->priv;
> > +return ff_hflip_config_props(s, inlink);
> > +}
> > +
> >  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
> >  {
> >  int i;
> > @@ -170,14 +175,10 @@ typedef struct ThreadData {
> >  AVFrame *in, *out;
> >  } ThreadData;
> >
> > -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> > nb_jobs)
> > +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> > job, int nb_jobs, int vflip)
> >  {
> > -FlipContext *s = ctx->priv;
> > -ThreadData *td = arg;
> > -AVFrame *in = td->in;
> > -AVFrame *out = td->out;
> >  uint8_t *inrow, *outrow;
> > -int i, plane, step;
> > +int i, plane, step, outlinesize;
> >
> >  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> > plane++) {
> >  const int width  = s->planewidth[plane];
> > @@ -187,19 +188,35 @@ static int filter_slice(AVFilterContext *ctx, void
> > *arg, int job, int nb_jobs)
> >
> >  step = s->max_step[plane];
> >
> > -outrow = out->data[plane] + start * out->linesize[plane];
> > -inrow  = in ->data[plane] + start * in->linesize[plane] +
> (width -
> > 1) * step;
> > +if (vflip) {
> > +outrow = out->data[plane] + (height - start - 1)*
> > out->linesize[plane];
> > +outlinesize = -out->linesize[plane];
> > +} else {
> > +outrow = out->data[plane] + start * out->linesize[plane];
> > +outlinesize = out->linesize[plane];
> > +}
> > +
> > +inrow = in->data[plane] + start * in->linesize[plane] +  (width
> -
> > 1) * step;
> > +
> >  for (i = start; i < end; i++) {
> >  s->flip_line[plane](inrow, outrow, width);
> >
> >  inrow  += in ->linesize[plane];
> > -outrow += out->linesize[plane];
> > +outrow += outlinesize;
> >  }
> >  }
> > -
> >  return 0;
> >  }

[FFmpeg-devel] [PATCH v5 1/2] lavf/vf_transpose: add exif orientation support

2019-05-28 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  41 ++---
 libavfilter/vf_transpose.c | 166 -
 4 files changed, 189 insertions(+), 34 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..97161000fd 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -37,6 +37,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/imgutils.h"
 
+
 static const AVOption hflip_options[] = {
 { NULL }
 };
@@ -125,9 +126,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +144,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +176,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +189,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..5ff86536ad 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,24 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {

[FFmpeg-devel] [PATCH v5 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-28 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c| 16 +++-
 fftools/ffmpeg.h|  3 ++-
 fftools/ffmpeg_filter.c | 28 +++-
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..2f4229a9d0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2126,6 +2126,19 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
 return 1;
 }
 
+static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
+{
+int orientaion = get_frame_orientation(frame);
+int filterst = ifilter->orientation <= 1 ? 0 : // not set
+   ifilter->orientation <= 4 ? 1 : // auto flip
+   2; // auto transpose
+int framest = orientaion <= 1 ? 0 : // not set
+  orientaion <= 4 ? 1 : // auto flip
+  2; // auto transpose
+
+return filterst != framest;
+}
+
 static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
 {
 FilterGraph *fg = ifilter->graph;
@@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
 break;
 case AVMEDIA_TYPE_VIDEO:
 need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+   ifilter->height != frame->height ||
+   orientation_need_update(ifilter, frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index eb1eaf6363..54532ef0eb 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -244,7 +244,7 @@ typedef struct InputFilter {
 // parameters configured for this input
 int format;
 
-int width, height;
+int width, height, orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..1fcadb1871 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+int get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+return orientation;
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +821,18 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation < 0 || ifilter->orientation > 8) {
+av_log(NULL, AV_LOG_ERROR, "Invalid frame orientation: %i\n", 
ifilter->orientation);
+} else if (ifilter->orientation > 1 && ifilter->orientation <= 4) 
{ // skip 0 (not set) and 1 (orientaion 'Normal') 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation > 4) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1208,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

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

To unsubscribe, visit link 

[FFmpeg-devel] [PATCH v4 1/2] lavf/vf_transpose: add exif orientation support

2019-05-28 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  41 ++---
 libavfilter/vf_transpose.c | 166 -
 4 files changed, 189 insertions(+), 34 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..97161000fd 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -37,6 +37,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/imgutils.h"
 
+
 static const AVOption hflip_options[] = {
 { NULL }
 };
@@ -125,9 +126,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +144,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +176,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +189,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..d3e6a8eea1 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,24 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {

[FFmpeg-devel] [PATCH v4 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-28 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c| 16 +++-
 fftools/ffmpeg.h|  3 ++-
 fftools/ffmpeg_filter.c | 28 +++-
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..2f4229a9d0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2126,6 +2126,19 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
 return 1;
 }
 
+static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
+{
+int orientaion = get_frame_orientation(frame);
+int filterst = ifilter->orientation <= 1 ? 0 : // not set
+   ifilter->orientation <= 4 ? 1 : // auto flip
+   2; // auto transpose
+int framest = orientaion <= 1 ? 0 : // not set
+  orientaion <= 4 ? 1 : // auto flip
+  2; // auto transpose
+
+return filterst != framest;
+}
+
 static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
 {
 FilterGraph *fg = ifilter->graph;
@@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
 break;
 case AVMEDIA_TYPE_VIDEO:
 need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+   ifilter->height != frame->height ||
+   orientation_need_update(ifilter, frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index eb1eaf6363..54532ef0eb 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -244,7 +244,7 @@ typedef struct InputFilter {
 // parameters configured for this input
 int format;
 
-int width, height;
+int width, height, orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..1fcadb1871 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+int get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry && entry->value)
+orientation = atoi(entry->value);
+return orientation;
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +821,18 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation < 0 || ifilter->orientation > 8) {
+av_log(NULL, AV_LOG_ERROR, "Invalid frame orientation: %i\n", 
ifilter->orientation);
+} else if (ifilter->orientation > 1 && ifilter->orientation <= 4) 
{ // skip 0 (not set) and 1 (orientaion 'Normal') 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_flip");
+} else if (ifilter->orientation > 4) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=auto_transpose");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=rotate180");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1208,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.1

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

To unsubscribe, visit link 

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-28 Thread Jun Li
On Mon, May 27, 2019 at 7:52 AM Nicolas George  wrote:

> Jun Li (12019-05-27):
> > I compared the perf between vflip and this patch before, they take almost
> > the same time, around 9ms for a frame.
> > Hflip is a little special, but surely I can update the patch to avoid
> frame
> > copy, and it will be as fast as hflip.
> >
> > But still this is duplicated feature with vflip/hflip, the only benefit I
> > can think of is rotate180.
> > Previously we need chain two filter (vflip + hflip) to do rotate180, here
> > we only need one.
>
> Please note that there are two separate issues interacting here: having
> separate filters, having separate code.
>
> Merging the features of a filter into a more generic one is, IMHO, a
> good thing. In this instance, it makes the rest of the code simpler.
>
> But that does not mean you have to duplicate the code. You should almost
> never duplicate the code. What you should do is make sure the two
> filters are using the same code, i.e. calling the same functions to do
> the actual work.
>
>
Thanks for pointing that out. I updated the version and merged the existing
flip operation into transpose, removed my previous implementation.
https://patchwork.ffmpeg.org/patch/13311/
https://patchwork.ffmpeg.org/patch/13312/

Thanks a lot for your code review.

Best Regard,
Jun

Regards,
>
> --
>   Nicolas George
> ___
> 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".
___
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".

Re: [FFmpeg-devel] [PATCH v1 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-28 Thread Jun Li
On Mon, May 27, 2019 at 7:56 AM Nicolas George  wrote:

> Jun Li (12019-05-25):
> > I believe it has been enabled by default, the 'autorotate' value is true
> by
> > default.
>
> Yes, but it is currently enabled for constant rotation. Variable
> rotation is more tricky, so the question of enabling it by default must
> be asked again.
>
> > Do you mean the orientation case 1, 2, 3, 4 have the same resolution and
> 5,
> > 6, 7, 8 are rotated, so the reinit is only necessary when switch between
> > these two cases?
>
> I do not know the numeric values by rote, but I think that is what I
> mean.
>
> > I think it is doable. That transpose filter can do partially dynamic
> > processing based on frame's orientation, but the filter args still need
> to
> > set resolution info.
>
> You can have the filter examine the metadata directly, as an option.
>
> > Addressed in the new version.
>
> Did you send it? If so I missed it.
>
>
Hi Nicolas,
I updated the version as follows, it addresses your feedback and leveraged
current flip functionality, as well new option to auto-flip or
auto-transpose.
https://patchwork.ffmpeg.org/patch/13311/
https://patchwork.ffmpeg.org/patch/13312/

Thanks for your review.

Best Regards,
Jun



> Regards,
>
> --
>   Nicolas George
> ___
> 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".
___
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".

[FFmpeg-devel] [PATCH v3 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

2019-05-28 Thread Jun Li
Fix #6945
Rotate or/and flip frame according to frame's metadata orientation
---
 fftools/ffmpeg.c| 16 +++-
 fftools/ffmpeg.h|  3 ++-
 fftools/ffmpeg_filter.c | 28 +++-
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 01f04103cf..2f4229a9d0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2126,6 +2126,19 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
 return 1;
 }
 
+static int orientation_need_update(InputFilter *ifilter, AVFrame *frame)
+{
+int orientaion = get_frame_orientation(frame);
+int filterst = ifilter->orientation <= 1 ? 0 : // not set
+   ifilter->orientation <= 4 ? 1 : // auto flip
+   2; // auto transpose
+int framest = orientaion <= 1 ? 0 : // not set
+  orientaion <= 4 ? 1 : // auto flip
+  2; // auto transpose
+
+return filterst != framest;
+}
+
 static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
 {
 FilterGraph *fg = ifilter->graph;
@@ -2142,7 +2155,8 @@ static int ifilter_send_frame(InputFilter *ifilter, 
AVFrame *frame)
 break;
 case AVMEDIA_TYPE_VIDEO:
 need_reinit |= ifilter->width  != frame->width ||
-   ifilter->height != frame->height;
+   ifilter->height != frame->height ||
+   orientation_need_update(ifilter, frame);
 break;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index eb1eaf6363..54532ef0eb 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -244,7 +244,7 @@ typedef struct InputFilter {
 // parameters configured for this input
 int format;
 
-int width, height;
+int width, height, orientation;
 AVRational sample_aspect_ratio;
 
 int sample_rate;
@@ -649,6 +649,7 @@ int init_complex_filtergraph(FilterGraph *fg);
 void sub2video_update(InputStream *ist, AVSubtitle *sub);
 
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int get_frame_orientation(const AVFrame* frame);
 
 int ffmpeg_parse_options(int argc, char **argv);
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..ff63540906 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -743,6 +743,18 @@ static int sub2video_prepare(InputStream *ist, InputFilter 
*ifilter)
 return 0;
 }
 
+int get_frame_orientation(const AVFrame *frame)
+{
+AVDictionaryEntry *entry = NULL;
+int orientation = 0;
+
+// read exif orientation data
+entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
+if (entry)
+orientation = atoi(entry->value);
+return orientation;
+}
+
 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 AVFilterInOut *in)
 {
@@ -809,13 +821,18 @@ static int configure_input_video_filter(FilterGraph *fg, 
InputFilter *ifilter,
 if (ist->autorotate) {
 double theta = get_rotation(ist->st);
 
-if (fabs(theta - 90) < 1.0) {
+if (fabs(theta) < 1.0) { // no rotation info in stream meta
+if (ifilter->orientation < 0 || ifilter->orientation > 8) {
+av_log(NULL, AV_LOG_ERROR, "Invalid frame orientation: %i\n", 
ifilter->orientation);
+} else if (ifilter->orientation > 1 && ifilter->orientation <= 4) 
{ // skip 0 (not set) and 1 (orientaion 'Normal') 
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=-1");
+} else if (ifilter->orientation > 4) {
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=-2");
+}
+} else if (fabs(theta - 90) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "clock");
 } else if (fabs(theta - 180) < 1.0) {
-ret = insert_filter(_filter, _idx, "hflip", NULL);
-if (ret < 0)
-return ret;
-ret = insert_filter(_filter, _idx, "vflip", NULL);
+ret = insert_filter(_filter, _idx, "transpose", 
"orientation=3");
 } else if (fabs(theta - 270) < 1.0) {
 ret = insert_filter(_filter, _idx, "transpose", "cclock");
 } else if (fabs(theta) > 1.0) {
@@ -1191,6 +1208,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, 
const AVFrame *frame)
 ifilter->width   = frame->width;
 ifilter->height  = frame->height;
 ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+ifilter->orientation = get_frame_orientation(frame);
 
 ifilter->sample_rate = frame->sample_rate;
 ifilter->channels= frame->channels;
-- 
2.17.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] [PATCH v3 1/2] lavf/vf_transpose: add exif orientation support

2019-05-28 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   3 +
 libavfilter/vf_hflip.c |  43 ++---
 libavfilter/vf_transpose.c | 173 +
 3 files changed, 171 insertions(+), 48 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..3d837f01b0 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,8 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
+
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..84fd8975b1 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -37,6 +37,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/imgutils.h"
 
+
 static const AVOption hflip_options[] = {
 { NULL }
 };
@@ -125,9 +126,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -140,10 +140,15 @@ static int config_props(AVFilterLink *inlink)
 s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub);
 
 nb_planes = av_pix_fmt_count_planes(inlink->format);
-
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,35 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
-
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..9cc07a1e6f 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,24 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];
+} TransContextData;
 
+typedef struct TransContext {
+const AVClass *class;
 int passthrough;///< PassthroughType, landscape passthrough mode 
enabled
 int dir;///< TransposeDir
-
-TransVtable vtables[4];
+int orientation;///< Orientation
+int autoflip;
+int autotranspose;
+union {

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-27 Thread Jun Li
On Mon, May 27, 2019 at 1:39 AM Paul B Mahol  wrote:

> On 5/27/19, Jun Li  wrote:
> > On Mon, May 27, 2019 at 12:32 AM Paul B Mahol  wrote:
> >
> >> On 5/27/19, Jun Li  wrote:
> >> > On Sun, May 26, 2019 at 2:09 AM Paul B Mahol 
> wrote:
> >> >
> >> >> On 5/26/19, Jun Li  wrote:
> >> >> > On Sun, May 26, 2019 at 1:16 AM Paul B Mahol 
> >> wrote:
> >> >> >
> >> >> >> On 5/25/19, Jun Li  wrote:
> >> >> >> > Add exif orientation support and expose an option.
> >> >> >> > ---
> >> >> >> >  libavfilter/vf_transpose.c | 258
> >> >> +
> >> >> >> >  1 file changed, 207 insertions(+), 51 deletions(-)
> >> >> >> >
> >> >> >> > diff --git a/libavfilter/vf_transpose.c
> >> b/libavfilter/vf_transpose.c
> >> >> >> > index dd54947bd9..4aebfb9ee4 100644
> >> >> >> > --- a/libavfilter/vf_transpose.c
> >> >> >> > +++ b/libavfilter/vf_transpose.c
> >> >> >> > @@ -46,6 +46,9 @@ typedef struct TransVtable {
> >> >> >> >  void (*transpose_block)(uint8_t *src, ptrdiff_t
> src_linesize,
> >> >> >> >  uint8_t *dst, ptrdiff_t
> dst_linesize,
> >> >> >> >  int w, int h);
> >> >> >> > +void (*copyline_block)(uint8_t *src, ptrdiff_t
> src_linesize,
> >> >> >> > +   uint8_t *dst, ptrdiff_t
> dst_linesize,
> >> >> >> > +   int line_dir, int w, int h);
> >> >> >> >  } TransVtable;
> >> >> >> >
> >> >> >>
> >> >> >> This is slow, the operations should be in one loop.
> >> >> >>
> >> >> >
> >> >> > Thanks Paul for review.
> >> >> > I see transpose is using " ctx->internal->execute(ctx,
> filter_slice,
> >> >> > ,
> >> >> > NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));" .
> >> >> > which looks like leveraging multi-threading.
> >> >> > If we do that in one loop, I guess it would be hard to use
> >> >> multi-threading
> >> >> > to accelerate ? But correct me if I am wrong.
> >> >>
> >> >> Transpose filter does one thing and that is transposing.
> >> >>
> >> >> If I'm not mistaken you are adding vertical and horizontal flipping?
> >> >>
> >> >
> >> > Thanks for review.
> >> > Yes, I am doing vflip, hflip and rotate180(vflip+hflip).
> >> >
> >> >
> >> >> If you really need to do that, do it efficiently in one loop, by
> that I
> >> >> mean
> >> >> you do not do cascading operations at all.
> >> >>
> >> >
> >> > Are you suggesting not use function pointer, and call the function
> >> directly
> >> > like this:
> >>
> >> Please do not invent things I never said.
> >
> > I am sorry that I wrongly understand your question. I am not a native
> > speaker, obviously here we have different understanding about the same
> > sentence.
> >
> > I think I was very clear.
> >
> > But to repeat it once more, it is unacceptable to transpose and do
> >> vflip/hflip as
> >> two separate operations. Instead everything should be done in single
> pass.
> >
> >
> > It may be stupid but I really have trouble understanding "single pass"
> > here. The new added function will be called only once per thread. And
> won't
> > be used together with current transpose method, they are "either-or"
> case.
>
> If they are not used in combination with transpose operation, then I fail
> to see
> point to addition of this slow path when much faster already exist in way
> like calling vflip/hflip filter directly.
> So I really do not see point in re-implementing something in slower
> fashion.
>

Hi Paul,
I compared the perf between vflip and this patch before, they take almost
the same time, around 9ms for a frame.
Hflip is a little special, but surely I can update the patch to avoid frame
copy, and it will be as fast as hflip.

But still this is duplicated feature with vflip/hflip, the only be

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-27 Thread Jun Li
On Mon, May 27, 2019 at 12:32 AM Paul B Mahol  wrote:

> On 5/27/19, Jun Li  wrote:
> > On Sun, May 26, 2019 at 2:09 AM Paul B Mahol  wrote:
> >
> >> On 5/26/19, Jun Li  wrote:
> >> > On Sun, May 26, 2019 at 1:16 AM Paul B Mahol 
> wrote:
> >> >
> >> >> On 5/25/19, Jun Li  wrote:
> >> >> > Add exif orientation support and expose an option.
> >> >> > ---
> >> >> >  libavfilter/vf_transpose.c | 258
> >> +
> >> >> >  1 file changed, 207 insertions(+), 51 deletions(-)
> >> >> >
> >> >> > diff --git a/libavfilter/vf_transpose.c
> b/libavfilter/vf_transpose.c
> >> >> > index dd54947bd9..4aebfb9ee4 100644
> >> >> > --- a/libavfilter/vf_transpose.c
> >> >> > +++ b/libavfilter/vf_transpose.c
> >> >> > @@ -46,6 +46,9 @@ typedef struct TransVtable {
> >> >> >  void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize,
> >> >> >  uint8_t *dst, ptrdiff_t dst_linesize,
> >> >> >  int w, int h);
> >> >> > +void (*copyline_block)(uint8_t *src, ptrdiff_t src_linesize,
> >> >> > +   uint8_t *dst, ptrdiff_t dst_linesize,
> >> >> > +   int line_dir, int w, int h);
> >> >> >  } TransVtable;
> >> >> >
> >> >>
> >> >> This is slow, the operations should be in one loop.
> >> >>
> >> >
> >> > Thanks Paul for review.
> >> > I see transpose is using " ctx->internal->execute(ctx, filter_slice,
> >> > ,
> >> > NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));" .
> >> > which looks like leveraging multi-threading.
> >> > If we do that in one loop, I guess it would be hard to use
> >> multi-threading
> >> > to accelerate ? But correct me if I am wrong.
> >>
> >> Transpose filter does one thing and that is transposing.
> >>
> >> If I'm not mistaken you are adding vertical and horizontal flipping?
> >>
> >
> > Thanks for review.
> > Yes, I am doing vflip, hflip and rotate180(vflip+hflip).
> >
> >
> >> If you really need to do that, do it efficiently in one loop, by that I
> >> mean
> >> you do not do cascading operations at all.
> >>
> >
> > Are you suggesting not use function pointer, and call the function
> directly
> > like this:
>
> Please do not invent things I never said.

I am sorry that I wrongly understand your question. I am not a native
speaker, obviously here we have different understanding about the same
sentence.

I think I was very clear.

But to repeat it once more, it is unacceptable to transpose and do
> vflip/hflip as
> two separate operations. Instead everything should be done in single pass.


It may be stupid but I really have trouble understanding "single pass"
here. The new added function will be called only once per thread. And won't
be used together with current transpose method, they are "either-or" case.

Or are you suggesting moving the flip operation into existing function,
rather than create a new one ?

Best Regards,
Jun

> switch (s->pixsteps[plane]) {
> > case 1:  copyline_block_8(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > case 2:  copyline_block_16(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > case 3:  copyline_block_24(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > case 4:  copyline_block_32(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > case 6:  copyline_block_48(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > case 8:  copyline_block_64(src, srclinesize, dst,
> > dstlinesize, line_dir, outw, end - start); break;
> > }
> >
> > I did some perf comparsion, they are very close and no significant
> > difference, about 9ms for one frame.
> >
> > Also I did some comparison between current hflip filter and this patch,
> > they take almost the same time, about 9ms too on my machine and I see 13
> > threads/jobs are used for filtering.
> > I just use the simple command "ffmpeg  -i test.bmp -vf
> > tra

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-26 Thread Jun Li
On Sun, May 26, 2019 at 2:09 AM Paul B Mahol  wrote:

> On 5/26/19, Jun Li  wrote:
> > On Sun, May 26, 2019 at 1:16 AM Paul B Mahol  wrote:
> >
> >> On 5/25/19, Jun Li  wrote:
> >> > Add exif orientation support and expose an option.
> >> > ---
> >> >  libavfilter/vf_transpose.c | 258
> +
> >> >  1 file changed, 207 insertions(+), 51 deletions(-)
> >> >
> >> > diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
> >> > index dd54947bd9..4aebfb9ee4 100644
> >> > --- a/libavfilter/vf_transpose.c
> >> > +++ b/libavfilter/vf_transpose.c
> >> > @@ -46,6 +46,9 @@ typedef struct TransVtable {
> >> >  void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize,
> >> >  uint8_t *dst, ptrdiff_t dst_linesize,
> >> >  int w, int h);
> >> > +void (*copyline_block)(uint8_t *src, ptrdiff_t src_linesize,
> >> > +   uint8_t *dst, ptrdiff_t dst_linesize,
> >> > +   int line_dir, int w, int h);
> >> >  } TransVtable;
> >> >
> >>
> >> This is slow, the operations should be in one loop.
> >>
> >
> > Thanks Paul for review.
> > I see transpose is using " ctx->internal->execute(ctx, filter_slice, ,
> > NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));" .
> > which looks like leveraging multi-threading.
> > If we do that in one loop, I guess it would be hard to use
> multi-threading
> > to accelerate ? But correct me if I am wrong.
>
> Transpose filter does one thing and that is transposing.
>
> If I'm not mistaken you are adding vertical and horizontal flipping?
>

Thanks for review.
Yes, I am doing vflip, hflip and rotate180(vflip+hflip).


> If you really need to do that, do it efficiently in one loop, by that I
> mean
> you do not do cascading operations at all.
>

Are you suggesting not use function pointer, and call the function directly
like this:
switch (s->pixsteps[plane]) {
case 1:  copyline_block_8(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
case 2:  copyline_block_16(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
case 3:  copyline_block_24(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
case 4:  copyline_block_32(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
case 6:  copyline_block_48(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
case 8:  copyline_block_64(src, srclinesize, dst,
dstlinesize, line_dir, outw, end - start); break;
}

I did some perf comparsion, they are very close and no significant
difference, about 9ms for one frame.

Also I did some comparison between current hflip filter and this patch,
they take almost the same time, about 9ms too on my machine and I see 13
threads/jobs are used for filtering.
I just use the simple command "ffmpeg  -i test.bmp -vf
transpose=orientation=2  -y hello.jpg".
Current vflip wins a lot and I see it is not copying frame at all, just
like "orientation=1" or "passthrough" cases.

I hope I understand you correctly, especially about "cascading operations".
But correct me if I am wrong.
Thanks for your time Paul.

Best Regards,
-Jun

>
> > Best Regards,
> > -Jun
> >
> >
> >> >  typedef struct TransContext {
> >> > @@ -56,7 +59,7 @@ typedef struct TransContext {
> >> >
> >> >  int passthrough;///< PassthroughType, landscape passthrough
> >> > mode
> >> > enabled
> >> >  int dir;///< TransposeDir
> >> > -
> >> > +int orientation;///< Orientation
> >> >  TransVtable vtables[4];
> >> >  } TransContext;
> >> >
> >> > @@ -182,6 +185,105 @@ static void transpose_8x8_64_c(uint8_t *src,
> >> ptrdiff_t
> >> > src_linesize,
> >> >  transpose_block_64_c(src, src_linesize, dst, dst_linesize, 8, 8);
> >> >  }
> >> >
> >> > +
> >> > +static void copyline_block_8(uint8_t *src, ptrdiff_t src_linesize,
> >> > + uint8_t *dst, ptrdiff_t dst_linesize,
> >> > + int line_dir, int w, int h)
> >> > +{
> >> > +int x, y, i;
> >> > +for (y = 0; y &

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-26 Thread Jun Li
On Sun, May 26, 2019 at 1:16 AM Paul B Mahol  wrote:

> On 5/25/19, Jun Li  wrote:
> > Add exif orientation support and expose an option.
> > ---
> >  libavfilter/vf_transpose.c | 258 +
> >  1 file changed, 207 insertions(+), 51 deletions(-)
> >
> > diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
> > index dd54947bd9..4aebfb9ee4 100644
> > --- a/libavfilter/vf_transpose.c
> > +++ b/libavfilter/vf_transpose.c
> > @@ -46,6 +46,9 @@ typedef struct TransVtable {
> >  void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize,
> >  uint8_t *dst, ptrdiff_t dst_linesize,
> >  int w, int h);
> > +void (*copyline_block)(uint8_t *src, ptrdiff_t src_linesize,
> > +   uint8_t *dst, ptrdiff_t dst_linesize,
> > +   int line_dir, int w, int h);
> >  } TransVtable;
> >
>
> This is slow, the operations should be in one loop.
>

Thanks Paul for review.
I see transpose is using " ctx->internal->execute(ctx, filter_slice, ,
NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));" .
which looks like leveraging multi-threading.
If we do that in one loop, I guess it would be hard to use multi-threading
to accelerate ? But correct me if I am wrong.

Best Regards,
-Jun


> >  typedef struct TransContext {
> > @@ -56,7 +59,7 @@ typedef struct TransContext {
> >
> >  int passthrough;///< PassthroughType, landscape passthrough mode
> > enabled
> >  int dir;///< TransposeDir
> > -
> > +int orientation;///< Orientation
> >  TransVtable vtables[4];
> >  } TransContext;
> >
> > @@ -182,6 +185,105 @@ static void transpose_8x8_64_c(uint8_t *src,
> ptrdiff_t
> > src_linesize,
> >  transpose_block_64_c(src, src_linesize, dst, dst_linesize, 8, 8);
> >  }
> >
> > +
> > +static void copyline_block_8(uint8_t *src, ptrdiff_t src_linesize,
> > + uint8_t *dst, ptrdiff_t dst_linesize,
> > + int line_dir, int w, int h)
> > +{
> > +int x, y, i;
> > +for (y = 0; y < h; y++, dst += dst_linesize, src += src_linesize) {
> > +for (x = 0; x < w; x ++) {
> > +i = line_dir < 0 ? w-x-1 : x;
> > +dst[i] = src[x];
> > +}
> > +}
> > +}
> > +
> > +static void copyline_block_16(uint8_t *src, ptrdiff_t src_linesize,
> > +  uint8_t *dst, ptrdiff_t dst_linesize,
> > +  int line_dir, int w, int h)
> > +{
> > +int x, y, i;
> > +for (y = 0; y < h; y++, dst += dst_linesize, src += src_linesize) {
> > +for (x = 0; x < w; x ++) {
> > +i = line_dir < 0 ? w-x-1 : x;
> > +*((uint16_t *)(dst + 2*i)) = *((uint16_t *)(src + 2*x));
> > +}
> > +}
> > +}
> > +
> > +static void copyline_block_24(uint8_t *src, ptrdiff_t src_linesize,
> > +  uint8_t *dst, ptrdiff_t dst_linesize,
> > +  int line_dir, int w, int h)
> > +{
> > +int x, y, i;
> > +for (y = 0; y < h; y++, dst += dst_linesize, src += src_linesize) {
> > +for (x = 0; x < w; x++) {
> > +int32_t v = AV_RB24(src + 3*x);
> > +i = line_dir < 0 ? w-x-1 : x;
> > +AV_WB24(dst + 3*i, v);
> > +}
> > +}
> > +}
> > +
> > +static void copyline_block_32(uint8_t *src, ptrdiff_t src_linesize,
> > +  uint8_t *dst, ptrdiff_t dst_linesize,
> > +  int line_dir, int w, int h)
> > +{
> > +int x, y, i;
> > +for (y = 0; y < h; y++, dst += dst_linesize, src += src_linesize) {
> > +for (x = 0; x < w; x ++) {
> > +i = line_dir < 0 ? w-x-1 : x;
> > +*((uint32_t *)(dst + 4*i)) = *((uint32_t *)(src + 4*x));
> > +}
> > +}
> > +}
> > +
> > +static void copyline_block_48(uint8_t *src, ptrdiff_t src_linesize,
> > +  uint8_t *dst, ptrdiff_t dst_linesize,
> > +  int line_dir, int w, int h)
> > +{
> > +int x, y, i;
> > +for (y = 0; y < h; y++, dst += dst_linesize, src += src_linesize) {
> > +for (x = 0; x < w; x++) {
> > +int64_t v = AV_RB48(src + 6*x);
> > +i = line_di

Re: [FFmpeg-devel] [PATCH v1 1/2] lavf/vf_transpose: add exif orientation support

2019-05-25 Thread Jun Li
On Sat, May 25, 2019 at 2:46 AM Nicolas George  wrote:

> Jun Li (12019-05-24):
> > Add exif orientation support and expose an option.
> > ---
> >  libavfilter/vf_transpose.c | 258 +
> >  1 file changed, 207 insertions(+), 51 deletions(-)
>
> If I read the code correctly, when orientation=1 (unchanged), this code
> will copy the frame instead of just passing it unchanged. Did I miss
> something?
>

return 0;
@@ -334,7 +485,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*in)
 ThreadData td;
 AVFrame *out;

-if (s->passthrough)
+if (s->passthrough || s->orientation == 1)

I believe this line skip the frame copy ?

 return ff_filter_frame(outlink, in);


>
> --
>   Nicolas George
> ___
> 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".
___
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".

  1   2   3   >