private static Entity.MediaEncoderSettings ToMediaEncoderSettingsEntity(IMediaEncoderSettings mediaEncoderSettings)
 {
     return new Entity.MediaEncoderSettings
                     {
                         SourceFileExtension = mediaEncoderSettings.SourceFileExtension,
                         DestinationFileExtension = mediaEncoderSettings.DestinationFileExtension,
                         EncoderArguments = mediaEncoderSettings.EncoderArguments
                     };
 }
 /// <summary>
 /// Compares the current object with another object of the same type.
 /// </summary>
 /// <param name="other">An object to compare with this object.</param>
 /// <returns>
 /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the <paramref name="other"/> parameter.Zero This object is equal to <paramref name="other"/>. Greater than zero This object is greater than <paramref name="other"/>.
 /// </returns>
 public int CompareTo(IMediaEncoderSettings other)
 {
     if (other == null)
         return 1;
     else
     {
         return Sequence.CompareTo(other.Sequence);
     }
 }
        /// <summary>
        /// Gets the target width for the optimized version of the <paramref name="mediaObject"/>. This value is applied to
        /// the {Width} replacement parameter in the encoder settings, if present. The first matching rule is returned:
        /// 1. The <paramref name="mediaObject" /> has a width meta value.
        /// 2. The width of the original file (videos only).
        /// 3. The default value for the media type (e.g. <see cref="IGallerySettings.DefaultVideoPlayerWidth" /> for video and
        /// cref="IGallerySettings.DefaultAudioPlayerWidth" /> for audio).
        /// </summary>
        /// <param name="mediaObject">The media object.</param>
        /// <param name="gallerySettings">The gallery settings.</param>
        /// <param name="encoderSetting">An instance of <see cref="IMediaEncoderSettings" />.</param>
        /// <returns>System.Int32.</returns>
        /// <exception cref="System.ComponentModel.InvalidEnumArgumentException">Thrown when the <paramref name="mediaObject" /> is not a
        /// video, audio, or generic item.</exception>
        private static int GetTargetWidth(IGalleryObject mediaObject, IGallerySettings gallerySettings, IMediaEncoderSettings encoderSetting)
        {
            IGalleryObjectMetadataItem miWidth;

            if (mediaObject.MetadataItems.TryGetMetadataItem(MetadataItemName.Width, out miWidth))
            {
                return(HelperFunctions.ParseInteger(miWidth.Value));
            }

            switch (mediaObject.GalleryObjectType)
            {
            case GalleryObjectType.Video:
                var width = FFmpeg.ParseSourceVideoWidth(FFmpeg.GetOutput(mediaObject.Original.FileNamePhysicalPath, mediaObject.GalleryId));

                return(width > int.MinValue ? width : gallerySettings.DefaultVideoPlayerWidth);

            case GalleryObjectType.Audio:
                return(gallerySettings.DefaultAudioPlayerWidth);

            case GalleryObjectType.Generic:                     // Should never hit this because we don't encode generic objects, but for completeness let's put it in
                return(gallerySettings.DefaultGenericObjectWidth);

            default:
                throw new System.ComponentModel.InvalidEnumArgumentException(String.Format("MediaConversionQueue.GetTargetWidth was not designed to handle the enum value {0}. The function must be updated.", mediaObject.GalleryObjectType));
            }
        }
        private MediaConversionSettings CreateOptimizedMediaObject(IGalleryObject mediaObject, IMediaEncoderSettings encoderSetting)
        {
            AttemptedEncoderSettings.Add(encoderSetting);

            IGallerySettings gallerySetting = Factory.LoadGallerySetting(mediaObject.GalleryId);

            // Determine file name and path of the new file.
            string optimizedPath            = HelperFunctions.MapAlbumDirectoryStructureToAlternateDirectory(mediaObject.Original.FileInfo.DirectoryName, gallerySetting.FullOptimizedPath, gallerySetting.FullMediaObjectPath);
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(mediaObject.Original.FileInfo.Name);
            string newFilename = GenerateNewFilename(optimizedPath, fileNameWithoutExtension, encoderSetting.DestinationFileExtension, gallerySetting.OptimizedFileNamePrefix);
            string newFilePath = Path.Combine(optimizedPath, newFilename);

            var mediaSettings = new MediaConversionSettings
            {
                FilePathSource      = mediaObject.Original.FileNamePhysicalPath,
                FilePathDestination = newFilePath,
                EncoderSetting      = encoderSetting,
                GalleryId           = mediaObject.GalleryId,
                MediaQueueId        = _currentMediaQueueItemId,
                TimeoutMs           = gallerySetting.MediaEncoderTimeoutMs,
                MediaObjectId       = mediaObject.Id,
                TargetWidth         = GetTargetWidth(mediaObject, gallerySetting, encoderSetting),
                TargetHeight        = GetTargetHeight(mediaObject, gallerySetting, encoderSetting),
                FFmpegArgs          = String.Empty,
                FFmpegOutput        = String.Empty,
                CancellationToken   = CancelTokenSource.Token
            };

            mediaSettings.FFmpegOutput = FFmpeg.CreateMedia(mediaSettings);
            mediaSettings.FileCreated  = ValidateFile(mediaSettings.FilePathDestination);

            if (!mediaSettings.FileCreated)
            {
                // Could not create the requested version of the file. Record the event, then try again,
                // using the next encoder setting (if one exists).
                string msg = String.Format(CultureInfo.CurrentCulture, "FAILURE: FFmpeg was not able to create file '{0}'.", Path.GetFileName(mediaSettings.FilePathDestination));
                RecordEvent(msg, mediaSettings);

                IMediaEncoderSettings nextEncoderSetting = GetEncoderSetting(mediaObject);
                if (nextEncoderSetting != null)
                {
                    return(ExecuteMediaConversion(mediaObject, nextEncoderSetting));
                }
            }

            return(mediaSettings);
        }
        /// <summary>
        /// Executes the actual media conversion, returning an object that contains settings and the
        /// results of the conversion.
        /// </summary>
        /// <param name="mediaObject">The media object.</param>
        /// <param name="encoderSetting">The encoder setting that defines the conversion parameters.</param>
        /// <returns>
        /// Returns an instance of <see cref="MediaConversionSettings"/> containing settings and
        /// results used in the conversion.
        /// </returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="mediaObject" /> or
        /// <paramref name="encoderSetting" /> is null.</exception>
        private MediaConversionSettings ExecuteMediaConversion(IGalleryObject mediaObject, IMediaEncoderSettings encoderSetting)
        {
            if (mediaObject == null)
            {
                throw new ArgumentNullException("mediaObject");
            }

            if (encoderSetting == null)
            {
                throw new ArgumentNullException("encoderSetting");
            }

            var mqi = GetCurrentMediaQueueItem();

            switch (mqi.ConversionType)
            {
            case MediaQueueItemConversionType.CreateOptimized:
                return(CreateOptimizedMediaObject(mediaObject, encoderSetting));

            case MediaQueueItemConversionType.RotateVideo:
                return(RotateVideo(mediaObject));

            default:
                throw new System.ComponentModel.InvalidEnumArgumentException(string.Format("MediaConversionQueue.ExecuteMediaConversion is not designed to handled the enumeration value {0}. It must be updated.", mqi.ConversionType));
            }
        }
        /// <summary>
        /// Executes the actual media conversion, returning an object that contains settings and the
        /// results of the conversion.
        /// </summary>
        /// <param name="mediaObject">The media object.</param>
        /// <param name="encoderSetting">The encoder setting that defines the conversion parameters.</param>
        /// <returns>
        /// Returns an instance of <see cref="MediaConversionSettings"/> containing settings and
        /// results used in the conversion.
        /// </returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="mediaObject" /> or
        /// <paramref name="encoderSetting" /> is null.</exception>
        private MediaConversionSettings ExecuteMediaConversion(IGalleryObject mediaObject, IMediaEncoderSettings encoderSetting)
        {
            if (mediaObject == null)
                throw new ArgumentNullException("mediaObject");

            if (encoderSetting == null)
                throw new ArgumentNullException("encoderSetting");

            var mqi = GetCurrentMediaQueueItem();

            switch (mqi.ConversionType)
            {
                case MediaQueueItemConversionType.CreateOptimized:
                    return CreateOptimizedMediaObject(mediaObject, encoderSetting);

                case MediaQueueItemConversionType.RotateVideo:
                    return RotateVideo(mediaObject);

                default:
                    throw new System.ComponentModel.InvalidEnumArgumentException(string.Format("MediaConversionQueue.ExecuteMediaConversion is not designed to handled the enumeration value {0}. It must be updated.", mqi.ConversionType));
            }
        }
        private MediaConversionSettings CreateOptimizedMediaObject(IGalleryObject mediaObject, IMediaEncoderSettings encoderSetting)
        {
            AttemptedEncoderSettings.Add(encoderSetting);

            IGallerySettings gallerySetting = Factory.LoadGallerySetting(mediaObject.GalleryId);

            // Determine file name and path of the new file.
            string optimizedPath = HelperFunctions.MapAlbumDirectoryStructureToAlternateDirectory(mediaObject.Original.FileInfo.DirectoryName, gallerySetting.FullOptimizedPath, gallerySetting.FullMediaObjectPath);
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(mediaObject.Original.FileInfo.Name);
            string newFilename = GenerateNewFilename(optimizedPath, fileNameWithoutExtension, encoderSetting.DestinationFileExtension, gallerySetting.OptimizedFileNamePrefix);
            string newFilePath = Path.Combine(optimizedPath, newFilename);

            var mediaSettings = new MediaConversionSettings
                                                    {
                                                        FilePathSource = mediaObject.Original.FileNamePhysicalPath,
                                                        FilePathDestination = newFilePath,
                                                        EncoderSetting = encoderSetting,
                                                        GalleryId = mediaObject.GalleryId,
                                                        MediaQueueId = _currentMediaQueueItemId,
                                                        TimeoutMs = gallerySetting.MediaEncoderTimeoutMs,
                                                        MediaObjectId = mediaObject.Id,
                                                        TargetWidth = GetTargetWidth(mediaObject, gallerySetting, encoderSetting),
                                                        TargetHeight = GetTargetHeight(mediaObject, gallerySetting, encoderSetting),
                                                        FFmpegArgs = String.Empty,
                                                        FFmpegOutput = String.Empty,
                                                        CancellationToken = CancelTokenSource.Token,
                                                        UseCustomTool=true
                                                    };

            mediaSettings.FFmpegOutput = FFmpeg.CreateMedia(mediaSettings);
            mediaSettings.FileCreated = ValidateFile(mediaSettings.FilePathDestination);

            if (!mediaSettings.FileCreated)
            {
                // Could not create the requested version of the file. Record the event, then try again,
                // using the next encoder setting (if one exists).
                string msg = String.Format(CultureInfo.CurrentCulture, "FAILURE: FFmpeg was not able to create file '{0}'.", Path.GetFileName(mediaSettings.FilePathDestination));
                RecordEvent(msg, mediaSettings);

                IMediaEncoderSettings nextEncoderSetting = GetEncoderSetting(mediaObject);
                if (nextEncoderSetting != null)
                {
                    return ExecuteMediaConversion(mediaObject, nextEncoderSetting);
                }
            }

            return mediaSettings;
        }
        /// <summary>
        /// Gets the target width for the optimized version of the <paramref name="mediaObject"/>. This value is applied to 
        /// the {Width} replacement parameter in the encoder settings, if present. The first matching rule is returned:
        /// 1. The <paramref name="mediaObject" /> has a width meta value.
        /// 2. The width of the original file (videos only).
        /// 3. The default value for the media type (e.g. <see cref="IGallerySettings.DefaultVideoPlayerWidth" /> for video and
        /// cref="IGallerySettings.DefaultAudioPlayerWidth" /> for audio).
        /// </summary>
        /// <param name="mediaObject">The media object.</param>
        /// <param name="gallerySettings">The gallery settings.</param>
        /// <param name="encoderSetting">An instance of <see cref="IMediaEncoderSettings" />.</param>
        /// <returns>System.Int32.</returns>
        /// <exception cref="System.ComponentModel.InvalidEnumArgumentException">Thrown when the <paramref name="mediaObject" /> is not a
        /// video, audio, or generic item.</exception>
        private static int GetTargetWidth(IGalleryObject mediaObject, IGallerySettings gallerySettings, IMediaEncoderSettings encoderSetting)
        {
            IGalleryObjectMetadataItem miWidth;
            if (mediaObject.MetadataItems.TryGetMetadataItem(MetadataItemName.Width, out miWidth))
            {
                return HelperFunctions.ParseInteger(miWidth.Value);
            }

            switch (mediaObject.GalleryObjectType)
            {
                case GalleryObjectType.Video:
                    var width = FFmpeg.ParseSourceVideoWidth(FFmpeg.GetOutput(mediaObject.Original.FileNamePhysicalPath, mediaObject.GalleryId));

                    return width > int.MinValue ? width : gallerySettings.DefaultVideoPlayerWidth;

                case GalleryObjectType.Audio:
                    return gallerySettings.DefaultAudioPlayerWidth;

                case GalleryObjectType.Generic: // Should never hit this because we don't encode generic objects, but for completeness let's put it in
                    return gallerySettings.DefaultGenericObjectWidth;

                default:
                    throw new System.ComponentModel.InvalidEnumArgumentException(String.Format("MediaConversionQueue.GetTargetWidth was not designed to handle the enum value {0}. The function must be updated.", mediaObject.GalleryObjectType));
            }
        }