Skip to content

Commit c3182a6

Browse files
committed
feat(*): mediamuxer: add experimental support for APV
1 parent da975c7 commit c3182a6

File tree

7 files changed

+176
-4
lines changed

7 files changed

+176
-4
lines changed

core/src/main/java/io/github/thibaultbee/streampack/core/elements/encoders/VideoCodecConfig.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package io.github.thibaultbee.streampack.core.elements.encoders
1818
import android.content.Context
1919
import android.media.MediaCodecInfo
2020
import android.media.MediaCodecInfo.CodecProfileLevel
21+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10
2122
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain8
2223
import android.media.MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline
2324
import android.media.MediaCodecInfo.CodecProfileLevel.AVCProfileConstrainedBaseline
@@ -309,6 +310,12 @@ open class VideoCodecConfig(
309310
)
310311
}
311312

313+
private val apvProfilePriority by lazy {
314+
listOf(
315+
APVProfile422_10
316+
)
317+
}
318+
312319
/**
313320
* Return the higher profile with the higher level
314321
*/
@@ -320,6 +327,7 @@ open class VideoCodecConfig(
320327
MediaFormat.MIMETYPE_VIDEO_VP9 -> vp9ProfilePriority
321328
MediaFormat.MIMETYPE_VIDEO_VP8 -> vp8ProfilePriority
322329
MediaFormat.MIMETYPE_VIDEO_AV1 -> av1ProfilePriority
330+
MediaFormat.MIMETYPE_VIDEO_APV -> apvProfilePriority
323331
else -> throw InvalidParameterException("Profile for $mimeType is not supported")
324332
}
325333

@@ -345,7 +353,7 @@ fun VideoCodecConfig.rotateFromNaturalOrientation(context: Context, @RotationVal
345353
rotateDegreesFromNaturalOrientation(context, rotation.rotationToDegrees)
346354

347355
/**
348-
* Rotatse video configuration to [rotationDegrees] from device natural orientation.
356+
* Rotates video configuration to [rotationDegrees] from device natural orientation.
349357
*/
350358
fun VideoCodecConfig.rotateDegreesFromNaturalOrientation(
351359
context: Context, @IntRange(from = 0, to = 359) rotationDegrees: Int

core/src/main/java/io/github/thibaultbee/streampack/core/elements/endpoints/MediaMuxerEndpoint.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class MediaMuxerEndpoint(
5353
private var numOfStreams = 0
5454

5555
override val info: IEndpoint.IEndpointInfo
56-
get() = containerType?.let { Companion.getInfo(it) }
56+
get() = containerType?.let { getInfo(it) }
5757
?: throw IllegalStateException("Endpoint is not opened")
5858

5959
override fun getInfo(type: MediaDescriptor.Type) = Companion.getInfo(type)
@@ -250,7 +250,8 @@ class MediaMuxerEndpoint(
250250
mutableListOf(
251251
MediaFormat.MIMETYPE_VIDEO_H263,
252252
MediaFormat.MIMETYPE_VIDEO_AVC,
253-
MediaFormat.MIMETYPE_VIDEO_MPEG4
253+
MediaFormat.MIMETYPE_VIDEO_MPEG4,
254+
MediaFormat.MIMETYPE_VIDEO_APV
254255
).apply {
255256
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
256257
add(MediaFormat.MIMETYPE_VIDEO_HEVC)

core/src/main/java/io/github/thibaultbee/streampack/core/elements/utils/av/video/DynamicRangeProfile.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package io.github.thibaultbee.streampack.core.elements.utils.av.video
22

33
import android.hardware.camera2.params.DynamicRangeProfiles
4+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10
5+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10
6+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10Plus
47
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10
58
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10
69
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10Plus
@@ -85,6 +88,12 @@ data class DynamicRangeProfile(val dynamicRange: Long, val transferFunction: Int
8588
AV1ProfileMain10HDR10Plus to hdr10Plus,
8689
)
8790

91+
private val apvProfilesMap = mapOf(
92+
APVProfile422_10 to hdr,
93+
APVProfile422_10HDR10 to hdr10,
94+
APVProfile422_10HDR10Plus to hdr10Plus,
95+
)
96+
8897
fun fromProfile(mimetype: String, profile: Int): DynamicRangeProfile {
8998
return when (mimetype) {
9099
MediaFormat.MIMETYPE_VIDEO_H263 -> sdr
@@ -93,6 +102,7 @@ data class DynamicRangeProfile(val dynamicRange: Long, val transferFunction: Int
93102
MediaFormat.MIMETYPE_VIDEO_VP8 -> vp8ProfilesMap[profile]
94103
MediaFormat.MIMETYPE_VIDEO_VP9 -> vp9ProfilesMap[profile]
95104
MediaFormat.MIMETYPE_VIDEO_AV1 -> av1ProfilesMap[profile]
105+
MediaFormat.MIMETYPE_VIDEO_APV -> apvProfilesMap[profile]
96106
else -> throw IllegalArgumentException("Unknown mimetype $mimetype")
97107
} ?: throw IllegalArgumentException("Profile $profile is not supported for $mimetype")
98108
}

core/src/main/java/io/github/thibaultbee/streampack/core/streamers/infos/StreamerConfigurationInfo.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ package io.github.thibaultbee.streampack.core.streamers.infos
1717

1818
import android.media.AudioFormat
1919
import android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing
20+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10
21+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10
22+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10Plus
2023
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10
2124
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10
2225
import android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10Plus
@@ -199,6 +202,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IEndpoi
199202
MediaFormat.MIMETYPE_VIDEO_VP8 -> vp8Profiles
200203
MediaFormat.MIMETYPE_VIDEO_VP9 -> vp9Profiles
201204
MediaFormat.MIMETYPE_VIDEO_AV1 -> av1Profiles
205+
MediaFormat.MIMETYPE_VIDEO_APV -> apvProfiles
202206
else -> throw InvalidParameterException("Unknown mimetype $mimeType")
203207
}
204208
val supportedProfiles = MediaCodecHelper.getProfiles(mimeType)
@@ -323,5 +327,13 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IEndpoi
323327
AV1ProfileMain10HDR10Plus
324328
)
325329
}
330+
331+
private val apvProfiles by lazy {
332+
listOf(
333+
APVProfile422_10,
334+
APVProfile422_10HDR10,
335+
APVProfile422_10HDR10Plus
336+
)
337+
}
326338
}
327339

demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/settings/SettingsFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ class SettingsFragment : PreferenceFragmentCompat() {
166166
MediaFormat.MIMETYPE_VIDEO_H263 to getString(R.string.video_encoder_h263),
167167
MediaFormat.MIMETYPE_VIDEO_VP9 to getString(R.string.video_encoder_vp9),
168168
MediaFormat.MIMETYPE_VIDEO_VP8 to getString(R.string.video_encoder_vp8),
169-
MediaFormat.MIMETYPE_VIDEO_AV1 to getString(R.string.video_encoder_av1)
169+
MediaFormat.MIMETYPE_VIDEO_AV1 to getString(R.string.video_encoder_av1),
170+
MediaFormat.MIMETYPE_VIDEO_APV to getString(R.string.video_encoder_apv)
170171
)
171172

172173
val supportedVideoEncoder = streamerInfo.video.supportedEncoders

demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/ProfileLevelDisplay.kt

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,65 @@ import android.media.MediaCodecInfo.CodecProfileLevel.AACObjectMain
1313
import android.media.MediaCodecInfo.CodecProfileLevel.AACObjectSSR
1414
import android.media.MediaCodecInfo.CodecProfileLevel.AACObjectScalable
1515
import android.media.MediaCodecInfo.CodecProfileLevel.AACObjectXHE
16+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel11Band0
17+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel11Band1
18+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel11Band2
19+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel11Band3
20+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel1Band0
21+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel1Band1
22+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel1Band2
23+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel1Band3
24+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel21Band0
25+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel21Band1
26+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel21Band2
27+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel21Band3
28+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel2Band0
29+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel2Band1
30+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel2Band2
31+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel2Band3
32+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel31Band0
33+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel31Band1
34+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel31Band2
35+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel31Band3
36+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel3Band0
37+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel3Band1
38+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel3Band2
39+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel3Band3
40+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel41Band0
41+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel41Band1
42+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel41Band2
43+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel41Band3
44+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel4Band0
45+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel4Band1
46+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel4Band2
47+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel4Band3
48+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel51Band0
49+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel51Band1
50+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel51Band2
51+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel51Band3
52+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel5Band0
53+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel5Band1
54+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel5Band2
55+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel5Band3
56+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel61Band0
57+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel61Band1
58+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel61Band2
59+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel61Band3
60+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel6Band0
61+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel6Band1
62+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel6Band2
63+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel6Band3
64+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel71Band0
65+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel71Band1
66+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel71Band2
67+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel71Band3
68+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel7Band0
69+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel7Band1
70+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel7Band2
71+
import android.media.MediaCodecInfo.CodecProfileLevel.APVLevel7Band3
72+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10
73+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10
74+
import android.media.MediaCodecInfo.CodecProfileLevel.APVProfile422_10HDR10Plus
1675
import android.media.MediaCodecInfo.CodecProfileLevel.AV1Level2
1776
import android.media.MediaCodecInfo.CodecProfileLevel.AV1Level21
1877
import android.media.MediaCodecInfo.CodecProfileLevel.AV1Level22
@@ -254,6 +313,18 @@ class ProfileLevelDisplay(private val context: Context) {
254313
}
255314
}
256315

316+
private val apvProfileNameMap =
317+
mutableMapOf<Int, String>().apply {
318+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
319+
put(APVProfile422_10, context.getString(R.string.video_profile_main10))
320+
put(APVProfile422_10HDR10, context.getString(R.string.video_profile_main10_hdr10))
321+
put(
322+
APVProfile422_10HDR10Plus,
323+
context.getString(R.string.video_profile_main10_hdr10_plus)
324+
)
325+
}
326+
}
327+
257328
private val h263LevelNameMap =
258329
mutableMapOf(
259330
H263Level10 to context.getString(R.string.video_level_10),
@@ -392,6 +463,72 @@ class ProfileLevelDisplay(private val context: Context) {
392463
}
393464
}
394465

466+
private val apvLevelNameMap =
467+
mutableMapOf<Int, String>().apply {
468+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
469+
putAll(
470+
mapOf(
471+
APVLevel11Band0 to "${context.getString(R.string.video_level_11)} Band 0",
472+
APVLevel11Band1 to "${context.getString(R.string.video_level_11)} Band 1",
473+
APVLevel11Band2 to "${context.getString(R.string.video_level_11)} Band 2",
474+
APVLevel11Band3 to "${context.getString(R.string.video_level_11)} Band 3",
475+
APVLevel1Band0 to "${context.getString(R.string.video_level_1)} Band 0",
476+
APVLevel1Band1 to "${context.getString(R.string.video_level_1)} Band 1",
477+
APVLevel1Band2 to "${context.getString(R.string.video_level_1)} Band 2",
478+
APVLevel1Band3 to "${context.getString(R.string.video_level_1)} Band 3",
479+
APVLevel21Band0 to "${context.getString(R.string.video_level_21)} Band 0",
480+
APVLevel21Band1 to "${context.getString(R.string.video_level_21)} Band 1",
481+
APVLevel21Band2 to "${context.getString(R.string.video_level_21)} Band 2",
482+
APVLevel21Band3 to "${context.getString(R.string.video_level_21)} Band 3",
483+
APVLevel2Band0 to "${context.getString(R.string.video_level_2)} Band 0",
484+
APVLevel2Band1 to "${context.getString(R.string.video_level_2)} Band 1",
485+
APVLevel2Band2 to "${context.getString(R.string.video_level_2)} Band 2",
486+
APVLevel2Band3 to "${context.getString(R.string.video_level_2)} Band 3",
487+
APVLevel31Band0 to "${context.getString(R.string.video_level_31)} Band 0",
488+
APVLevel31Band1 to "${context.getString(R.string.video_level_31)} Band 1",
489+
APVLevel31Band2 to "${context.getString(R.string.video_level_31)} Band 2",
490+
APVLevel31Band3 to "${context.getString(R.string.video_level_31)} Band 3",
491+
APVLevel3Band0 to "${context.getString(R.string.video_level_3)} Band 0",
492+
APVLevel3Band1 to "${context.getString(R.string.video_level_3)} Band 1",
493+
APVLevel3Band2 to "${context.getString(R.string.video_level_3)} Band 2",
494+
APVLevel3Band3 to "${context.getString(R.string.video_level_3)} Band 3",
495+
APVLevel41Band0 to "${context.getString(R.string.video_level_41)} Band 0",
496+
APVLevel41Band1 to "${context.getString(R.string.video_level_41)} Band 1",
497+
APVLevel41Band2 to "${context.getString(R.string.video_level_41)} Band 2",
498+
APVLevel41Band3 to "${context.getString(R.string.video_level_41)} Band 3",
499+
APVLevel4Band0 to "${context.getString(R.string.video_level_4)} Band 0",
500+
APVLevel4Band1 to "${context.getString(R.string.video_level_4)} Band 1",
501+
APVLevel4Band2 to "${context.getString(R.string.video_level_4)} Band 2",
502+
APVLevel4Band3 to "${context.getString(R.string.video_level_4)} Band 3",
503+
APVLevel51Band0 to "${context.getString(R.string.video_level_51)} Band 0",
504+
APVLevel51Band1 to "${context.getString(R.string.video_level_51)} Band 1",
505+
APVLevel51Band2 to "${context.getString(R.string.video_level_51)} Band 2",
506+
APVLevel51Band3 to "${context.getString(R.string.video_level_51)} Band 3",
507+
APVLevel5Band0 to "${context.getString(R.string.video_level_5)} Band 0",
508+
APVLevel5Band1 to "${context.getString(R.string.video_level_5)} Band 1",
509+
APVLevel5Band2 to "${context.getString(R.string.video_level_5)} Band 2",
510+
APVLevel5Band3 to "${context.getString(R.string.video_level_5)} Band 3",
511+
APVLevel61Band0 to "${context.getString(R.string.video_level_61)} Band 0",
512+
APVLevel61Band1 to "${context.getString(R.string.video_level_61)} Band 1",
513+
APVLevel61Band2 to "${context.getString(R.string.video_level_61)} Band 2",
514+
APVLevel61Band3 to "${context.getString(R.string.video_level_61)} Band 3",
515+
APVLevel6Band0 to "${context.getString(R.string.video_level_6)} Band 0",
516+
APVLevel6Band1 to "${context.getString(R.string.video_level_6)} Band 1",
517+
APVLevel6Band2 to "${context.getString(R.string.video_level_6)} Band 2",
518+
APVLevel6Band3 to "${context.getString(R.string.video_level_6)} Band 3",
519+
APVLevel71Band0 to "${context.getString(R.string.video_level_71)} Band 0",
520+
APVLevel71Band1 to "${context.getString(R.string.video_level_71)} Band 1",
521+
APVLevel71Band2 to "${context.getString(R.string.video_level_71)} Band 2",
522+
APVLevel71Band3 to "${context.getString(R.string.video_level_71)} Band 3",
523+
APVLevel7Band0 to "${context.getString(R.string.video_level_7)} Band 0",
524+
APVLevel7Band1 to "${context.getString(R.string.video_level_7)} Band 1",
525+
APVLevel7Band2 to "${context.getString(R.string.video_level_7)} Band 2",
526+
APVLevel7Band3 to "${context.getString(R.string.video_level_7)} Band 3",
527+
)
528+
)
529+
}
530+
}
531+
395532
private fun getProfileMap(mimeType: String) = when (mimeType) {
396533
MediaFormat.MIMETYPE_AUDIO_AAC -> aacProfileNameMap
397534
MediaFormat.MIMETYPE_VIDEO_H263 -> h263ProfileNameMap
@@ -400,6 +537,7 @@ class ProfileLevelDisplay(private val context: Context) {
400537
MediaFormat.MIMETYPE_VIDEO_VP9 -> vp9ProfileNameMap
401538
MediaFormat.MIMETYPE_VIDEO_VP8 -> vp8ProfileNameMap
402539
MediaFormat.MIMETYPE_VIDEO_AV1 -> av1ProfileNameMap
540+
MediaFormat.MIMETYPE_VIDEO_APV -> apvProfileNameMap
403541
else -> emptyMap()
404542
}
405543

@@ -424,6 +562,7 @@ class ProfileLevelDisplay(private val context: Context) {
424562
MediaFormat.MIMETYPE_VIDEO_VP9 -> vp9LevelNameMap
425563
MediaFormat.MIMETYPE_VIDEO_VP8 -> vp8LevelNameMap
426564
MediaFormat.MIMETYPE_VIDEO_AV1 -> av1LevelNameMap
565+
MediaFormat.MIMETYPE_VIDEO_APV -> apvLevelNameMap
427566
else -> emptyMap()
428567
}
429568

demos/camera/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
<string name="video_encoder_vp8">VP8</string>
144144
<string name="video_encoder_av1">AV1</string>
145145
<string name="video_encoder_h263">H.263</string>
146+
<string name="video_encoder_apv">APV</string>
146147
<string name="audio_encoder_aac">AAC</string>
147148
<string name="audio_encoder_opus">Opus</string>
148149

0 commit comments

Comments
 (0)