0025-transcode-add-support-for-mutliple-venc-parameters.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. From 143033b48bc77061fd9286fb00c82160cd8b8de3 Mon Sep 17 00:00:00 2001
  2. From: Alexandre Janniaux <alexandre.janniaux@gmail.com>
  3. Date: Wed, 28 Nov 2018 18:27:16 +0100
  4. Subject: [PATCH 25/26] transcode: add support for mutliple venc parameters
  5. Add support for multiple venc parameters for transcoding. Venc
  6. parameters are tested in th given order and fallback if the encoder
  7. can't be opened.
  8. For example:
  9. --sout#transcode{\
  10. venc={vcodec=h264,module=avcodec{...}},\
  11. venc={vcodec=VP80,module=vpx{...}}}
  12. will first try avcodec module with h264 video format, then vpx module
  13. with VP8 video format.
  14. ---
  15. modules/stream_out/transcode/transcode.c | 258 ++++++++++++++++++-----
  16. modules/stream_out/transcode/transcode.h | 2 +
  17. 2 files changed, 205 insertions(+), 55 deletions(-)
  18. diff --git a/modules/stream_out/transcode/transcode.c b/modules/stream_out/transcode/transcode.c
  19. index c92dd4a974..bc9f9e694a 100644
  20. --- a/modules/stream_out/transcode/transcode.c
  21. +++ b/modules/stream_out/transcode/transcode.c
  22. @@ -153,6 +153,9 @@ vlc_module_begin ()
  23. set_section( N_("Video"), NULL )
  24. add_module( SOUT_CFG_PREFIX "venc", "encoder", NULL, VENC_TEXT,
  25. VENC_LONGTEXT, false )
  26. + /* XXX: VERY HACKY */
  27. + add_string( SOUT_CFG_PREFIX "module", NULL,
  28. + "define the venc module in venc{} parameters", "", true )
  29. add_string( SOUT_CFG_PREFIX "vcodec", NULL, VCODEC_TEXT,
  30. VCODEC_LONGTEXT, false )
  31. add_integer( SOUT_CFG_PREFIX "vb", 0, VB_TEXT,
  32. @@ -219,7 +222,7 @@ vlc_module_begin ()
  33. vlc_module_end ()
  34. static const char *const ppsz_sout_options[] = {
  35. - "venc", "vcodec", "vb",
  36. + "vcodec", "vb",
  37. "scale", "fps", "width", "height", "vfilter", "deinterlace",
  38. "deinterlace-module", "threads", "aenc", "acodec", "ab", "alang",
  39. "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
  40. @@ -227,6 +230,10 @@ static const char *const ppsz_sout_options[] = {
  41. NULL
  42. };
  43. +static const char *const ppsz_venc_options[] = {
  44. + "vcodec", "module", NULL
  45. +};
  46. +
  47. /*****************************************************************************
  48. * Exported prototypes
  49. *****************************************************************************/
  50. @@ -241,6 +248,7 @@ static int Open( vlc_object_t *p_this )
  51. {
  52. sout_stream_t *p_stream = (sout_stream_t*)p_this;
  53. sout_stream_sys_t *p_sys;
  54. + config_chain_t *p_cfg;
  55. char *psz_string;
  56. if( !p_stream->p_next )
  57. @@ -251,8 +259,17 @@ static int Open( vlc_object_t *p_this )
  58. p_sys = calloc( 1, sizeof( *p_sys ) );
  59. p_sys->i_master_drift = 0;
  60. + ARRAY_INIT( p_sys->pp_vencs );
  61. +
  62. + for( p_cfg = p_stream->p_cfg; p_cfg; p_cfg = p_cfg->p_next )
  63. + {
  64. + if( !strcmp( p_cfg->psz_name, "venc" ) )
  65. + ARRAY_APPEND(p_sys->pp_vencs, p_cfg);
  66. + }
  67. +
  68. + /* Parse the other option (except venc) */
  69. config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
  70. - p_stream->p_cfg );
  71. + p_stream->p_cfg );
  72. /* Audio transcoding parameters */
  73. psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "aenc" );
  74. @@ -310,29 +327,6 @@ static int Open( vlc_object_t *p_this )
  75. free( psz_string );
  76. /* Video transcoding parameters */
  77. - psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "venc" );
  78. - p_sys->psz_venc = NULL;
  79. - p_sys->p_video_cfg = NULL;
  80. - if( psz_string && *psz_string )
  81. - {
  82. - char *psz_next;
  83. - psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
  84. - psz_string );
  85. - free( psz_next );
  86. - }
  87. - free( psz_string );
  88. -
  89. - psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vcodec" );
  90. - p_sys->i_vcodec = 0;
  91. - if( psz_string && *psz_string )
  92. - {
  93. - char fcc[5] = " \0";
  94. - memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
  95. - p_sys->i_vcodec = vlc_fourcc_GetCodecFromString( VIDEO_ES, fcc );
  96. - msg_Dbg( p_stream, "Checking video codec mapping for %s got %4.4s ", fcc, (char*)&p_sys->i_vcodec);
  97. - }
  98. - free( psz_string );
  99. -
  100. p_sys->i_vbitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
  101. if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
  102. @@ -435,6 +429,11 @@ static void Close( vlc_object_t * p_this )
  103. sout_stream_t *p_stream = (sout_stream_t*)p_this;
  104. sout_stream_sys_t *p_sys = p_stream->p_sys;
  105. + if( p_sys->p_venc_conf )
  106. + vlc_object_release( p_sys->p_venc_conf );
  107. +
  108. + ARRAY_RESET(p_sys->pp_vencs);
  109. +
  110. free( p_sys->psz_af );
  111. config_ChainDestroy( p_sys->p_audio_cfg );
  112. @@ -481,6 +480,30 @@ static void DeleteSoutStreamID( sout_stream_id_sys_t *id )
  113. }
  114. }
  115. +static encoder_t *InitEncoder( vlc_object_t *p_parent,
  116. + sout_stream_t *p_stream,
  117. + const es_format_t *p_fmt )
  118. +{
  119. + sout_stream_sys_t *p_sys = p_stream->p_sys;
  120. + encoder_t *p_encoder = sout_EncoderCreate( p_parent );
  121. + if( !p_encoder )
  122. + return NULL;
  123. + p_encoder->p_module = NULL;
  124. +
  125. + /* Create destination format */
  126. + es_format_Init( &p_encoder->fmt_in, p_fmt->i_cat, 0 );
  127. + es_format_Init( &p_encoder->fmt_out, p_fmt->i_cat, 0 );
  128. + p_encoder->fmt_out.i_id = p_fmt->i_id;
  129. + p_encoder->fmt_out.i_group = p_fmt->i_group;
  130. +
  131. + if( p_sys->psz_alang )
  132. + p_encoder->fmt_out.psz_language = strdup( p_sys->psz_alang );
  133. + else if( p_fmt->psz_language )
  134. + p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
  135. +
  136. + return p_encoder;
  137. +}
  138. +
  139. static sout_stream_id_sys_t *Add( sout_stream_t *p_stream,
  140. const es_format_t *p_fmt )
  141. {
  142. @@ -499,49 +522,174 @@ static sout_stream_id_sys_t *Add( sout_stream_t *p_stream,
  143. /* Create decoder object */
  144. id->p_decoder = vlc_object_create( p_stream, sizeof( decoder_t ) );
  145. if( !id->p_decoder )
  146. + {
  147. + msg_Err( p_stream, "cannot create decoder" );
  148. goto error;
  149. + }
  150. id->p_decoder->p_module = NULL;
  151. es_format_Init( &id->p_decoder->fmt_out, p_fmt->i_cat, 0 );
  152. es_format_Copy( &id->p_decoder->fmt_in, p_fmt );
  153. id->p_decoder->b_frame_drop_allowed = false;
  154. /* Create encoder object */
  155. - id->p_encoder = sout_EncoderCreate( p_stream );
  156. - if( !id->p_encoder )
  157. - goto error;
  158. - id->p_encoder->p_module = NULL;
  159. -
  160. - /* Create destination format */
  161. - es_format_Init( &id->p_encoder->fmt_in, p_fmt->i_cat, 0 );
  162. - es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
  163. - id->p_encoder->fmt_out.i_id = p_fmt->i_id;
  164. - id->p_encoder->fmt_out.i_group = p_fmt->i_group;
  165. + if( p_fmt->i_cat == VIDEO_ES &&
  166. + ( p_sys->i_vcodec || p_sys->pp_vencs.i_size > 0 ) )
  167. + {
  168. + for( int config_idx=0;
  169. + config_idx<p_sys->pp_vencs.i_size;
  170. + config_idx++ )
  171. + {
  172. + config_chain_t *p_enc_cfg = ARRAY_VAL( p_sys->pp_vencs, config_idx );
  173. +
  174. + /* the encoder config will be hold by the encoder if it succeed */
  175. + p_sys->p_venc_conf =
  176. + vlc_object_create( p_stream, sizeof(vlc_object_t) );
  177. +
  178. + msg_Dbg( p_stream, "trying configuration venc={%s}",
  179. + p_enc_cfg->psz_value );
  180. +
  181. + size_t length = strlen( p_enc_cfg->psz_value );
  182. + size_t first_equal = strcspn( p_enc_cfg->psz_value, "=" );
  183. + size_t first_brace = strcspn( p_enc_cfg->psz_value, "{" );
  184. + size_t first_comma = strcspn( p_enc_cfg->psz_value, "," );
  185. +
  186. + config_ChainDestroy( p_sys->p_video_cfg );
  187. + free( p_sys->psz_venc );
  188. +
  189. + p_sys->psz_venc = NULL;
  190. + p_sys->p_video_cfg = NULL;
  191. +
  192. + if( first_comma == length
  193. + && first_equal > first_brace )
  194. + {
  195. + /* venc configuration is in the legacy form */
  196. + char *psz_next;
  197. + psz_next = config_ChainCreate( &p_sys->psz_venc,
  198. + &p_sys->p_video_cfg,
  199. + p_enc_cfg->psz_value );
  200. + free( psz_next );
  201. + }
  202. + else
  203. + {
  204. + /* venc configuration is in the new extended form */
  205. + config_chain_t *p_conf;
  206. + config_ChainParseOptions( &p_conf, p_enc_cfg->psz_value );
  207. + config_ChainParse( p_sys->p_venc_conf, SOUT_CFG_PREFIX,
  208. + ppsz_venc_options, p_conf );
  209. + config_ChainDestroy( p_conf );
  210. +
  211. + p_sys->psz_venc = NULL;
  212. + p_sys->p_video_cfg = NULL;
  213. + char *psz_string = var_GetString( p_sys->p_venc_conf,
  214. + SOUT_CFG_PREFIX "module" );
  215. +
  216. +
  217. + if( !psz_string )
  218. + {
  219. + msg_Err( p_stream,
  220. + "missing key \"encoder\" in extended venc option: %s",
  221. + p_enc_cfg->psz_value );
  222. + vlc_object_release( p_sys->p_venc_conf );
  223. + p_sys->p_venc_conf = NULL;
  224. + continue;
  225. + }
  226. +
  227. +
  228. + char *psz_next;
  229. + psz_next = config_ChainCreate( &p_sys->psz_venc,
  230. + &p_sys->p_video_cfg,
  231. + psz_string );
  232. + free( psz_next );
  233. + free( psz_string );
  234. + }
  235. +
  236. + char *psz_vcodec = var_GetString( p_sys->p_venc_conf,
  237. + SOUT_CFG_PREFIX "vcodec" );
  238. + if( psz_vcodec == NULL )
  239. + psz_vcodec = var_InheritString( p_sys->p_venc_conf,
  240. + SOUT_CFG_PREFIX "vcodec" );
  241. + p_sys->i_vcodec = 0;
  242. + if( psz_vcodec && *psz_vcodec )
  243. + {
  244. + char fcc[5] = " \0";
  245. + memcpy( fcc, psz_vcodec, __MIN( strlen( psz_vcodec ), 4 ) );
  246. + p_sys->i_vcodec = vlc_fourcc_GetCodecFromString( VIDEO_ES, fcc );
  247. + msg_Dbg( p_stream, "Checking video codec mapping for %s got %4.4s ", fcc, (char*)&p_sys->i_vcodec);
  248. + }
  249. + free( psz_vcodec );
  250. +
  251. +
  252. + id->p_encoder = InitEncoder( p_sys->p_venc_conf, p_stream, p_fmt );
  253. + if( !id->p_encoder )
  254. + {
  255. + msg_Warn( p_stream, "cannot initialize encoder" );
  256. + vlc_object_release( p_sys->p_venc_conf );
  257. + p_sys->p_venc_conf = NULL;
  258. + continue;
  259. + }
  260. +
  261. + if( !p_sys->i_vcodec )
  262. + {
  263. + msg_Warn( p_stream,
  264. + "cannot use config venc={%s}, no vcodec defined",
  265. + p_enc_cfg->psz_value );
  266. +
  267. + es_format_Clean( &id->p_encoder->fmt_out );
  268. + vlc_object_release( p_sys->p_venc_conf );
  269. + p_sys->p_venc_conf = NULL;
  270. +
  271. + vlc_object_release( id->p_encoder );
  272. + id->p_encoder = NULL;
  273. + continue;
  274. + }
  275. +
  276. + if( !transcode_video_add( p_stream, p_fmt, id ) )
  277. + {
  278. + msg_Warn( p_stream,
  279. + "can't use transcode configuration with venc=%s",
  280. + p_enc_cfg->psz_value );
  281. + es_format_Clean( &id->p_encoder->fmt_out );
  282. +
  283. + vlc_object_release( p_sys->p_venc_conf );
  284. + p_sys->p_venc_conf = NULL;
  285. +
  286. + vlc_object_release( id->p_encoder );
  287. + id->p_encoder = NULL;
  288. + continue;
  289. + }
  290. +
  291. + msg_Info( p_stream, "using venc={%s} configuration for transcoding",
  292. + p_enc_cfg->psz_value );
  293. + break;
  294. + }
  295. + }
  296. + else
  297. + {
  298. + id->p_encoder = InitEncoder( VLC_OBJECT(p_stream), p_stream, p_fmt );
  299. - if( p_sys->psz_alang )
  300. - id->p_encoder->fmt_out.psz_language = strdup( p_sys->psz_alang );
  301. - else if( p_fmt->psz_language )
  302. - id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
  303. + bool success;
  304. - bool success;
  305. + if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec )
  306. + success = transcode_audio_add(p_stream, p_fmt, id);
  307. + else if( ( p_fmt->i_cat == SPU_ES ) &&
  308. + ( p_sys->i_scodec || p_sys->b_soverlay ) )
  309. + success = transcode_spu_add(p_stream, p_fmt, id);
  310. + else
  311. + {
  312. + msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
  313. + (char*)&p_fmt->i_codec );
  314. + id->id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
  315. + id->b_transcode = false;
  316. - if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec )
  317. - success = transcode_audio_add(p_stream, p_fmt, id);
  318. - else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_vcodec )
  319. - success = transcode_video_add(p_stream, p_fmt, id);
  320. - else if( ( p_fmt->i_cat == SPU_ES ) &&
  321. - ( p_sys->i_scodec || p_sys->b_soverlay ) )
  322. - success = transcode_spu_add(p_stream, p_fmt, id);
  323. - else
  324. - {
  325. - msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
  326. - (char*)&p_fmt->i_codec );
  327. - id->id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
  328. - id->b_transcode = false;
  329. + success = id->id;
  330. + }
  331. - success = id->id;
  332. + if (!success)
  333. + goto error;
  334. }
  335. - if(!success)
  336. +
  337. + if( !id->p_encoder )
  338. goto error;
  339. return id;
  340. diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h
  341. index 1b5e886d94..e2ba426030 100644
  342. --- a/modules/stream_out/transcode/transcode.h
  343. +++ b/modules/stream_out/transcode/transcode.h
  344. @@ -38,6 +38,8 @@ struct sout_stream_sys_t
  345. char *psz_af;
  346. /* Video */
  347. + DECL_ARRAY(config_chain_t *) pp_vencs;
  348. + vlc_object_t *p_venc_conf;
  349. vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
  350. char *psz_venc;
  351. config_chain_t *p_video_cfg;
  352. --
  353. 2.20.1