Migrate Media enhancement, HDR, projection, and spatial audio snippets - #1114
barbaralaw wants to merge 5 commits into
Conversation
60e9422 to
4359abc
Compare
|
Here is the summary of changes. You are about to add 19 region tags.
This comment is generated by snippet-bot.
|
| } | ||
| // [END android_media_ai_enhancement_bitmap_viewmodel] | ||
|
|
||
| // Shims for Media Enhancement API types if not provided by standalone SDK |
There was a problem hiding this comment.
Are these classes provided by an existing google library? If so, could we use the library instead of defining shims?
| import android.widget.ImageView | ||
| import androidx.fragment.app.Fragment | ||
|
|
||
| class UltraHdrDisplayFragment : Fragment() { |
There was a problem hiding this comment.
If this is more of a Fragment snippet, I'm wondering if we need to migrate this? Is there a compose-version of this code? or is this the only way to do it?
There was a problem hiding this comment.
Thanks, these are good questions. The published Kotlin is the Views path: ImageView via view binding and requireActivity().window.colorMode. The Fragment wrapper is only there because requireActivity() is a Fragment API.
Looking into it more though, on the Overview page for this section there is a link to github resource on Displaying an Ultra HDR image in Compose. It seems to me that this section of the page needs work beyond the scope of the migration and should be added to the list of other snippets that need further work, leaving this snippet hardcoded for now. Does that sound OK?
|
Moving this back to draft while I apply the outcome of the Media legacy assessment and get an internal review. I'll address your comments and re-request your review once it's ready. Thanks for your patience! |
Alphabetize :media dependencies, rename MediaProjection.kt, replace the spatial-audio ellipsis sandwich with // ..., and fix ViewModel comment / HDR buffer indent plus Surface imports.
- Replace the compile-only shims with the published com.google.android.gms:play-services-media-effect-enhancement library, pinned to 16.0.0-beta04 (the version the get-started page documents). Where page code doesn't compile against the real API, use the real API with the smallest visible change (review feedback). - Remove the Surface-mode snapshot region. The page describes an API the library doesn't have, so that block stays hardcoded on DAC and is being reported to the page owner. - Ultra HDR: make the host Fragment private, replace the stand-in binding class with a real generated ViewBinding (new layout, viewBinding enabled in :media) and use a hidden twin for the placeholder. Rendered output is unchanged. - Make MediaProjectionActivity private. - End natural-language comments inside regions with a full stop.
4359abc to
ac35f97
Compare
Make the projection_start nullability fix visible, simplify createSession, move compile-only helpers out of the regions to the bottom of their files, and drop the unused media3 session and ui dependencies.
Summary
Extracts the Kotlin samples from eight Media guides (AI enhancement, HDR, media projection, spatial audio and Ultra HDR) into
:mediaas region-tagged source, so the guides can import them instead of hardcoding them.18 snippets across 8 pages. 4 publish exactly what the page shows. The rest differ for a reason listed below. One Surface-mode block stays hardcoded because it can't be made to compile without contradicting the page's text (see page 3).
Region tags all begin
android_media_; the lists and tables drop that prefix.Code snippets are for:
One non-Kotlin file is added because a tagged Kotlin snippet won't build without it:
media/src/main/res/layout/fragment_ultra_hdr_display.xml. The Display page's code callsbinding.imageContainer, which needs a generated view binding (FragmentUltraHdrDisplayBinding) with anImageViewwhose id isimage_container. The page's code forces only that id; the file name is our choice. The layout has no region tag and doesn't appear on the page.List of modifications
ai_enhancement_bitmap_initialize_engine:installModule()becomesinstallModule(installStatusCallback), because the published library requires a callback. 2 comments end with a full stop.ai_enhancement_bitmap_wrappers:this.createSession(...)becomescreateSession(...), because insidewithContext { }thisis theCoroutineScopeand the published code doesn't compile.ai_enhancement_bitmap_viewmodel:EnhancementOptionsuses the library's parameter names and gains one argument line. The library splits deblur/denoise and upscale into photo and video flags and has no denoise-only option, soenableDenoiseOnlyis dropped and both video flags arefalse.val optionsmoves above theifso it can be passed toprocessBitmapAsync(bitmap, options), becauseEnhancementSessionhas nodefaultOptions. Comments that sat at column 0 are indented. 4 comments end with a full stop.ai_enhancement_get_started_checks: 2 comments end with a full stop.ai_enhancement_surface_initialize_engine: the sameinstallModule(installStatusCallback)change as on the Bitmap-mode-lifecycle page. 2 comments end with a full stop.hdr_playback_check_support: trailing;dropped and indentation goes from 2 to 4 spaces (formatter). 1 comment ends with a full stop.hdr_playback_mediacodec: two declarations jammed on one line are split into two statements, because the published line doesn't compile. Trailing;and the space before(are dropped, the callback is re-wrapped so(and)sit on their own lines (its body gains one indent level), and 3-space indents, including thewhilebody, become 4 (formatter). 4 comments end with a full stop.projection_start:var mediaProjection : MediaProjectionbecomesvar mediaProjection: MediaProjection?, becausegetMediaProjection()can return null and the published assignment doesn't compile.projection_start:<br>line breaks become blank lines (formatter).projection_virtual_displayandprojection_window_context_metrics: aligned arguments get a 4-space indent and the call is re-wrapped so the closing)sits on its own line (formatter).spatial_audio_disable_channel_constraints_player,spatial_audio_disable_channel_constraints_selectorandspatial_audio_set_max_channels: builder chains are indented 4 instead of 2 spaces (formatter). The page shows.setConstrainAudioChannelCountToDeviceCapabilities(false)in bold in the first two blocks; the imported snippets show it as plain code. The selector block's bare...becomes// ....ultra_hdr_display_window_color_mode: one continuation line is indented 4 instead of 3 spaces (formatter).media/src/main/res/layout/fragment_ultra_hdr_display.xml(oneImageView, idimage_container). Required for the Kotlin snippet to compile.The per-page tables below give the same changes with the page section for each snippet.
How to read the "why" column
// ......, which Kotlin won't compile. The region publishes// ....spotlessApplynormalizes indentation to 4 spaces, drops trailing;and wraps long calls.The enhancement library
The AI-enhancement snippets now compile against the published library,
com.google.android.gms:play-services-media-effect-enhancement, instead of local compile-only shims. It's pinned to 16.0.0-beta04, the version the get-started page documents. 16.0.0-beta05 and later add an abstractEnhancementCallback.onCancelled(int)that the page's callback doesn't implement.Per page
1. Understand the media enhancement lifecycle in Bitmap mode
https://developer.android.com/media/ai-enhancement/bitmap-mode-lifecycle
3 snippets, all 3 differ.
ai_enhancement_bitmap_initialize_engineinstallModule()→installModule(installStatusCallback); the callback is a private declaration outside the snippet. 2 comments get a full stopai_enhancement_bitmap_wrappersthis.createSession(...)insidewithContext { }becomescreateSession(...)ai_enhancement_bitmap_viewmodelViewModelEnhancementOptionsuses the library's parameters (isTonemappingEnabled,isDeblurAndDenoisePhotoEnabled,isDeblurAndDenoiseVideoEnabled,isUpscalePhotoEnabled,isUpscaleVideoEnabled), which adds one line. The library splits deblur/denoise and upscale into photo and video flags and has no denoise-only option, soenableDenoiseOnlyis dropped and both video flags arefalse.val optionsmoves above theifso it can be passed toprocessBitmapAsync(bitmap, options), becauseEnhancementSessionhas nodefaultOptions. Column-0 comments are indented. 4 comments get a full stop2. Get started with Media Enhancement APIs
https://developer.android.com/media/ai-enhancement/get-started
1 snippet, differs.
ai_enhancement_get_started_checks3. Understand the media enhancement lifecycle in Surface mode
https://developer.android.com/media/ai-enhancement/surface-mode-lifecycle
1 snippet migrated, differs; 1 block stays hardcoded.
ai_enhancement_surface_initialize_engineinstallModule(installStatusCallback)change as Bitmap mode; 2 comments get a full stopKept hardcoded: the snapshot block under Process a single frame. The page's code and prose describe the app supplying the input
Surface(options.setInputSurface/setOutputSurface). In the real library, the session provides the input surface (EnhancementSession.getInputSurface()) and the output is set withEnhancementSession.setOutputSurface(Surface, EnhancementOptions, EnhancementCallback). Fixing the code would contradict the page text, so the block stays hardcoded (with a linter suppression) and is being reported to the page owner.4. Color correct with look-up tables (LUTs)
https://developer.android.com/media/grow/hdr-lut
1 snippet, matches as published:
hdr_lut_apply.5. HDR video playback
https://developer.android.com/media/grow/hdr-playback
2 snippets, both differ.
hdr_playback_check_support;dropped; indentation 2 → 4 spaces; 1 comment gets a full stophdr_playback_mediacodecval list = MediaCodecList(...) var format = MediaFormat() …;is split into two statements. Trailing;dropped; the space before(infindDecoderForFormat (format)andRuntimeException (...)removed; the callback re-wrapped so(and)sit on their own lines (its body gains one indent level); 3-space indents, including thewhilebody, become 4;onOutputFormatChangedparameters on separate lines. 4 comments get a full stop6. Media projection
https://developer.android.com/media/grow/media-projection
3 snippets, all 3 differ.
projection_startvar mediaProjection : MediaProjection→var mediaProjection: MediaProjection?. The page's<br>line breaks become blank linesprojection_virtual_display)on its own lineprojection_window_context_metricscreateWindowContext(...)split socontext.display!!and the closing)sit on their own lines;.maximumWindowMetricsindented 4 instead of 67. Spatial Audio
https://developer.android.com/media/grow/spatial-audio
6 snippets, 3 match, 3 differ.
spatial_audio_disable_channel_constraints_player.setConstrainAudioChannelCountToDeviceCapabilities(false); the imported snippet can't, so it shows as plain codespatial_audio_disable_channel_constraints_selector...becomes// ...; builder chain indented 4 instead of 2. The same bold line shows as plain code// ..., Spotless, no bold in imported codespatial_audio_set_max_channelsMatching as published:
spatial_audio_get_spatializer,spatial_audio_max_output_channels,spatial_audio_audio_format.8. Display Ultra HDR images
https://developer.android.com/media/grow/ultra-hdr/display
1 snippet, differs.
ultra_hdr_display_window_color_modeThe published Kotlin is Views-based (
binding.imageContainer,requireActivity().window.colorMode). It compiles inside a hiddenprivateFragment that inflates a real generated ViewBinding. That adds a small layout,media/src/main/res/layout/fragment_ultra_hdr_display.xml(oneImageViewwith idimage_container, which the page'sbinding.imageContainerrequires), andbuildFeatures { viewBinding = true }in:media. The page's/* Get Bitmap from Image Resource */placeholder is kept visible, and a hidden line supplies the real bitmap. A Compose version of this page is a content change for the page owner, not part of this migration.Snippets not migrated
dependenciesblocks, because they are dependency blocks. The native-library block, because it is in the Android manifest file.The Java versions of the migrated Kotlin samples (HDR LUT, HDR playback, media projection, spatial audio and Ultra HDR) aren't migrated. The paired guide-page change removes them, following Kotlin-first guidance.
Dependencies
gradle/libs.versions.toml:playServicesMediaEffectEnhancement = "16.0.0-beta04"and theplay-services-media-effect-enhancementlibrary entry.:medianow also depends onandroidx-activity-ktx,androidx-fragment-ktx,androidx-lifecycle-viewmodel-ktx,media3-common,kotlinx-coroutines-android,kotlinx-coroutines-play-servicesandplay-services-media-effect-enhancement, each used by a snippet in this PR, and enablesviewBinding.Live snippet defects this surfaced
Fixed in the migrated regions:
val list = MediaCodecList(...) var format = MediaFormat() /* media format from the container */;), which isn't valid Kotlin. The region publishes them as separate statements.this.createSession(...)sits insidewithContext(Dispatchers.Main) { }, sothisis theCoroutineScopeand the call doesn't compile. The region keeps the Main hop and publishescreateSession(...)....between theDefaultTrackSelectorsetup andbuildUponParametersisn't valid Kotlin. The region publishes// ....getMediaProjection()can return null, so assigning it to a non-nullMediaProjectiondoesn't compile. The region declaresvar mediaProjection: MediaProjection?.installModule()needs anInstallStatusCallback,EnhancementOptionshas different parameters, andEnhancementSessionhas nodefaultOptions. The regions use the real API (see page 1).Not fixed (listed for the page owner):
Notes for reviewers
isDeviceSupportedAsync()andisModuleInstalledAsync()are public extensions inGetStartedEnhancement.ktbecause they're declared inside the visibleai_enhancement_get_started_checksregion; the Bitmap and Surface files reuse them./* … */placeholder labels on the pages (for example/* flags */,/* until EOS */) are kept exactly as published, without a full stop.while (/* until EOS */) {is backed by a hiddenwhile (isStreaming) {,buffer?.put(/* write bitstream */)by a hiddenbuffer?.put(byteArrayOf())(both in HDR playback), and/* Get Bitmap from Image Resource */by a hidden bitmap load (Ultra HDR). The rendered blocks match the page.installStatusCallbackand thenotifyUi*/handleInitializationErrorstubs used by the twoinitialize_enginesnippets are private top-level declarations outside the regions.Verification
Rebased on
main../gradlew :media:spotlessCheckpasses./gradlew :media:compileDebugKotlinpasses./gradlew :media:lintDebugpassesincludecoderegion parser and compared with the live page block; the differences are exactly the ones listed above.