[vlc-devel] [PATCH 0/3] Bug when converting with both deinterlace checked and codec options
Jérôme Froissart
software at froissart.eu
Thu Sep 19 22:47:57 CEST 2019
>From c3e064e8985acf23d7af688167345335f80f568a Mon Sep 17 00:00:00 2001
From: Jérôme Froissart <software at froissart.eu>
Date: Thu, 19 Sep 2019 12:48:29 +0200
Subject: [PATCH 3/3] Deinterlace can be associated with codec arguments
Previously, one could not convert a video into a video with both:
* deinterlace checked (in the Convert dialog)
* custom options (in "Profile edition" dialog, "Video codec" tab)
This was due to incorrectly handled braces in a SoutMrl.
This patches requires to make VLCProfileSelector::getTranscode() return a
SoutMrl instead of a plain QString, which eases the handling of the Mrl
---
.../qt/components/sout/profile_selector.cpp | 78 +++++++++----------
.../qt/components/sout/profile_selector.hpp | 5 +-
modules/gui/qt/dialogs/convert.cpp | 37 ++++++---
modules/gui/qt/dialogs/sout.cpp | 4 +-
4 files changed, 66 insertions(+), 58 deletions(-)
diff --git a/modules/gui/qt/components/sout/profile_selector.cpp
b/modules/gui/qt/components/sout/profile_selector.cpp
index 55fc5c9c28..36867bc91b 100644
--- a/modules/gui/qt/components/sout/profile_selector.cpp
+++ b/modules/gui/qt/components/sout/profile_selector.cpp
@@ -203,7 +203,7 @@ void VLCProfileSelector::updateOptions( int i )
if ( rx.indexIn( options ) != -1 )
return updateOptionsOldFormat( i );
- transcode = "";
+ transcode.clear();
QStringList tuples = options.split( ";" );
typedef QHash<QString, QString> proptovalueHashType;
@@ -242,8 +242,7 @@ void VLCProfileSelector::updateOptions( int i )
}\
else value = QString()
- SoutMrl smrl;
- smrl.begin( "transcode" );
+ transcode.begin( "transcode" );
/* First muxer options */
HASHPICK( "muxer", "mux" );
@@ -257,19 +256,19 @@ void VLCProfileSelector::updateOptions( int i )
if ( !value.isEmpty() )
{
- smrl.option( "vcodec", value );
+ transcode.option( "vcodec", value );
HASHPICK( "vcodec", "bitrate" );
if ( value.toInt() > 0 )
{
- smrl.option( "vb", value.toInt() );
+ transcode.option( "vb", value.toInt() );
}
HASHPICK( "video", "filters" );
if ( !value.isEmpty() )
{
QStringList valuesList = QUrl::fromPercentEncoding(
value.toLatin1() ).split( ";" );
- smrl.option( "vfilter", valuesList.join( ":" ) );
+ transcode.option( "vfilter", valuesList.join( ":" ) );
}
/*if ( codec is h264 )*/
@@ -286,28 +285,28 @@ void VLCProfileSelector::updateOptions( int i )
codecoptions << QUrl::fromPercentEncoding(
value.toLatin1() );
if ( codecoptions.count() )
- smrl.option( "venc",
+ transcode.option( "venc",
QString("x264{%1}").arg( codecoptions.join(",") )
);
}
HASHPICK( "vcodec", "framerate" );
if ( !value.isEmpty() && value.toInt() > 0 )
- smrl.option( "fps", value );
+ transcode.option( "fps", value );
HASHPICK( "vcodec", "scale" );
if ( !value.isEmpty() )
- smrl.option( "scale", value );
+ transcode.option( "scale", value );
HASHPICK( "vcodec", "width" );
if ( !value.isEmpty() && value.toInt() > 0 )
- smrl.option( "width", value );
+ transcode.option( "width", value );
HASHPICK( "vcodec", "height" );
if ( !value.isEmpty() && value.toInt() > 0 )
- smrl.option( "height", value );
+ transcode.option( "height", value );
}
} else {
- smrl.option( "vcodec", "none" );
+ transcode.option( "vcodec", "none" );
}
HASHPICK( "audio", "enable" );
@@ -316,27 +315,27 @@ void VLCProfileSelector::updateOptions( int i )
HASHPICK( "audio", "codec" );
if ( !value.isEmpty() )
{
- smrl.option( "acodec", value );
+ transcode.option( "acodec", value );
HASHPICK( "acodec", "bitrate" );
- smrl.option( "ab", value.toInt() );
+ transcode.option( "ab", value.toInt() );
HASHPICK( "acodec", "channels" );
- smrl.option( "channels", value.toInt() );
+ transcode.option( "channels", value.toInt() );
HASHPICK( "acodec", "samplerate" );
- smrl.option( "samplerate", value.toInt() );
+ transcode.option( "samplerate", value.toInt() );
HASHPICK( "audio", "filters" );
if ( !value.isEmpty() )
{
QStringList valuesList = QUrl::fromPercentEncoding(
value.toLatin1() ).split( ";" );
- smrl.option( "afilter", valuesList.join( ":" ) );
+ transcode.option( "afilter", valuesList.join( ":" ) );
}
}
} else {
- smrl.option( "acodec", "none" );
+ transcode.option( "acodec", "none" );
}
HASHPICK( "subtitles", "enable" );
@@ -346,20 +345,18 @@ void VLCProfileSelector::updateOptions( int i )
if ( value.isEmpty() )
{
HASHPICK( "subtitles", "codec" );
- smrl.option( "scodec", value );
+ transcode.option( "scodec", value );
}
else
{
- smrl.option( "soverlay" );
+ transcode.option( "soverlay" );
}
} else {
- smrl.option( "scodec", "none" );
+ transcode.option( "scodec", "none" );
}
- smrl.end();
+ transcode.end();
#undef HASHPICK
- transcode = smrl.getMrl();
-
cleanup:
/* Temp hash tables cleanup */
foreach( proptovalueHashType *hash, categtopropHash )
@@ -376,52 +373,49 @@ void VLCProfileSelector::updateOptionsOldFormat( int
i )
mux = options[0];
- SoutMrl smrl;
if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
{
- smrl.begin( "transcode" );
+ transcode.begin( "transcode" );
if( options[1].toInt() )
{
- smrl.option( "vcodec", options[4] );
+ transcode.option( "vcodec", options[4] );
if( options[4] != "none" )
{
- smrl.option( "vb", options[5].toInt() );
+ transcode.option( "vb", options[5].toInt() );
if( !options[7].isEmpty() && options[7].toInt() > 0 )
- smrl.option( "fps", options[7] );
+ transcode.option( "fps", options[7] );
if( !options[6].isEmpty() )
- smrl.option( "scale", options[6] );
+ transcode.option( "scale", options[6] );
if( !options[8].isEmpty() && options[8].toInt() > 0 )
- smrl.option( "width", options[8].toInt() );
+ transcode.option( "width", options[8].toInt() );
if( !options[9].isEmpty() && options[9].toInt() > 0 )
- smrl.option( "height", options[9].toInt() );
+ transcode.option( "height", options[9].toInt() );
}
}
if( options[2].toInt() )
{
- smrl.option( "acodec", options[10] );
+ transcode.option( "acodec", options[10] );
if( options[10] != "none" )
{
- smrl.option( "ab", options[11].toInt() );
- smrl.option( "channels", options[12].toInt() );
- smrl.option( "samplerate", options[13].toInt() );
+ transcode.option( "ab", options[11].toInt() );
+ transcode.option( "channels", options[12].toInt() );
+ transcode.option( "samplerate", options[13].toInt() );
}
}
if( options[3].toInt() )
{
- smrl.option( "scodec", options[14] );
+ transcode.option( "scodec", options[14] );
if( options[15].toInt() )
- smrl.option( "soverlay" );
+ transcode.option( "soverlay" );
}
- smrl.end();
-
- transcode = smrl.getMrl();
+ transcode.end();
}
else
- transcode = "";
+ transcode.clear();
emit optionsChanged();
}
diff --git a/modules/gui/qt/components/sout/profile_selector.hpp
b/modules/gui/qt/components/sout/profile_selector.hpp
index 1074c7b220..61d3502eb7 100644
--- a/modules/gui/qt/components/sout/profile_selector.hpp
+++ b/modules/gui/qt/components/sout/profile_selector.hpp
@@ -30,6 +30,7 @@
#include <QHash>
#include "util/qvlcframe.hpp"
+#include "util/soutmrl.hpp"
#include "ui_profiles.h"
class QComboBox;
@@ -42,14 +43,14 @@ public:
VLCProfileSelector( QWidget *_parent );
~VLCProfileSelector();
QString getMux() { return mux; }
- QString getTranscode() { return transcode; }
+ SoutMrl getTranscode() { return transcode; }
private:
QComboBox *profileBox;
void fillProfilesCombo();
void editProfile( const QString&, const QString& );
void saveProfiles();
QString mux;
- QString transcode;
+ SoutMrl transcode;
private slots:
void newProfile();
void editProfile();
diff --git a/modules/gui/qt/dialogs/convert.cpp
b/modules/gui/qt/dialogs/convert.cpp
index cf157472b6..332da28c70 100644
--- a/modules/gui/qt/dialogs/convert.cpp
+++ b/modules/gui/qt/dialogs/convert.cpp
@@ -176,21 +176,20 @@ void ConvertDialog::close()
for(int i = 0; i < incomingMRLs->length(); i++)
{
- QString mrl;
+ SoutMrl mrl;
if( dumpRadio->isChecked() )
{
- mrl = "demux=dump :demuxdump-file=" + fileLine->text();
+ mrl.header("demux=dump :demuxdump-file=" + fileLine->text());
}
else
{
- mrl = "sout=#" + profile->getTranscode();
+ mrl = profile->getTranscode();
+ mrl.header( "sout=#" + mrl.getHeader() );
if( deinterBox->isChecked() )
{
- mrl.remove( '}' );
- mrl += ",deinterlace}";
+ mrl.option("deinterlace");
}
- mrl += ":";
QString newFileName;
@@ -229,15 +228,29 @@ void ConvertDialog::close()
newFileName.replace( QChar('\''), "\\\'" );
- QString chain =
QString("std{access=file{no-overwrite},mux=%1,dst='%2'}")
- .arg( profile->getMux() ).arg(
newFileName );
+
+ mrl.end();
+ MrlModule dstModule("std");
+ MrlModule file("file");
+ file.option("no-overwrite");
+ dstModule.option("access", file);
+ dstModule.option("mux", profile->getMux());
+ dstModule.option("dst", "'" + newFileName + "'");
+
if( displayBox->isChecked() )
- mrl += QString( "duplicate{dst=display,dst=%1}" ).arg(
chain );
+ {
+ MrlModule duplicate("duplicate");
+ duplicate.option("dst", "display");
+ duplicate.option("dst", dstModule);
+ mrl.module(duplicate);
+ }
else
- mrl += chain;
+ {
+ mrl.module(dstModule);
+ }
}
- msg_Dbg( p_intf, "Transcode MRL: %s", qtu( mrl ) );
- mrls.append(mrl);
+ msg_Dbg( p_intf, "Transcode MRL: %s", qtu( mrl.getMrl() ) );
+ mrls.append(mrl.getMrl());
}
accept();
}
diff --git a/modules/gui/qt/dialogs/sout.cpp
b/modules/gui/qt/dialogs/sout.cpp
index bbcc308d63..3dd764e418 100644
--- a/modules/gui/qt/dialogs/sout.cpp
+++ b/modules/gui/qt/dialogs/sout.cpp
@@ -179,9 +179,9 @@ void SoutDialog::updateMRL()
QString qs_mux = ui.profileSelect->getMux();
SoutMrl smrl( ":sout=#" );
- if( !ui.profileSelect->getTranscode().isEmpty() &&
ui.transcodeBox->isChecked() )
+ if( !ui.profileSelect->getTranscode().getMrl().isEmpty() &&
ui.transcodeBox->isChecked() )
{
- smrl.begin( ui.profileSelect->getTranscode() );
+ smrl.begin( ui.profileSelect->getTranscode().getMrl() );
smrl.end();
}
--
2.20.1
Le jeu. 19 sept. 2019 à 22:46, Jérôme Froissart <software at froissart.eu> a
écrit :
>
> ---
> modules/gui/qt/util/soutmrl.cpp | 5 +++++
> modules/gui/qt/util/soutmrl.hpp | 17 +++++++++++++++++
> 2 files changed, 22 insertions(+)
>
> diff --git a/modules/gui/qt/util/soutmrl.cpp
> b/modules/gui/qt/util/soutmrl.cpp
> index 92aa10ae90..90615c6c86 100644
> --- a/modules/gui/qt/util/soutmrl.cpp
> +++ b/modules/gui/qt/util/soutmrl.cpp
> @@ -38,6 +38,11 @@ void MrlModule::option( const QString& option )
> options.append( OptionPairType( option, "" ) );
> }
>
> +QString SoutMrl::getHeader() const
> +{
> + return hdr;
> +}
> +
> QString SoutMrl::getMrl() const
> {
> QString mrl = hdr;
> diff --git a/modules/gui/qt/util/soutmrl.hpp
> b/modules/gui/qt/util/soutmrl.hpp
> index f584e1162b..69ba4458bb 100644
> --- a/modules/gui/qt/util/soutmrl.hpp
> +++ b/modules/gui/qt/util/soutmrl.hpp
> @@ -99,6 +99,17 @@ public:
> {
> }
>
> + void clear()
> + {
> + hdr = "";
> + modules.clear();
> + }
> +
> + void header( const QString& newHeader )
> + {
> + hdr = newHeader;
> + }
> +
> MrlModule& begin( const QString& module )
> {
> modules.append( MrlModule( module ) );
> @@ -110,6 +121,11 @@ public:
> {
> }
>
> + void module( const MrlModule& module )
> + {
> + modules.append( module );
> + }
> +
> // These should be only in MRLModule, but they are kept in this
> parent class for compatibility with an older API
> void option( const QString& name, const QString& value = "" );
> void option( const QString& name, const int i_value, const int
> i_precision = 10 );
> @@ -117,6 +133,7 @@ public:
> void option( const QString& name, const QString& base, const int
> i_value, const int i_precision = 10 );
> void option( const QString& name, const MrlModule& nested );
>
> + QString getHeader() const;
> QString getMrl() const;
>
> private:
> --
> 2.20.1
>
>
> Le jeu. 19 sept. 2019 à 22:46, Jérôme Froissart <software at froissart.eu> a
> écrit :
>
>>
>> ---
>> modules/gui/qt/Makefile.am | 1 +
>> .../qt/components/sout/profile_selector.cpp | 2 +-
>> .../gui/qt/components/sout/sout_widgets.cpp | 1 +
>> modules/gui/qt/dialogs/sout.hpp | 71 +---------
>> modules/gui/qt/util/soutmrl.cpp | 81 +++++++++++
>> modules/gui/qt/util/soutmrl.hpp | 128 ++++++++++++++++++
>> 6 files changed, 213 insertions(+), 71 deletions(-)
>> create mode 100644 modules/gui/qt/util/soutmrl.cpp
>> create mode 100644 modules/gui/qt/util/soutmrl.hpp
>>
>> diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
>> index af4a5d05cc..71f96a5910 100644
>> --- a/modules/gui/qt/Makefile.am
>> +++ b/modules/gui/qt/Makefile.am
>> @@ -186,6 +186,7 @@ libqt_plugin_la_SOURCES = \
>> gui/qt/util/customwidgets.cpp gui/qt/util/customwidgets.hpp \
>> gui/qt/util/searchlineedit.cpp gui/qt/util/searchlineedit.hpp \
>> gui/qt/util/registry.cpp gui/qt/util/registry.hpp \
>> + gui/qt/util/soutmrl.cpp gui/qt/util/soutmrl.hpp \
>> gui/qt/util/qt_dirs.cpp gui/qt/util/qt_dirs.hpp \
>> gui/qt/util/validators.cpp gui/qt/util/validators.hpp \
>> gui/qt/util/buttons/BrowseButton.cpp \
>> diff --git a/modules/gui/qt/components/sout/profile_selector.cpp
>> b/modules/gui/qt/components/sout/profile_selector.cpp
>> index 586a01f681..55fc5c9c28 100644
>> --- a/modules/gui/qt/components/sout/profile_selector.cpp
>> +++ b/modules/gui/qt/components/sout/profile_selector.cpp
>> @@ -23,7 +23,7 @@
>>
>> #include "components/sout/profile_selector.hpp"
>> #include "components/sout/profiles.hpp"
>> -#include "dialogs/sout.hpp"
>> +#include "util/soutmrl.hpp"
>>
>> #include <QHBoxLayout>
>> #include <QToolButton>
>> diff --git a/modules/gui/qt/components/sout/sout_widgets.cpp
>> b/modules/gui/qt/components/sout/sout_widgets.cpp
>> index 8eb9cccea3..88e64f42cc 100644
>> --- a/modules/gui/qt/components/sout/sout_widgets.cpp
>> +++ b/modules/gui/qt/components/sout/sout_widgets.cpp
>> @@ -26,6 +26,7 @@
>> #include "components/sout/sout_widgets.hpp"
>> #include "dialogs/sout.hpp"
>> #include "util/qt_dirs.hpp"
>> +#include "util/soutmrl.hpp"
>> #include <vlc_intf_strings.h>
>>
>> #include <QGroupBox>
>> diff --git a/modules/gui/qt/dialogs/sout.hpp
>> b/modules/gui/qt/dialogs/sout.hpp
>> index 909dcf80bf..9380a0bc5b 100644
>> --- a/modules/gui/qt/dialogs/sout.hpp
>> +++ b/modules/gui/qt/dialogs/sout.hpp
>> @@ -31,81 +31,12 @@
>>
>> #include "ui_sout.h"
>> #include "util/qvlcframe.hpp"
>> +#include "util/soutmrl.hpp"
>>
>> #include <QWizard>
>>
>> class QPushButton;
>>
>> -class SoutMrl
>> -{
>> -public:
>> - SoutMrl( const QString& head = "")
>> - {
>> - mrl = head;
>> - b_first = true;
>> - b_has_bracket = false;
>> - }
>> -
>> - QString getMrl()
>> - {
>> - return mrl;
>> - }
>> -
>> - void begin( const QString& module )
>> - {
>> - if( !b_first )
>> - mrl += ":";
>> - b_first = false;
>> -
>> - mrl += module;
>> - b_has_bracket = false;
>> - }
>> - void end()
>> - {
>> - if( b_has_bracket )
>> - mrl += "}";
>> - }
>> - void option( const QString& option, const QString& value = "" )
>> - {
>> - if( !b_has_bracket )
>> - mrl += "{";
>> - else
>> - mrl += ",";
>> - b_has_bracket = true;
>> -
>> - mrl += option;
>> -
>> - if( !value.isEmpty() )
>> - {
>> - char *psz = config_StringEscape( qtu(value) );
>> - if( psz )
>> - {
>> - mrl += "=" + qfu( psz );
>> - free( psz );
>> - }
>> - }
>> - }
>> - void option( const QString& name, const int i_value, const int
>> i_precision = 10 )
>> - {
>> - option( name, QString::number( i_value, i_precision ) );
>> - }
>> - void option( const QString& name, const double f_value )
>> - {
>> - option( name, QString::number( f_value ) );
>> - }
>> -
>> - void option( const QString& name, const QString& base, const int
>> i_value, const int i_precision = 10 )
>> - {
>> - option( name, base + ":" + QString::number( i_value, i_precision
>> ) );
>> - }
>> -
>> -private:
>> - QString mrl;
>> - bool b_has_bracket;
>> - bool b_first;
>> -};
>> -
>> -
>> class SoutDialog : public QWizard
>> {
>> Q_OBJECT
>> diff --git a/modules/gui/qt/util/soutmrl.cpp
>> b/modules/gui/qt/util/soutmrl.cpp
>> new file mode 100644
>> index 0000000000..92aa10ae90
>> --- /dev/null
>> +++ b/modules/gui/qt/util/soutmrl.cpp
>> @@ -0,0 +1,81 @@
>> +#include "soutmrl.hpp"
>> +
>> +QString MrlModule::to_string() const
>> +{
>> + QString s = moduleName;
>> +
>> + if( options.size() > 0 )
>> + {
>> + s += "{";
>> + }
>> + OptionsType::const_iterator it;
>> + for( it=options.begin(); it!=options.end(); )
>> + {
>> + s += it->first;
>> + if( it->second.to_string().compare("") != 0 )
>> + {
>> + s += "=" + it->second.to_string();
>> + }
>> + ++it;
>> + if( it != options.end() )
>> + {
>> + s += ",";
>> + }
>> + }
>> + if( options.size() > 0 )
>> + {
>> + s += "}";
>> + }
>> + return s;
>> +}
>> +
>> +void MrlModule::option( const QString& option, const MrlOption& value )
>> +{
>> + options.append( OptionPairType( option, value ) );
>> +}
>> +void MrlModule::option( const QString& option )
>> +{
>> + options.append( OptionPairType( option, "" ) );
>> +}
>> +
>> +QString SoutMrl::getMrl() const
>> +{
>> + QString mrl = hdr;
>> + for( int m=0; m<modules.size(); m++ )
>> + {
>> + mrl += modules[m].to_string();
>> + if( m < modules.size() - 1 )
>> + {
>> + mrl += ":";
>> + }
>> + }
>> +
>> + return mrl;
>> +}
>> +
>> +void SoutMrl::option( const QString& name, const QString& value )
>> +{
>> + if( modules.size() > 0 )
>> + {
>> + modules.back().option( name, value );
>> + }
>> +}
>> +void SoutMrl::option( const QString& name, const int i_value, const int
>> i_precision )
>> +{
>> + option( name, QString::number( i_value, i_precision ) );
>> +}
>> +void SoutMrl::option( const QString& name, const double f_value )
>> +{
>> + option( name, QString::number( f_value ) );
>> +}
>> +void SoutMrl::option( const QString& name, const QString& base, const
>> int i_value, const int i_precision )
>> +{
>> + option( name, base + ":" + QString::number( i_value, i_precision ) );
>> +}
>> +void SoutMrl::option( const QString& name, const MrlModule& nested )
>> +{
>> + if( modules.size() > 0 )
>> + {
>> + modules.back().option( name, nested );
>> + }
>> +}
>> \ No newline at end of file
>> diff --git a/modules/gui/qt/util/soutmrl.hpp
>> b/modules/gui/qt/util/soutmrl.hpp
>> new file mode 100644
>> index 0000000000..f584e1162b
>> --- /dev/null
>> +++ b/modules/gui/qt/util/soutmrl.hpp
>> @@ -0,0 +1,128 @@
>>
>> +/*****************************************************************************
>> + * soutmrl.hpp: A class to generate sout MRLs
>> +
>> ****************************************************************************
>> + *
>> + *
>> + *
>> + *
>> + * What should we put here?
>> + * Authors: Jérôme Froissart <software at froissart.eu>
>> + *
>> + *
>> + *
>> + *
>> + *
>> +
>> *****************************************************************************/
>> +
>> +#ifndef VLC_QT_SOUTMRL_HPP_
>> +#define VLC_QT_SOUTMRL_HPP_
>> +
>> +#include "qt.hpp"
>> +
>> +#include <QMap>
>> +
>> +
>> +class MrlOption;
>> +
>> +class MrlModule
>> +{
>> +public:
>> + MrlModule( const QString& name ) :
>> + moduleName( name )
>> + {
>> + }
>> +
>> + void option( const QString& option, const MrlOption& value );
>> + void option( const QString& option );
>> + QString to_string() const;
>> +
>> +private:
>> + typedef QPair<QString, MrlOption> OptionPairType;
>> + typedef QList<OptionPairType> OptionsType;
>> + const QString moduleName;
>> + OptionsType options;
>> +};
>> +
>> +
>> +class MrlOption
>> +{
>> +public:
>> + MrlOption( const QString& value ) :
>> + kind( String ),
>> + stringValue( value ),
>> + nestedModule("")
>> + {}
>> +
>> + MrlOption( const char* s ) :
>> + MrlOption( QString(s) )
>> + {}
>> +
>> + MrlOption( const MrlModule& module ) :
>> + kind(Nested),
>> + nestedModule(module)
>> + {}
>> +
>> + QString to_string() const{
>> + if( kind == String )
>> + {
>> + return stringValue;
>> + }
>> + else
>> + {
>> + return nestedModule.to_string();
>> + }
>> + }
>> +
>> +private:
>> + enum Kind{ String, Nested };
>> + const Kind kind;
>> + const QString stringValue;
>> + const MrlModule nestedModule;
>> +};
>> +
>> +
>> +/// This class helps building MRLs
>> +///
>> +/// An MRL has the following structure:
>> +/// * a header
>> +/// * any number of modules, which have
>> +/// - a name
>> +/// - any number of key(=value) pairs
>> +/// values can be nested modules
>> +///
>> +/// Example of MRL:
>> HEADERmodule1{a,b=val}:module2:module3{opt,arg=1,stuff=nestedModule{subkey=subvalue}}
>> +class SoutMrl
>> +{
>> +public:
>> + SoutMrl( const QString& header="" ) :
>> + hdr(header)
>> + {
>> + }
>> +
>> + MrlModule& begin( const QString& module )
>> + {
>> + modules.append( MrlModule( module ) );
>> + return modules.back();
>> + }
>> +
>> + // Useless, kept for compatibility with an older API
>> + void end()
>> + {
>> + }
>> +
>> + // These should be only in MRLModule, but they are kept in this
>> parent class for compatibility with an older API
>> + void option( const QString& name, const QString& value = "" );
>> + void option( const QString& name, const int i_value, const int
>> i_precision = 10 );
>> + void option( const QString& name, const double f_value );
>> + void option( const QString& name, const QString& base, const int
>> i_value, const int i_precision = 10 );
>> + void option( const QString& name, const MrlModule& nested );
>> +
>> + QString getMrl() const;
>> +
>> +private:
>> + QString hdr;
>> + QList<MrlModule> modules;
>> +};
>> +
>> +#endif // include guard
>> +
>> --
>> 2.20.1
>>
>>
>> Le jeu. 19 sept. 2019 à 22:44, Jérôme Froissart <software at froissart.eu>
>> a écrit :
>>
>>> Hi,
>>>
>>> When converting a video, an MRL is poorly handled.
>>> When the user checks the "deinterlace" statement, convert.cpp inserts
>>> this statement after removing closing braces to the MRL (using "mrl.remove(
>>> '}' );").
>>> This causes issues in case the passed mrl already contains closing
>>> braces (which is the case when the selected profile has custom video codec
>>> options).
>>> A quick-and-dirty fix would be to remove only the latest brace before
>>> inserting the "deinterlace" statement, but, well...that would be
>>> quick-and-dirty.
>>>
>>> I rather send you a more object-oriented implementation of SoutMrl, that
>>> avoids problems because it better handles "modules" and "options" within
>>> SoutMrls.
>>> The first and second patches are drop-in replacement for the current
>>> implementation.
>>> Then the thirs patch actually fixes the bug.
>>>
>>> To reproduce the bug:
>>> * open VLC, then "Open capture device" (I am not using the English
>>> version, my description can be slightly wrong)
>>> * Choose whatever source you want, e.g. screen
>>> * Choose "convert"
>>> * Choose a profile, and edit it. In the "video codec" tab, add a custom
>>> argument (e.g. "preset=faster", which makes sense with the x264 codec)
>>> * Start the process. VLC will fail because the MRL will lack a closing
>>> brace.
>>> You can see the MRL in the "messages" dialog.
>>> Without my patch, the MRL may look like
>>>
>>> sout=#transcode{vcodec=MJPG,venc=x264{preset=faster,scale=Auto,acodec=mp4a,ab=128,channels=1,samplerate=44100,scodec=none,deinterlace}:std{access=file{no-overwrite},mux=mp4,dst='/path/to/output.mp4'}
>>> whereas my patch correctly handles the closing brace
>>>
>>>
>>> Sorry, I did not know what to put in the .hpp header, I could have
>>> copied/pasted the GPL license, but I do not know how to properly set the
>>> copyright. Maybe you'll know this better than I do.
>>>
>>> These patches can be applied (almost painlessly) to the 3.0.8 branch
>>> (there may only be slight issues with a Makefile.am and a convert.cpp that
>>> was slightly changed)
>>>
>>>
>>> Jérôme Froissart (3):
>>> Re-implemented SoutMrl in a more object-oriented way
>>> Additions to the new SoutMrl implementation
>>> Deinterlace can be associated with codec arguments
>>>
>>> modules/gui/qt/Makefile.am | 1 +
>>> .../qt/components/sout/profile_selector.cpp | 80 +++++-----
>>> .../qt/components/sout/profile_selector.hpp | 5 +-
>>> .../gui/qt/components/sout/sout_widgets.cpp | 1 +
>>> modules/gui/qt/dialogs/convert.cpp | 37 +++--
>>> modules/gui/qt/dialogs/sout.cpp | 4 +-
>>> modules/gui/qt/dialogs/sout.hpp | 71 +--------
>>> modules/gui/qt/util/soutmrl.cpp | 86 +++++++++++
>>> modules/gui/qt/util/soutmrl.hpp | 145 ++++++++++++++++++
>>> 9 files changed, 301 insertions(+), 129 deletions(-)
>>> create mode 100644 modules/gui/qt/util/soutmrl.cpp
>>> create mode 100644 modules/gui/qt/util/soutmrl.hpp
>>>
>>> --
>>> 2.20.1
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20190919/9aa5762c/attachment-0001.html>
More information about the vlc-devel
mailing list