After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 747728 - vp8enc: multipass-mode=2 is not working
vp8enc: multipass-mode=2 is not working
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other Linux
: Normal blocker
: 1.5.90
Assigned To: GStreamer Maintainers
GStreamer Maintainers
: 719799 740002 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2015-04-12 09:16 UTC by Oleksij Rempel
Modified: 2016-02-05 11:44 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
test file with different caps. (455.84 KB, video/mpeg)
2015-07-08 19:34 UTC, Oleksij Rempel
  Details
patch v1 (4.50 KB, patch)
2015-07-09 08:00 UTC, Oleksij Rempel
none Details | Review
patch v2 (4.45 KB, patch)
2015-07-10 05:45 UTC, Oleksij Rempel
none Details | Review
patch v3 (5.10 KB, patch)
2015-08-11 13:32 UTC, Oleksij Rempel
none Details | Review
patch v4 (5.63 KB, patch)
2015-08-11 14:30 UTC, Oleksij Rempel
none Details | Review

Description Oleksij Rempel 2015-04-12 09:16:40 UTC
It is a regression, but suddenly i don't have time to bisect it.

tested with git master from 12.04.2015.

the vp8enc is working multipass-mode 1 or 0.

The fallowing script will fail with this error:

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Redistribute latency...
ERROR: from element /GstPipeline:pipeline0/GstVP8Enc:vp8enc0: Failed to initialize encoder
Additional debug info:
gstvp8enc.c(1599): gst_vp8_enc_set_format (): /GstPipeline:pipeline0/GstVP8Enc:vp8enc0:
invalid parameter
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

============= script ==========================

echo "======== VIDEO, pass 1 ========="
date
gst-launch-1.0 filesrc location=stream.dump ! mpegpsdemux name=demux demux.video_e0 ! mpegvideoparse ! mpeg2dec ! videorate ! \
    vp8enc threads=2 multipass-mode=1 target-bitrate=1000000 \
      multipass-cache-file=multipass.cache end-usage=vbr auto-alt-ref=1 \
      keyframe-max-dist=360 min-quantizer=0 max-quantizer=60 \
      token-partitions=2 lag-in-frames=16 ! fakesink


#  webmmux name=mux ! filesink location=out_audio.webm \
echo "======== VIDEO, pass 2 ========="
date
gst-launch-1.0 filesrc location=stream.dump ! mpegpsdemux name=demux \
  webmmux name=mux ! filesink location=out_video.webm \
  demux.video_e0 ! mpegvideoparse ! mpeg2dec ! videorate ! \
    vp8enc threads=2 multipass-mode=2 target-bitrate=1000000 \
      multipass-cache-file=multipass.cache end-usage=vbr auto-alt-ref=1 \
      keyframe-max-dist=360 min-quantizer=0 max-quantizer=60 \
      token-partitions=2 lag-in-frames=16 ! queue ! mux. \
  demux.audio_80 ! a52dec mode=2 ! audiorate tolerance=50000000 ! \
    audioconvert ! audioresample ! \
    taginject tags="language-code=ger" ! queue ! vorbisenc ! mux. \
  demux.audio_81 ! a52dec mode=2 ! audiorate tolerance=50000000 ! \
    audioconvert ! audioresample ! \
    taginject tags="language-code=fra" ! queue ! vorbisenc ! mux.
Comment 1 Vincent Penquerc'h 2015-04-13 10:37:54 UTC
Works for me with latest master.

Might be file specific ?
Comment 2 Oleksij Rempel 2015-04-13 15:01:32 UTC
hm... i'll provide a file at weekend.
Comment 3 Oleksij Rempel 2015-04-13 15:03:11 UTC
or, can it be libvpx version issue? 
apt-cache policy libvpx1
libvpx1:
  Installiert:           1.3.0-2
  Installationskandidat: 1.3.0-2
  Versionstabelle:
 *** 1.3.0-2 0
        500 http://de.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages
        100 /var/lib/dpkg/status
Comment 4 Vincent Penquerc'h 2015-04-14 10:58:05 UTC
Works with v1.3.0 and v1.4.0.
Comment 5 Oleksij Rempel 2015-04-18 18:38:46 UTC
I did some more tests. If i use only part of this file, then dual pass is working. If complete file is used, then dual pass will fail. I assume multipass.cache has some corruptions.


stream.dump (complete video dump) https://www.dropbox.com/s/rzn444d9sz8k8pa/stream.dump?dl=0
multipass.cache (probably corrupt file created by fist pass) https://www.dropbox.com/s/uprgegvlaaqrd3i/multipass.cache?dl=0
Comment 6 Oleksij Rempel 2015-05-02 12:14:45 UTC
Hid Vincent,

did you downloaded sample file? May i remove it from dropbox, i need some place :)
Comment 7 Vincent Penquerc'h 2015-05-04 08:28:05 UTC
Seems I can't download from dropbox without making an account anymore, so delete it for now as I'm not sure when I'd get more time to debug this atm.
Comment 8 Oleksij Rempel 2015-07-06 17:27:33 UTC
I found a patch coused this regression. See https://bugzilla.gnome.org/show_bug.cgi?id=726329#c23
Comment 9 Oleksij Rempel 2015-07-06 17:29:09 UTC
I place my comment here too:
this patch (Bug 726329) introduced an regression on two pass encoding. Some DVDs will cause caps renegotiation just at the end of stream and as result corrupted multipass cache.
The issue looks like fallowing:
1. start of stream
2. frames
.........
5. caps reinit.
6. frames
6. end of stream.

Since reinit will send NULL frame image to the encoder, it will create EOS header for the multipass cache file. Next frame will reinit multipass file and actual end of stream will create one more header with EOS and wrong count of frames.
Comment 10 Sebastian Dröge (slomo) 2015-07-07 10:06:44 UTC
So how can we prevent this? Will the renegotiation actually change the caps, if so how are the caps different before and after?
Comment 11 Oleksij Rempel 2015-07-07 18:39:37 UTC
caps are sort of different:
/GstPipeline:pipeline0/GstMpeg2dec:mpeg2dec0.GstPad:src: caps = "video/x-raw\,\ format\=\(string\)I420\,\ width\=\(int\)720\,\ height\=\(int\)576\,\ pixel-aspect-ratio\=\(fraction\)256/135\,\ interlace-mode\=\(string\)mixed\,\ chroma-site\=\(string\)mpeg2\,\ colorimetry\=\(string\)2:4:8:3\,\ framerate\=\(fraction\)25/1"

vs

/GstPipeline:pipeline0/GstMpeg2dec:mpeg2dec0.GstPad:src: caps = "video/x-raw\,\ format\=\(string\)I420\,\ width\=\(int\)720\,\ height\=\(int\)576\,\ pixel-aspect-ratio\=\(fraction\)256/135\,\ interlace-mode\=\(string\)mixed\,\ chroma-site\=\(string\)mpeg2\,\ colorimetry\=\(string\)2:4:5:4\,\ framerate\=\(fraction\)25/1"

The only difference is colorimetry\=\(string\)2:4:5:4.
hm.. what is the best way to solve it? I think about some variants:
- don't reinit on caps which we don't support.
- don't reinit on multipass mode
- use counter for files suffix for each reinit: multipass.cache.0 ... multipass.cache.2 and so on
- other ideas?
Comment 12 Sebastian Dröge (slomo) 2015-07-07 20:17:24 UTC
Also first of all, try to understand *why* the colorimetry is changing :)
Comment 13 Oleksij Rempel 2015-07-08 03:56:48 UTC
I assume because content was changed to plain black frames.
Comment 14 Sebastian Dröge (slomo) 2015-07-08 07:46:39 UTC
That's not enough, I wouldn't be surprised if the caps change is actually wrong.


But your idea to use separate multipass.cache.X files sounds like the best so far. Want to provide a patch?
Comment 15 Oleksij Rempel 2015-07-08 08:32:50 UTC
Sure. Can you please help me to create test case? Currently i need to encode 4GB to get this point.
Comment 16 Sebastian Dröge (slomo) 2015-07-08 08:47:38 UTC
You could create a pipeline with videotestsrc ! capsfilter ! vp8enc ! ... and then at some point change e.g. the resolution in the capsfilter.
Comment 17 Oleksij Rempel 2015-07-08 19:34:17 UTC
Created attachment 307101 [details]
test file with different caps.
Comment 18 Oleksij Rempel 2015-07-09 08:00:10 UTC
Created attachment 307132 [details] [review]
patch v1

So, how about this patch?
Comment 19 Nicolas Dufresne (ndufresne) 2015-07-09 13:28:11 UTC
Review of attachment 307132 [details] [review]:

::: ext/vpx/gstvp8enc.c
@@ +761,3 @@
   gst_vp8_enc->cfg.g_pass = DEFAULT_MULTIPASS_MODE;
+  gst_vp8_enc->multipass_cache_prefix = g_strdup (DEFAULT_MULTIPASS_CACHE_FILE);
+  gst_vp8_enc->multipass_cache_prefix = NULL;

This code seems to dup a string, then set it to NULL. This seems like a bug (and a leak).

@@ +805,3 @@
 
+  g_free (gst_vp8_enc->multipass_cache_prefix);
+  gst_vp8_enc->multipass_cache_prefix = NULL;

Note for future (you are following the style so not your fault) finalize() is never called twice, so there is no need to reset the value to NULL or zero.

@@ +913,3 @@
+      if (gst_vp8_enc->multipass_cache_prefix)
+        g_free (gst_vp8_enc->multipass_cache_prefix);
+      gst_vp8_enc->multipass_cache_prefix = g_value_dup_string (value);

So are you changing the meaning of an existing property ? This seems like an API break.
Comment 20 Oleksij Rempel 2015-07-09 15:26:11 UTC
(In reply to Nicolas Dufresne (stormer) from comment #19)
> Review of attachment 307132 [details] [review] [review]:
> 
> ::: ext/vpx/gstvp8enc.c
> @@ +761,3 @@
>    gst_vp8_enc->cfg.g_pass = DEFAULT_MULTIPASS_MODE;
> +  gst_vp8_enc->multipass_cache_prefix = g_strdup
> (DEFAULT_MULTIPASS_CACHE_FILE);
> +  gst_vp8_enc->multipass_cache_prefix = NULL;
> 
> This code seems to dup a string, then set it to NULL. This seems like a bug
> (and a leak).

oops, you right.

> 
> @@ +805,3 @@
>  
> +  g_free (gst_vp8_enc->multipass_cache_prefix);
> +  gst_vp8_enc->multipass_cache_prefix = NULL;
> 
> Note for future (you are following the style so not your fault) finalize()
> is never called twice, so there is no need to reset the value to NULL or
> zero.

ok

> @@ +913,3 @@
> +      if (gst_vp8_enc->multipass_cache_prefix)
> +        g_free (gst_vp8_enc->multipass_cache_prefix);
> +      gst_vp8_enc->multipass_cache_prefix = g_value_dup_string (value);
> 
> So are you changing the meaning of an existing property ? This seems like an
> API break.

yes, i was thinking about it too. Any idea how to solve it without braking the api?
Comment 21 Oleksij Rempel 2015-07-10 05:45:39 UTC
Created attachment 307193 [details] [review]
patch v2
Comment 22 Tim-Philipp Müller 2015-08-10 14:48:04 UTC
Comment on attachment 307193 [details] [review]
patch v2

Not sure what to do about the subtle change in how the property works. Perhaps just make it so that the first file created is the filename specified, and only for indices > 0 you add the .N suffix to the filename. I suppose the app is supposed to clean those up, but it should create those in a temp dir anyway, so don't think this is a huge problem. The behaviour should maybe be documented for the property, so app developers can know about this without reading the code.
Comment 23 Oleksij Rempel 2015-08-11 13:32:25 UTC
Created attachment 309071 [details] [review]
patch v3

New version. As suggested cache files will be named:
cache
cache.1
cache.2
... and so on
What do you mean about documentation? Should it be in same patch?
Comment 24 Tim-Philipp Müller 2015-08-11 13:38:08 UTC
Doesn't really matter, same patch would be good IMHO. Just add a short note to tell application developers that there might be multiple cache files, under what conditions, and what the naming scheme will be.
Comment 25 Oleksij Rempel 2015-08-11 14:30:00 UTC
Created attachment 309075 [details] [review]
patch v4

How about this?
Comment 26 Tim-Philipp Müller 2015-08-14 10:47:05 UTC
Ok, let's get this in then:

commit abc33c928fc39ab58ec7f8f3784b72b4266242ae
Author: Oleksij Rempel <linux@rempel-privat.de>
Date:   Thu Jul 9 09:51:26 2015 +0200

    vp8enc: provide support for multiple pass cache files
    
    Some files may provide different caps insight of one stream. Since vp8enc
    support caps reinit, we should support cache reinit too.
    If more then file cache file will be created, the naming will be:
    cache
    cache.1
    cache.2
    ...
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747728

Question: don't we need to reset the cache_idx to 0 somewhere?

When doing multi-pass encoding, do you create a new encoder element? I think it needs to be reset to 0 in _stop() or so, so that if the same pipeline/element is re-used for the second pass, it starts reading the right cache files. If you confirm I'll fix it up.
Comment 27 Oleksij Rempel 2015-08-15 07:00:45 UTC
Hm... yes you right. If it can be called without gst_vp8_enc_finalize, then we need it on gst_vp8_enc_stop too.
Comment 28 Sebastian Dröge (slomo) 2015-08-15 07:23:24 UTC
The same change should be applied to vp9enc :)


stop() should always free all stream-specific information, yes.
Comment 29 Tim-Philipp Müller 2015-08-15 10:25:22 UTC
commit 98527a6ea22198db575822dc8201cacea1d5d8bb
Author: Tim-Philipp Müller <tim@centricular.com>
Date:   Sat Aug 15 11:12:05 2015 +0100

    vp8enc, vp9enc: reset multipass file index when stopping encoder
    
    Fixes multipass encoding when re-using the same element/pipeline
    for subsequent encoding runs.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747728

commit 0e10e9295376282036fef0a2129101d7fae9bb94
Author: Tim-Philipp Müller <tim@centricular.com>
Date:   Sat Aug 15 11:09:42 2015 +0100

    vp9enc: provide support for multiple pass cache files
    
    Some files may provide different caps insight of one stream. Since
    vp9enc support caps reinit, we should support cache reinit too.
    If more then file cache file will be created, the naming will be:
    cache cache.1 cache.2 ...
    
    Based on patch by: Oleksij Rempel <linux@rempel-privat.de>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747728
Comment 30 Oleksij Rempel 2015-08-15 12:29:55 UTC
Great! Thank you!
Comment 31 Tim-Philipp Müller 2016-02-05 11:43:50 UTC
*** Bug 740002 has been marked as a duplicate of this bug. ***
Comment 32 Tim-Philipp Müller 2016-02-05 11:44:01 UTC
*** Bug 719799 has been marked as a duplicate of this bug. ***