Create a new MetricsReporter.Factory

This includes creating a new Factory for `MetricsReporter` and adding it to Transformer. This is done as we need to create a new `MetricsReporter` for each export operation, so it makes sense to have a Factory.

PiperOrigin-RevId: 727798528
(cherry picked from commit 6d408c2d31bddacb254bb0cc917e4ecd5d0e4b66)
This commit is contained in:
shahddaghash 2025-02-17 03:33:05 -08:00 committed by oceanjules
parent bb358241b9
commit e58d9120bc
2 changed files with 78 additions and 13 deletions

View File

@ -16,6 +16,7 @@
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.usToMs;
import android.content.Context;
@ -32,6 +33,7 @@ import androidx.media3.common.C;
import androidx.media3.common.ColorInfo;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.SystemClock;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@ -45,6 +47,11 @@ import java.util.List;
/** Reports the collected metrics. */
public interface MetricsReporter extends AutoCloseable {
/** Factory for metrics reporters */
interface Factory {
/** Returns a new {@link MetricsReporter}. */
MetricsReporter create();
}
/**
* Reports the given {@link EditingEndedEvent}.
@ -59,16 +66,31 @@ import java.util.List;
* EditingSession}.
*/
static final class DefaultMetricsReporter implements MetricsReporter {
/** A {@link MetricsReporter.Factory} for {@link DefaultMetricsReporter}. */
public static final class Factory implements MetricsReporter.Factory {
private final Context context;
/**
* Creates an instance.
*
* @param context The {@link Context}.
*/
public Factory(Context context) {
this.context = context;
}
@Override
public MetricsReporter create() {
return new DefaultMetricsReporter(context);
}
}
/** The {@link EditingSession} to report collected metrics to. */
@Nullable private EditingSession editingSession;
/**
* Creates an instance.
*
* @param context A {@link Context}.
*/
public DefaultMetricsReporter(Context context) {
private boolean metricsReported;
private DefaultMetricsReporter(Context context) {
@Nullable
MediaMetricsManager mediaMetricsManager =
(MediaMetricsManager) context.getSystemService(Context.MEDIA_METRICS_SERVICE);
@ -79,9 +101,10 @@ import java.util.List;
@Override
public void reportMetrics(EditingEndedEvent editingEndedEvent) {
checkState(!metricsReported, "Metrics have already been reported.");
if (editingSession != null) {
editingSession.reportEditingEndedEvent(editingEndedEvent);
close();
metricsReported = true;
}
}
@ -94,6 +117,7 @@ import java.util.List;
}
}
private static final String TAG = "EditingMetricsCollector";
// TODO: b/386328723 - Add missing error codes to EditingEndedEvent.ErrorCode.
private static final SparseIntArray ERROR_CODE_CONVERSION_MAP = new SparseIntArray();
private static final SparseIntArray DATA_SPACE_STANDARD_CONVERSION_MAP = new SparseIntArray();
@ -222,6 +246,11 @@ import java.util.List;
editingEndedEventBuilder.setOutputMediaItemInfo(getOutputMediaItemInfo(exportResult));
metricsReporter.reportMetrics(editingEndedEventBuilder.build());
try {
metricsReporter.close();
} catch (Exception e) {
Log.e(TAG, "error while closing the metrics reporter", e);
}
}
/**
@ -250,6 +279,11 @@ import java.util.List;
editingEndedEventBuilder.setOutputMediaItemInfo(getOutputMediaItemInfo(exportResult));
metricsReporter.reportMetrics(editingEndedEventBuilder.build());
try {
metricsReporter.close();
} catch (Exception e) {
Log.e(TAG, "error while closing the metrics reporter", e);
}
}
/**
@ -266,6 +300,11 @@ import java.util.List;
}
metricsReporter.reportMetrics(editingEndedEventBuilder.build());
try {
metricsReporter.close();
} catch (Exception e) {
Log.e(TAG, "error while closing the metrics reporter", e);
}
}
private EditingEndedEvent.Builder createEditingEndedEventBuilder(int finalState) {

View File

@ -122,6 +122,8 @@ public final class Transformer {
private Looper looper;
private DebugViewProvider debugViewProvider;
private Clock clock;
private EditingMetricsCollector.MetricsReporter.@MonotonicNonNull Factory
metricsReporterFactory;
/**
* Creates a builder with default values.
@ -142,6 +144,10 @@ public final class Transformer {
debugViewProvider = DebugViewProvider.NONE;
clock = Clock.DEFAULT;
listeners = new ListenerSet<>(looper, clock, (listener, flags) -> {});
if (SDK_INT >= 35) {
metricsReporterFactory =
new EditingMetricsCollector.DefaultMetricsReporter.Factory(context);
}
}
/** Creates a builder with the values of the provided {@link Transformer}. */
@ -169,6 +175,7 @@ public final class Transformer {
this.looper = transformer.looper;
this.debugViewProvider = transformer.debugViewProvider;
this.clock = transformer.clock;
this.metricsReporterFactory = transformer.metricsReporterFactory;
}
/**
@ -515,6 +522,23 @@ public final class Transformer {
return this;
}
/**
* Sets the {@link EditingMetricsCollector.MetricsReporter.Factory} that will be used to report
* the metrics.
*
* <p>The default value is {@link EditingMetricsCollector.DefaultMetricsReporter.Factory}.
*
* @param metricsReporterFactory A {@link EditingMetricsCollector.MetricsReporter.Factory}.
* @return This builder.
*/
@CanIgnoreReturnValue
@VisibleForTesting
/* package */ Builder setMetricsReporterFactory(
EditingMetricsCollector.MetricsReporter.Factory metricsReporterFactory) {
this.metricsReporterFactory = metricsReporterFactory;
return this;
}
/**
* Sets whether transformer reports diagnostics data to the Android platform.
*
@ -582,7 +606,8 @@ public final class Transformer {
muxerFactory,
looper,
debugViewProvider,
clock);
clock,
metricsReporterFactory);
}
private void checkSampleMimeType(String sampleMimeType) {
@ -772,7 +797,7 @@ public final class Transformer {
private final HandlerWrapper applicationHandler;
private final ComponentListener componentListener;
private final ExportResult.Builder exportResultBuilder;
private @MonotonicNonNull EditingMetricsCollector editingMetricsCollector;
@Nullable private final EditingMetricsCollector.MetricsReporter.Factory metricsReporterFactory;
@Nullable private TransformerInternal transformerInternal;
@Nullable private MuxerWrapper remuxingMuxerWrapper;
@ -783,6 +808,7 @@ public final class Transformer {
private TransmuxTranscodeHelper.@MonotonicNonNull ResumeMetadata resumeMetadata;
private @MonotonicNonNull ListenableFuture<TransmuxTranscodeHelper.ResumeMetadata>
getResumeMetadataFuture;
private @MonotonicNonNull EditingMetricsCollector editingMetricsCollector;
private @MonotonicNonNull ListenableFuture<Void> copyOutputFuture;
@Nullable private Mp4Info mediaItemInfo;
@Nullable private WatchdogTimer exportWatchdogTimer;
@ -808,7 +834,8 @@ public final class Transformer {
Muxer.Factory muxerFactory,
Looper looper,
DebugViewProvider debugViewProvider,
Clock clock) {
Clock clock,
@Nullable EditingMetricsCollector.MetricsReporter.Factory metricsReporterFactory) {
checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed.");
this.context = context;
this.transformationRequest = transformationRequest;
@ -831,6 +858,7 @@ public final class Transformer {
this.looper = looper;
this.debugViewProvider = debugViewProvider;
this.clock = clock;
this.metricsReporterFactory = metricsReporterFactory;
transformerState = TRANSFORMER_STATE_PROCESS_FULL_INPUT;
applicationHandler = clock.createHandler(looper, /* callback= */ null);
componentListener = new ComponentListener();
@ -1590,9 +1618,7 @@ public final class Transformer {
}
editingMetricsCollector =
new EditingMetricsCollector(
new EditingMetricsCollector.DefaultMetricsReporter(context),
EXPORTER_NAME,
muxerName);
checkNotNull(metricsReporterFactory).create(), EXPORTER_NAME, muxerName);
}
transformerInternal =
new TransformerInternal(