Implement basic Metrics Collector in Transformer

Added a new `EditingMediaMetrics` class that interacts with the platform's `MediaMetricsManager` through an `EditingSession` created when export starts.

Currently, only the `finalState` of the export event is reported to the `EditingSession`. Future changes will collect additional metrics based on the export operation's output.

PiperOrigin-RevId: 711721801
This commit is contained in:
shahddaghash 2025-01-03 05:24:35 -08:00 committed by Copybara-Service
parent 9b71f2a3ba
commit cd5d5bde27
2 changed files with 101 additions and 0 deletions

View File

@ -0,0 +1,83 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import android.content.Context;
import android.media.metrics.EditingEndedEvent;
import android.media.metrics.EditingSession;
import android.media.metrics.MediaMetricsManager;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A metrics collector that collects editing events and forwards them to an {@link EditingSession}
* created by {@link MediaMetricsManager}.
*/
@RequiresApi(35)
/* package */ final class EditingMetricsCollector {
private @MonotonicNonNull EditingSession editingSession;
/**
* Creates an instance.
*
* <p>A new instance must be created before starting a new export.
*
* @param context The {@link Context}.
*/
public EditingMetricsCollector(Context context) {
@Nullable
MediaMetricsManager mediaMetricsManager =
(MediaMetricsManager) context.getSystemService(Context.MEDIA_METRICS_SERVICE);
if (mediaMetricsManager != null) {
editingSession = checkNotNull(mediaMetricsManager.createEditingSession());
}
}
/** Called when export completes with success. */
public void onExportSuccess() {
if (editingSession == null) {
return;
}
editingSession.reportEditingEndedEvent(
new EditingEndedEvent.Builder(EditingEndedEvent.FINAL_STATE_SUCCEEDED).build());
editingSession.close();
}
/** Called when export completes with an error. */
public void onExportError() {
if (editingSession == null) {
return;
}
editingSession.reportEditingEndedEvent(
new EditingEndedEvent.Builder(EditingEndedEvent.FINAL_STATE_ERROR).build());
editingSession.close();
}
/** Called when export is cancelled. */
public void onExportCancelled() {
if (editingSession == null) {
return;
}
editingSession.reportEditingEndedEvent(
new EditingEndedEvent.Builder(EditingEndedEvent.FINAL_STATE_CANCELED).build());
editingSession.close();
}
}

View File

@ -19,6 +19,7 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.SDK_INT;
import static androidx.media3.common.util.Util.isRunningOnEmulator;
import static androidx.media3.extractor.AacUtil.AAC_LC_AUDIO_SAMPLE_COUNT;
import static androidx.media3.transformer.ExportException.ERROR_CODE_MUXING_APPEND;
@ -771,6 +772,7 @@ public final class Transformer {
private final HandlerWrapper applicationHandler;
private final ComponentListener componentListener;
private final ExportResult.Builder exportResultBuilder;
private @MonotonicNonNull EditingMetricsCollector editingMetricsCollector;
@Nullable private TransformerInternal transformerInternal;
@Nullable private MuxerWrapper remuxingMuxerWrapper;
@ -1168,6 +1170,9 @@ public final class Transformer {
} finally {
transformerInternal = null;
}
if (canCollectEditingMetrics()) {
checkNotNull(editingMetricsCollector).onExportCancelled();
}
if (getResumeMetadataFuture != null && !getResumeMetadataFuture.isDone()) {
getResumeMetadataFuture.cancel(/* mayInterruptIfRunning= */ false);
@ -1542,6 +1547,10 @@ public final class Transformer {
}
}
private boolean canCollectEditingMetrics() {
return SDK_INT >= 35 && usePlatformDiagnostics;
}
private void startInternal(
Composition composition,
MuxerWrapper muxerWrapper,
@ -1563,6 +1572,9 @@ public final class Transformer {
context, new DefaultDecoderFactory.Builder(context).build(), clock);
}
DebugTraceUtil.reset();
if (canCollectEditingMetrics()) {
editingMetricsCollector = new EditingMetricsCollector(context);
}
transformerInternal =
new TransformerInternal(
context,
@ -1590,6 +1602,9 @@ public final class Transformer {
/* eventFlag= */ C.INDEX_UNSET,
listener -> listener.onCompleted(checkNotNull(composition), exportResultBuilder.build()));
listeners.flushEvents();
if (canCollectEditingMetrics()) {
checkNotNull(editingMetricsCollector).onExportSuccess();
}
transformerState = TRANSFORMER_STATE_PROCESS_FULL_INPUT;
}
@ -1600,6 +1615,9 @@ public final class Transformer {
listener ->
listener.onError(checkNotNull(composition), exportResultBuilder.build(), exception));
listeners.flushEvents();
if (canCollectEditingMetrics()) {
checkNotNull(editingMetricsCollector).onExportError();
}
transformerState = TRANSFORMER_STATE_PROCESS_FULL_INPUT;
}