protected override void OnCreate(Bundle savedInstanceState) { context = this; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); SetContentView(Resource.Layout.activity_main); var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar); SetSupportActionBar(toolbar); var processButton = FindViewById<Button>(Resource.Id.processButton); processButton.Click += ProcessButton_Click; _playerView = FindViewById<PlayerView>(Resource.Id.playerView); _sourceMedia = new SourceMedia(); _targetMedia = new TargetMedia(); _transformationState = new TransformationState(); _trimConfig = new TrimConfig(); _mediaTransformer = new MediaTransformer(this); var builder = new SimpleExoPlayer.Builder(this); _player = builder.Build(); _player.PlayWhenReady = true; _playerView.Player = _player; }
protected void updateSourceMedia(SourceMedia sourceMedia, Android.Net.Uri uri) { sourceMedia.uri = uri; sourceMedia.size = TranscoderUtils.GetSize(this, uri); sourceMedia.duration = getMediaDuration(uri) / 1000f; try { MediaExtractor mediaExtractor = new MediaExtractor(); mediaExtractor.SetDataSource(this, uri, null); sourceMedia.tracks = new List<MediaTrackFormat>(mediaExtractor.TrackCount); for (int track = 0; track < mediaExtractor.TrackCount; track++) { MediaFormat mediaFormat = mediaExtractor.GetTrackFormat(track); var mimeType = mediaFormat.GetString(MediaFormat.KeyMime); if (mimeType == null) { continue; } if (mimeType.StartsWith("video")) { VideoTrackFormat videoTrack = new VideoTrackFormat(track, mimeType); videoTrack.width = getInt(mediaFormat, MediaFormat.KeyWidth); videoTrack.height = getInt(mediaFormat, MediaFormat.KeyHeight); videoTrack.duration = getLong(mediaFormat, MediaFormat.KeyDuration); videoTrack.frameRate = MediaFormatUtils.GetFrameRate(mediaFormat, new Java.Lang.Integer(-1)).IntValue(); videoTrack.keyFrameInterval = MediaFormatUtils.GetIFrameInterval(mediaFormat, new Java.Lang.Integer(-1)).IntValue(); videoTrack.rotation = getInt(mediaFormat, TrackMetadataUtil.KEY_ROTATION, 0); videoTrack.bitrate = getInt(mediaFormat, MediaFormat.KeyBitRate); sourceMedia.tracks.Add(videoTrack); } else if (mimeType.StartsWith("audio")) { AudioTrackFormat audioTrack = new AudioTrackFormat(track, mimeType); audioTrack.channelCount = getInt(mediaFormat, MediaFormat.KeyChannelCount); audioTrack.samplingRate = getInt(mediaFormat, MediaFormat.KeySampleRate); audioTrack.duration = getLong(mediaFormat, MediaFormat.KeyDuration); audioTrack.bitrate = getInt(mediaFormat, MediaFormat.KeyBitRate); sourceMedia.tracks.Add(audioTrack); } else { sourceMedia.tracks.Add(new GenericTrackFormat(track, mimeType)); } } } catch (IOException ex) { System.Diagnostics.Debug.WriteLine($"Failed to extract sourceMedia: {ex.Message}"); } sourceMedia.NotifyChange(); }
private List<IGlFilter> createGlFilters(SourceMedia sourceMedia, TargetVideoTrack targetTrack, float overlayWidth, PointF position, float rotation) { List<IGlFilter> glFilters = null; if (targetTrack != null && targetTrack.overlay != null) { try { Bitmap bitmap = BitmapFactory.DecodeStream(context.ContentResolver.OpenInputStream(targetTrack.overlay)); if (bitmap != null) { float overlayHeight; VideoTrackFormat sourceVideoTrackFormat = (VideoTrackFormat)sourceMedia.tracks[targetTrack.sourceTrackIndex]; if (sourceVideoTrackFormat.rotation == 90 || sourceVideoTrackFormat.rotation == 270) { float overlayWidthPixels = overlayWidth * sourceVideoTrackFormat.height; float overlayHeightPixels = overlayWidthPixels * bitmap.Height / bitmap.Width; overlayHeight = overlayHeightPixels / sourceVideoTrackFormat.width; } else { float overlayWidthPixels = overlayWidth * sourceVideoTrackFormat.width; float overlayHeightPixels = overlayWidthPixels * bitmap.Height / bitmap.Width; overlayHeight = overlayHeightPixels / sourceVideoTrackFormat.height; } PointF size = new PointF(overlayWidth, overlayHeight); IGlFilter filter = TransformationUtil.createGlFilter(context, targetTrack.overlay, size, position, rotation); if (filter != null) { glFilters = new List<IGlFilter>(); glFilters.Add(filter); } } } catch (System.Exception err) { System.Diagnostics.Debug.WriteLine($"Failed to extract audio track metadata: {err.Message}"); } } return glFilters; }
public async void Delete(SourceMedia media) { File.Delete(media.Reference); }
public void TranscodeAudio(SourceMedia sourceMedia, TargetMedia targetMedia, TrimConfig trimConfig, TransformationState transformationState) { if (targetMedia.targetFile.Exists()) { targetMedia.targetFile.Delete(); } transformationState.requestId = UUID.RandomUUID().ToString(); /* MediaTransformationListener transformationListener = new MediaTransformationListener(context, transformationState.requestId, transformationState, targetMedia); */ MediaRange mediaRange = trimConfig.enabled ? new MediaRange( TimeUnit.Milliseconds.ToMicros((long)(trimConfig.range[0] * 1000)), TimeUnit.Milliseconds.ToMicros((long)(trimConfig.range[1] * 1000))) : new MediaRange(0, long.MaxValue); try { var targetMimeType = targetMedia.writeToWav ? "audio/raw" : "audio/mp4a-latm"; IMediaTarget mediaTarget; if (targetMedia.writeToWav) { mediaTarget = new WavMediaTarget(targetMedia.targetFile.Path); } else { mediaTarget = new MediaMuxerMediaTarget(targetMedia.targetFile.Path, 1, 0, (int)MuxerOutputType.Mpeg4); } var mediaSource = new MediaExtractorMediaSource(context, sourceMedia.uri, mediaRange); List<TrackTransform> trackTransforms = new List<TrackTransform>(1); foreach (TargetTrack targetTrack in targetMedia.tracks) { if (targetTrack.format is AudioTrackFormat trackFormat) { MediaFormat mediaFormat = MediaFormat.CreateAudioFormat( targetMimeType, trackFormat.samplingRate, trackFormat.channelCount); mediaFormat.SetInteger(MediaFormat.KeyBitRate, trackFormat.bitrate); mediaFormat.SetLong(MediaFormat.KeyDuration, trackFormat.duration); IEncoder encoder; if (targetMedia.writeToWav) { encoder = new PassthroughBufferEncoder(8192); } else { encoder = new MediaCodecEncoder(); } //IEncoder encoder = targetMedia.writeToWav ? new PassthroughBufferEncoder(8192) : new MediaCodecEncoder(); TrackTransform trackTransform = new TrackTransform.Builder(mediaSource, targetTrack.sourceTrackIndex, mediaTarget) .SetTargetTrack(0) .SetDecoder(new MediaCodecDecoder()) .SetEncoder(encoder) .SetRenderer(new AudioRenderer(encoder)) .SetTargetFormat(mediaFormat) .Build(); trackTransforms.Add(trackTransform); break; } } _mediaTransformer.Transform( transformationState.requestId, trackTransforms, this, MediaTransformer.GranularityDefault); } catch (System.Exception err) { System.Diagnostics.Debug.WriteLine($"Exception when trying to transcode audio: {err.Message}"); } }
void ApplyWatermark(SourceMedia sourceMedia, TargetMedia targetMedia, TrimConfig trimConfig, TransformationState transformationState) { if (targetMedia.targetFile.Exists()) { targetMedia.targetFile.Delete(); } transformationState.requestId = UUID.RandomUUID().ToString(); /* MediaTransformationListener transformationListener = new MediaTransformationListener(this, transformationState.requestId, transformationState, targetMedia); */ var resourceId = Resource.Drawable.test_image_1; var watermarkUri = new Uri.Builder() .Scheme(ContentResolver.SchemeAndroidResource) .Authority(Resources.GetResourcePackageName(resourceId)) .AppendPath(Resources.GetResourceTypeName(resourceId)) .AppendPath(Resources.GetResourceEntryName(resourceId)) .Build(); List<IGlFilter> watermarkImageFilter = null; foreach (TargetTrack targetTrack in targetMedia.tracks) { if (targetTrack is TargetVideoTrack targetVideoTrack) { targetVideoTrack.overlay = watermarkUri; watermarkImageFilter = createGlFilters( sourceMedia, (TargetVideoTrack)targetTrack, 0.2f, new PointF(0.8f, 0.8f), 0); break; } } MediaRange mediaRange = trimConfig.enabled ? new MediaRange( TimeUnit.Milliseconds.ToMicros((long)(trimConfig.range[0] * 1000)), TimeUnit.Milliseconds.ToMicros((long)(trimConfig.range[1] * 1000))) : new MediaRange(0, long.MaxValue); TransformationOptions transformationOptions = new TransformationOptions.Builder() .SetGranularity(MediaTransformer.GranularityDefault) .SetVideoFilters(watermarkImageFilter) .SetSourceMediaRange(mediaRange) .Build(); _mediaTransformer.Transform( _transformationState.requestId, _sourceMedia.uri, targetMedia.targetFile.Path, null, null, this, transformationOptions); }
private bool _do() { AddOutputMessage($"Operation {Title} started"); StartTime = DateTime.UtcNow; OperationStatus = FileOperationStatus.InProgress; switch (Kind) { case TFileOperationKind.None: return(true); case TFileOperationKind.Convert: case TFileOperationKind.Export: throw new InvalidOperationException("Invalid operation kind"); case TFileOperationKind.Copy: if (_sourceMedia != null && File.Exists(_sourceMedia.FullPath) && Directory.Exists(DestDirectory.Folder)) { try { CreateDestMediaIfNotExists(); if (!(_destMedia.FileExists() && File.GetLastWriteTimeUtc(_sourceMedia.FullPath).Equals(File.GetLastWriteTimeUtc(_destMedia.FullPath)) && File.GetCreationTimeUtc(_sourceMedia.FullPath).Equals(File.GetCreationTimeUtc(_destMedia.FullPath)) && SourceMedia.FileSize.Equals(_destMedia.FileSize))) { _destMedia.MediaStatus = TMediaStatus.Copying; IsIndeterminate = true; if (!((Media)SourceMedia).CopyMediaTo((Media)_destMedia, ref _aborted)) { return(false); } } _destMedia.MediaStatus = TMediaStatus.Copied; ThreadPool.QueueUserWorkItem(o => ((Media)_destMedia).Verify()); AddOutputMessage($"Copy operation {Title} finished"); return(true); } catch (Exception e) { AddOutputMessage($"Copy operation {Title} failed with {e.Message}"); } } return(false); case TFileOperationKind.Delete: try { if (SourceMedia.Delete()) { AddOutputMessage($"Delete operation {Title} finished"); return(true); } } catch (Exception e) { AddOutputMessage($"Delete operation {Title} failed with {e.Message}"); } return(false); case TFileOperationKind.Move: if (File.Exists(_sourceMedia.FullPath) && Directory.Exists(DestDirectory.Folder)) { try { CreateDestMediaIfNotExists(); if (_destMedia.FileExists()) { if (File.GetLastWriteTimeUtc(_sourceMedia.FullPath).Equals(File.GetLastWriteTimeUtc(_destMedia.FullPath)) && File.GetCreationTimeUtc(_sourceMedia.FullPath).Equals(File.GetCreationTimeUtc(_destMedia.FullPath)) && _sourceMedia.FileSize.Equals(_destMedia.FileSize)) { _sourceMedia.Delete(); return(true); } else if (!_destMedia.Delete()) { AddOutputMessage("Move operation failed - destination media not deleted"); return(false); } } IsIndeterminate = true; _destMedia.MediaStatus = TMediaStatus.Copying; FileUtils.CreateDirectoryIfNotExists(Path.GetDirectoryName(_destMedia.FullPath)); File.Move(_sourceMedia.FullPath, _destMedia.FullPath); File.SetCreationTimeUtc(_destMedia.FullPath, File.GetCreationTimeUtc(_sourceMedia.FullPath)); File.SetLastWriteTimeUtc(_destMedia.FullPath, File.GetLastWriteTimeUtc(_sourceMedia.FullPath)); _destMedia.MediaStatus = TMediaStatus.Copied; ThreadPool.QueueUserWorkItem(o => ((Media)_destMedia).Verify()); AddOutputMessage("Move operation finished"); Debug.WriteLine(this, "File operation succeed"); return(true); } catch (Exception e) { AddOutputMessage($"Move operation {Title} failed with {e.Message}"); } } return(false); default: return(false); } }