Skip to content

Commit f1a7538

Browse files
committed
As a workaround for issues with thumbnails in combination with Ffmpeg 7, add option decodeOutput to ThumbnailEncode and ThumbnailMapEncode allowing them to use video output as input using loopback decoder introduced in Ffmpeg 7.
2 parents acd9d62 + 2159928 commit f1a7538

File tree

15 files changed

+109
-42
lines changed

15 files changed

+109
-42
lines changed

encore-common/src/main/kotlin/se/svt/oss/encore/model/output/Output.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ data class Output(
1313
val format: String = "mp4",
1414
val postProcessor: PostProcessor = PostProcessor { outputFolder -> listOf(outputFolder.resolve(output)) },
1515
val id: String,
16-
val isImage: Boolean = false
16+
val isImage: Boolean = false,
17+
val decodeOutputStream: String? = null
1718
)
1819

1920
fun interface PostProcessor {
@@ -39,7 +40,7 @@ data class AudioStreamEncode(
3940
override val params: List<String>,
4041
override val filter: String? = null,
4142
override val inputLabels: List<String>,
42-
val preserveLayout: Boolean = false
43+
val preserveLayout: Boolean = false,
4344
) : StreamEncode {
4445
override val twoPass: Boolean
4546
get() = false

encore-common/src/main/kotlin/se/svt/oss/encore/model/profile/ChannelLayout.kt

+12-4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum class ChannelLayout(@JsonValue val layoutName: String, val channels: List<C
5151
CH_LAYOUT_5POINT1_SIDE("5.1(side)", listOf(FL, FR, FC, LFE, SL, SR)),
5252
CH_LAYOUT_6POINT0("6.0", listOf(FL, FR, FC, BC, SL, SR)),
5353
CH_LAYOUT_6POINT0_FRONT("6.0(front)", listOf(FL, FR, FLC, FRC, SL, SR)),
54+
CH_LAYOUT_3POINT1POINT2("3.1.2", listOf(FL, FR, FC, LFE, TFL, TFR)),
5455
CH_LAYOUT_HEXAGONAL("hexagonal", listOf(FL, FR, FC, BL, BR, BC)),
5556
CH_LAYOUT_6POINT1("6.1", listOf(FL, FR, FC, LFE, BC, SL, SR)),
5657
CH_LAYOUT_6POINT1_BACK("6.1(back)", listOf(FL, FR, FC, LFE, BL, BR, BC)),
@@ -60,9 +61,16 @@ enum class ChannelLayout(@JsonValue val layoutName: String, val channels: List<C
6061
CH_LAYOUT_7POINT1("7.1", listOf(FL, FR, FC, LFE, BL, BR, SL, SR)),
6162
CH_LAYOUT_7POINT1_WIDE("7.1(wide)", listOf(FL, FR, FC, LFE, BL, BR, FLC, FRC)),
6263
CH_LAYOUT_7POINT1_WIDE_SIDE("7.1(wide-side)", listOf(FL, FR, FC, LFE, FLC, FRC, SL, SR)),
63-
CH_LAYOUT_OCTAGONAL("octagonal)", listOf(FL, FR, FC, BL, BR, BC, SL, SR)),
64+
CH_LAYOUT_5POINT1POINT2("5.1.2", listOf(FL, FR, FC, LFE, BL, BR, TFL, TFR)),
65+
CH_LAYOUT_OCTAGONAL("octagonal", listOf(FL, FR, FC, BL, BR, BC, SL, SR)),
66+
CH_LAYOUT_CUBE("cube", listOf(FL, FR, BL, BR, TFL, TFR, TBL, TBR)),
67+
CH_LAYOUT_5POINT1POINT4("5.1.4", listOf(FL, FR, FC, LFE, BL, BR, TFL, TFR, TBL, TBR)),
68+
CH_LAYOUT_7POINT1POINT2("7.1.2", listOf(FL, FR, FC, LFE, BL, BR, SL, SR, TFL, TFR)),
69+
CH_LAYOUT_7POINT1POINT4("7.1.4", listOf(FL, FR, FC, LFE, BL, BR, SL, SR, TFL, TFR, TBL, TBR)),
70+
CH_LAYOUT_7POINT2POINT3("7.2.3", listOf(FL, FR, FC, LFE, BL, BR, SL, SR, TFL, TFR, TBC, LFE2)),
71+
CH_LAYOUT_9POINT1POINT4("9.1.4", listOf(FL, FR, FC, LFE, BL, BR, FLC, FRC, SL, SR, TFL, TFR, TBL, TBR)),
6472
CH_LAYOUT_HEXADECAGONAL(
65-
"hexadecagonal)",
73+
"hexadecagonal",
6674
listOf(
6775
FL, FR, FC, BL, BR, BC, SL, SR, TFL, TFC, TFR, TBL, TBC, TBR, WL, WR
6876
)
@@ -99,7 +107,7 @@ enum class ChannelLayout(@JsonValue val layoutName: String, val channels: List<C
99107
);
100108

101109
companion object {
102-
fun defaultChannelLayout(numChannels: Int) = values().firstOrNull { it.channels.size == numChannels }
103-
fun getByNameOrNull(layoutName: String) = values().firstOrNull { it.layoutName == layoutName }
110+
fun defaultChannelLayout(numChannels: Int) = entries.firstOrNull { it.channels.size == numChannels }
111+
fun getByNameOrNull(layoutName: String) = entries.firstOrNull { it.layoutName == layoutName }
104112
}
105113
}

encore-common/src/main/kotlin/se/svt/oss/encore/model/profile/ThumbnailEncode.kt

+18-7
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ data class ThumbnailEncode(
2323
val suffixZeroPad: Int = 2,
2424
val inputLabel: String = DEFAULT_VIDEO_LABEL,
2525
val optional: Boolean = false,
26-
val intervalSeconds: Double? = null
26+
val intervalSeconds: Double? = null,
27+
val decodeOutput: Int? = null
2728
) : OutputProducer {
2829

2930
private val log = KotlinLogging.logger { }
@@ -58,20 +59,23 @@ data class ThumbnailEncode(
5859
video = VideoStreamEncode(
5960
params = params.toParams(),
6061
filter = filter,
61-
inputLabels = listOf(inputLabel)
62+
inputLabels = listOf(inputLabel),
6263
),
6364
output = "${job.baseName}$suffix%0${suffixZeroPad}d.jpg",
6465
postProcessor = { outputFolder ->
6566
outputFolder.listFiles().orEmpty().filter { it.name.matches(fileRegex) }
6667
},
67-
isImage = true
68+
isImage = true,
69+
decodeOutputStream = decodeOutput?.let { "$it:v:0" }
6870
)
6971
}
7072

7173
private fun selectInterval(interval: Double, outputSeek: Double?): String {
72-
val select = outputSeek
73-
?.let { "gte(t\\,$it)*(isnan(prev_selected_t)+gt(floor((t-$it)/$interval)\\,floor((prev_selected_t-$it)/$interval)))" }
74-
?: "isnan(prev_selected_t)+gt(floor(t/$interval)\\,floor(prev_selected_t/$interval))"
74+
val select = if (outputSeek != null && decodeOutput == null) {
75+
"gte(t\\,$outputSeek)*(isnan(prev_selected_t)+gt(floor((t-$outputSeek)/$interval)\\,floor((prev_selected_t-$outputSeek)/$interval)))"
76+
} else {
77+
"isnan(prev_selected_t)+gt(floor(t/$interval)\\,floor(prev_selected_t/$interval))"
78+
}
7579
return "select=$select"
7680
}
7781

@@ -87,7 +91,14 @@ data class ThumbnailEncode(
8791
val outputDuration = outputDuration(videoIn, job)
8892
return percentages
8993
.map { it * outputDuration / 100 }
90-
.map { t -> job.seekTo?.let { t + it } ?: t }
94+
.map { t ->
95+
val outputSeek = job.seekTo
96+
if (outputSeek != null && decodeOutput == null) {
97+
t + outputSeek
98+
} else {
99+
t
100+
}
101+
}
91102
}
92103

93104
private fun selectTimes(times: List<Double>) =

encore-common/src/main/kotlin/se/svt/oss/encore/model/profile/ThumbnailMapEncode.kt

+19-15
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ data class ThumbnailMapEncode(
2222
val tileHeight: Int = 90,
2323
val cols: Int = 12,
2424
val rows: Int = 20,
25+
val quality: Int = 5,
2526
val optional: Boolean = true,
2627
val suffix: String = "_${cols}x${rows}_${tileWidth}x${tileHeight}_thumbnail_map",
2728
val format: String = "jpg",
28-
val inputLabel: String = DEFAULT_VIDEO_LABEL
29+
val inputLabel: String = DEFAULT_VIDEO_LABEL,
30+
val decodeOutput: Int? = null
2931
) : OutputProducer {
3032

3133
private val log = KotlinLogging.logger { }
@@ -40,53 +42,54 @@ data class ThumbnailMapEncode(
4042
?: return logOrThrow("No input with label $inputLabel!")
4143

4244
var inputDuration = videoStream.duration
45+
val outputSeek = job.seekTo
4346
inputSeekTo?.let { inputDuration -= it }
44-
job.seekTo?.let { inputDuration -= it }
47+
outputSeek?.let { inputDuration -= it }
4548
val outputDuration = job.duration ?: inputDuration
4649

4750
if (outputDuration <= 0) {
4851
return logOrThrow("Cannot create thumbnail map $suffix! Could not detect duration.")
4952
}
5053

5154
val interval = outputDuration / (cols * rows)
52-
val select = job.seekTo
53-
?.let { "gte(t\\,$it)*(isnan(prev_selected_t)+gt(floor((t-$it)/$interval)\\,floor((prev_selected_t-$it)/$interval)))" }
54-
?: "isnan(prev_selected_t)+gt(floor(t/$interval)\\,floor(prev_selected_t/$interval))"
55+
val select = if (outputSeek != null && decodeOutput == null) {
56+
"gte(t\\,$outputSeek)*(isnan(prev_selected_t)+gt(floor((t-$outputSeek)/$interval)\\,floor((prev_selected_t-$outputSeek)/$interval)))"
57+
} else {
58+
"isnan(prev_selected_t)+gt(floor(t/$interval)\\,floor(prev_selected_t/$interval))"
59+
}
5560

5661
val tempFolder = createTempDir(suffix).toFile()
5762
tempFolder.deleteOnExit()
5863

5964
val pad = "aspect=${Fraction(tileWidth, tileHeight).stringValue()}:x=(ow-iw)/2:y=(oh-ih)/2"
6065

61-
val scale = if (format == "jpg") {
62-
"-1:$tileHeight:out_range=jpeg"
63-
} else {
64-
"-1:$tileHeight"
65-
}
66+
val scale = "-1:$tileHeight"
67+
6668
val params = linkedMapOf(
67-
"q:v" to "5",
6869
"fps_mode" to "vfr"
6970
)
7071
return Output(
7172
id = "$suffix.$format",
7273
video = VideoStreamEncode(
7374
params = params.toParams(),
7475
filter = "select=$select,pad=$pad,scale=$scale",
75-
inputLabels = listOf(inputLabel)
76+
inputLabels = listOf(inputLabel),
7677
),
77-
output = tempFolder.resolve("${job.baseName}$suffix%04d.$format").toString(),
78+
output = tempFolder.resolve("${job.baseName}$suffix%04d.png").toString(),
7879
postProcessor = { outputFolder ->
7980
try {
8081
val targetFile = outputFolder.resolve("${job.baseName}$suffix.$format")
8182
val process = ProcessBuilder(
8283
"ffmpeg",
8384
"-y",
8485
"-i",
85-
"${job.baseName}$suffix%04d.$format",
86+
"${job.baseName}$suffix%04d.png",
8687
"-vf",
8788
"tile=${cols}x$rows",
8889
"-frames:v",
8990
"1",
91+
"-q:v",
92+
"$quality",
9093
"$targetFile"
9194
)
9295
.directory(tempFolder)
@@ -102,7 +105,8 @@ data class ThumbnailMapEncode(
102105
emptyList()
103106
}
104107
},
105-
isImage = true
108+
isImage = true,
109+
decodeOutputStream = decodeOutput?.let { "$it:v:0" }
106110
)
107111
}
108112

encore-common/src/main/kotlin/se/svt/oss/encore/process/CommandBuilder.kt

+20-7
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,23 @@ class CommandBuilder(
6262
}
6363

6464
private fun secondPassCommand(outputs: List<Output>): List<String> {
65-
val videoFilters = videoFilters(encoreJob.inputs, outputs)
66-
val audioFilters = audioFilters(outputs)
67-
val outputParams = outputs.flatMap(this::secondPassParams)
68-
return inputParams(encoreJob.inputs) + filterParam(videoFilters + audioFilters) + outputParams
65+
val (loopbackOutputs, mainOutputs) = outputs.partition { it.decodeOutputStream != null }
66+
val videoFilters = videoFilters(encoreJob.inputs, mainOutputs)
67+
val audioFilters = audioFilters(mainOutputs)
68+
val outputParams = mainOutputs.flatMap(this::secondPassParams)
69+
return inputParams(encoreJob.inputs) + filterParam(videoFilters + audioFilters) + outputParams + loopbackParams(loopbackOutputs)
6970
}
7071

72+
private fun loopbackParams(outputs: List<Output>): List<String> =
73+
outputs.flatMapIndexed { index: Int, output: Output ->
74+
listOf(
75+
"-dec",
76+
output.decodeOutputStream ?: throw RuntimeException("No decodeOutputStream in $output!"),
77+
"-filter_complex",
78+
"[dec:$index]${output.video?.filter ?: ""}${MapName.VIDEO.mapLabel(output.id)}"
79+
) + secondPassParams(output)
80+
}
81+
7182
private fun audioFilters(outputs: List<Output>): List<String> {
7283
val audioSplits = encoreJob.inputs.mapIndexedNotNull { inputIndex, input ->
7384
if (input !is AudioIn) return@mapIndexedNotNull null
@@ -230,8 +241,10 @@ class CommandBuilder(
230241
}
231242

232243
private fun secondPassParams(output: Output): List<String> {
244+
val seekParams = output.decodeOutputStream?.let { emptyList() } ?: seekParams()
245+
val durationParams = output.decodeOutputStream?.let { emptyList() } ?: durationParams()
233246
val mapV: List<String> =
234-
output.video?.let { listOf("-map", MapName.VIDEO.mapLabel(output.id)) + seekParams() }
247+
output.video?.let { listOf("-map", MapName.VIDEO.mapLabel(output.id)) + seekParams }
235248
?: emptyList()
236249

237250
val preserveAudioLayout = output.audioStreams.any { it.preserveLayout }
@@ -246,7 +259,7 @@ class CommandBuilder(
246259
} else {
247260
MapName.AUDIO.mapLabel("${output.id}-$index")
248261
}
249-
listOf("-map", mapLabel) + seekParams()
262+
listOf("-map", mapLabel) + seekParams
250263
}
251264

252265
val maps = mapV + mapA
@@ -264,7 +277,7 @@ class CommandBuilder(
264277
val metaDataParams = listOf("-metadata", "comment=Transcoded using Encore")
265278

266279
return maps +
267-
durationParams() +
280+
durationParams +
268281
videoParams + audioParams +
269282
metaDataParams +
270283
File(outputFolder).resolve(output.output).toString()

encore-common/src/test/kotlin/se/svt/oss/encore/model/profile/ThumbnailMapEncodeTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class ThumbnailMapEncodeTest {
2929
.hasId("_12x20_160x90_thumbnail_map.jpg")
3030
.hasVideo(
3131
VideoStreamEncode(
32-
params = listOf("-q:v", "5", "-fps_mode", "vfr"),
33-
filter = "select=isnan(prev_selected_t)+gt(floor(t/0.041666666666666664)\\,floor(prev_selected_t/0.041666666666666664)),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,scale=-1:90:out_range=jpeg",
32+
params = listOf("-fps_mode", "vfr"),
33+
filter = "select=isnan(prev_selected_t)+gt(floor(t/0.041666666666666664)\\,floor(prev_selected_t/0.041666666666666664)),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,scale=-1:90",
3434
twoPass = false,
3535
inputLabels = listOf(DEFAULT_VIDEO_LABEL)
3636
)
@@ -50,8 +50,8 @@ class ThumbnailMapEncodeTest {
5050
.hasId("_6x10_160x90_thumbnail_map.jpg")
5151
.hasVideo(
5252
VideoStreamEncode(
53-
params = listOf("-q:v", "5", "-fps_mode", "vfr"),
54-
filter = "select=gte(t\\,1.0)*(isnan(prev_selected_t)+gt(floor((t-1.0)/0.08333333333333333)\\,floor((prev_selected_t-1.0)/0.08333333333333333))),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,scale=-1:90:out_range=jpeg",
53+
params = listOf("-fps_mode", "vfr"),
54+
filter = "select=gte(t\\,1.0)*(isnan(prev_selected_t)+gt(floor((t-1.0)/0.08333333333333333)\\,floor((prev_selected_t-1.0)/0.08333333333333333))),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,scale=-1:90",
5555
twoPass = false,
5656
inputLabels = listOf(DEFAULT_VIDEO_LABEL)
5757
)

encore-common/src/test/kotlin/se/svt/oss/encore/process/CommandBuilderTest.kt

+17-3
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,15 @@ internal class CommandBuilderTest {
202202
encodingProperties.copy(exitOnError = false, globalParams = linkedMapOf("err_detect" to "explode"))
203203
)
204204

205-
val buildCommands = commandBuilder.buildCommands(listOf(output(true), audioOutput("other", "extra")))
205+
val buildCommands = commandBuilder.buildCommands(listOf(output(true), audioOutput("other", "extra"), thumbnailOutput("thumb", "0:v:0")))
206206

207207
assertThat(buildCommands).hasSize(2)
208208

209209
val firstPass = buildCommands[0].joinToString(" ")
210210
val secondPass = buildCommands[1].joinToString(" ")
211211

212212
assertThat(firstPass).isEqualTo("ffmpeg -err_detect explode -hide_banner -loglevel +level -y -f mp4 -t 22.5 -i /input/test.mp4 -filter_complex sws_flags=scaling;[0:v:1]yadif,setdar=16/9,scale=iw*sar:ih,crop=min(iw\\,ih*1/1):min(ih\\,iw/(1/1)),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,video,filter,split=1[VIDEO-main-test-out];[VIDEO-main-test-out]video-filter[VIDEO-test-out] -map [VIDEO-test-out] -ss 12.1 -an -t 10.4 first pass -f mp4 /dev/null")
213-
assertThat(secondPass).isEqualTo("ffmpeg -err_detect explode -hide_banner -loglevel +level -y -f mp4 -t 22.5 -i /input/test.mp4 -ac 4 -t 22.5 -i /input/main-audio.mp4 -t 22.5 -i /input/other-audio.mp4 -filter_complex sws_flags=scaling;[0:v:1]yadif,setdar=16/9,scale=iw*sar:ih,crop=min(iw\\,ih*1/1):min(ih\\,iw/(1/1)),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,video,filter,split=1[VIDEO-main-test-out];[VIDEO-main-test-out]video-filter[VIDEO-test-out];[1:a]join=inputs=4:channel_layout=4.0:map=0.0-FL|1.0-FR|2.0-FC|3.0-BC,audio-main,main-filter,asplit=1[AUDIO-main-test-out-0];[2:a:3]asplit=1[AUDIO-other-extra-0];[AUDIO-main-test-out-0]audio-filter[AUDIO-test-out-0];[AUDIO-other-extra-0]audio-filter-extra[AUDIO-extra-0] -map [VIDEO-test-out] -ss 12.1 -map [AUDIO-test-out-0] -ss 12.1 -t 10.4 video params audio params -metadata comment=Transcoded using Encore /tmp/123/out.mp4 -map [AUDIO-extra-0] -ss 12.1 -t 10.4 -vn audio extra -metadata comment=Transcoded using Encore /tmp/123/extra.mp4")
213+
assertThat(secondPass).isEqualTo("ffmpeg -err_detect explode -hide_banner -loglevel +level -y -f mp4 -t 22.5 -i /input/test.mp4 -ac 4 -t 22.5 -i /input/main-audio.mp4 -t 22.5 -i /input/other-audio.mp4 -filter_complex sws_flags=scaling;[0:v:1]yadif,setdar=16/9,scale=iw*sar:ih,crop=min(iw\\,ih*1/1):min(ih\\,iw/(1/1)),pad=aspect=16/9:x=(ow-iw)/2:y=(oh-ih)/2,video,filter,split=1[VIDEO-main-test-out];[VIDEO-main-test-out]video-filter[VIDEO-test-out];[1:a]join=inputs=4:channel_layout=4.0:map=0.0-FL|1.0-FR|2.0-FC|3.0-BC,audio-main,main-filter,asplit=1[AUDIO-main-test-out-0];[2:a:3]asplit=1[AUDIO-other-extra-0];[AUDIO-main-test-out-0]audio-filter[AUDIO-test-out-0];[AUDIO-other-extra-0]audio-filter-extra[AUDIO-extra-0] -map [VIDEO-test-out] -ss 12.1 -map [AUDIO-test-out-0] -ss 12.1 -t 10.4 video params audio params -metadata comment=Transcoded using Encore /tmp/123/out.mp4 -map [AUDIO-extra-0] -ss 12.1 -t 10.4 -vn audio extra -metadata comment=Transcoded using Encore /tmp/123/extra.mp4 -dec 0:v:0 -filter_complex [dec:0]thumb-filter[VIDEO-thumb] -map [VIDEO-thumb] thumb thumb -an -metadata comment=Transcoded using Encore /tmp/123/thumb.jpg")
214214
}
215215

216216
private fun output(twoPass: Boolean): Output {
@@ -234,7 +234,7 @@ internal class CommandBuilderTest {
234234
)
235235
}
236236

237-
fun audioOutput(label: String, id: String): Output {
237+
private fun audioOutput(label: String, id: String): Output {
238238
return Output(
239239
id = id,
240240
output = "$id.mp4",
@@ -248,4 +248,18 @@ internal class CommandBuilderTest {
248248
)
249249
)
250250
}
251+
252+
private fun thumbnailOutput(id: String, decodeOutputStream: String? = null): Output {
253+
return Output(
254+
id = id,
255+
output = "$id.jpg",
256+
video = VideoStreamEncode(
257+
params = listOf("thumb", id),
258+
inputLabels = listOf(DEFAULT_VIDEO_LABEL),
259+
filter = "thumb-filter",
260+
),
261+
isImage = true,
262+
decodeOutputStream = decodeOutputStream
263+
)
264+
}
251265
}

encore-common/src/test/resources/profile/multiple_inputs.yml

+2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ encodes:
6767
- type: ThumbnailMapEncode
6868
cols: 6
6969
rows: 10
70+
decodeOutput: 0
7071

7172
- type: ThumbnailEncode
73+
decodeOutput: 0
7274

7375

encore-common/src/test/resources/profile/program-x265.yml

+2
Original file line numberDiff line numberDiff line change
@@ -471,5 +471,7 @@ encodes:
471471
channelLayout: '5.1'
472472

473473
- type: ThumbnailMapEncode
474+
decodeOutput: 0
474475

475476
- type: ThumbnailEncode
477+
decodeOutput: 0

encore-common/src/test/resources/profile/program.yml

+2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ encodes:
231231
channelLayout: '5.1'
232232

233233
- type: ThumbnailMapEncode
234+
decodeOutput: 0
234235

235236
- type: ThumbnailEncode
237+
decodeOutput: 0
236238

237239

encore-common/src/test/resources/profile/test_profile_invalid.yml

+2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ encodes:
4848
suffix: STEREO
4949

5050
- type: ThumbnailEncode
51+
decodeOutput: 0
5152

5253
- type: ThumbnailMapEncode
54+
decodeOutput: 0
5355

5456
- type: AudioEncode
5557
codec: aac

encore-web/src/test/resources/profile/multiple_inputs.yml

+2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ encodes:
6767
- type: ThumbnailMapEncode
6868
cols: 6
6969
rows: 10
70+
decodeOutput: 0
7071

7172
- type: ThumbnailEncode
73+
decodeOutput: 0
7274

7375

encore-web/src/test/resources/profile/program-x265.yml

+2
Original file line numberDiff line numberDiff line change
@@ -471,5 +471,7 @@ encodes:
471471
channelLayout: '5.1'
472472

473473
- type: ThumbnailMapEncode
474+
decodeOutput: 0
474475

475476
- type: ThumbnailEncode
477+
decodeOutput: 0

encore-web/src/test/resources/profile/program.yml

+2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ encodes:
219219
channelLayout: '5.1'
220220

221221
- type: ThumbnailMapEncode
222+
decodeOutput: 0
222223

223224
- type: ThumbnailEncode
225+
decodeOutput: 0
224226

225227

0 commit comments

Comments
 (0)