0025-transcode-add-support-for-mutliple-venc-paramete.patch 15 KB

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