Skip to content

Commit

Permalink
uniform api and simplification for read only collections and dictiona…
Browse files Browse the repository at this point in the history
…ries. Reduction of reference creation. Also fixes loading behavior expressed in #404
  • Loading branch information
mariodivece committed Jun 24, 2019
1 parent 046585a commit 918a448
Show file tree
Hide file tree
Showing 19 changed files with 106 additions and 123 deletions.
4 changes: 2 additions & 2 deletions Unosquare.FFME.MediaElement/MediaElement.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
using Common;
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

public partial class MediaElement
{
Expand Down Expand Up @@ -81,7 +81,7 @@ public TimeSpan? RemainingDuration
/// Provides key-value pairs of the metadata contained in the media.
/// Returns null when media has not been loaded.
/// </summary>
public ReadOnlyDictionary<string, string> Metadata => MediaCore?.State.Metadata;
public IReadOnlyDictionary<string, string> Metadata => MediaCore?.State.Metadata;

/// <summary>
/// Provides stream, chapter and program info of the underlying media.
Expand Down
13 changes: 6 additions & 7 deletions Unosquare.FFME.MediaElement/Platform/ClassProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;

Expand Down Expand Up @@ -37,14 +36,14 @@ public ClassProxy(Func<PropertyInfo, bool> matchClause)
proxies[property.Name] = proxy;
}

Properties = new ReadOnlyDictionary<string, IPropertyProxy>(proxies);
PropertyNames = new ReadOnlyCollection<string>(Properties.Keys.ToArray());
ReadOnlyPropertyNames = new ReadOnlyCollection<string>(Properties
Properties = proxies;
PropertyNames = Properties.Keys.ToArray();
ReadOnlyPropertyNames = Properties
.Where(kvp => kvp.Value.CanRead && !kvp.Value.CanWrite)
.Select(kvp => kvp.Key).OrderBy(s => s).ToArray());
ReadWritePropertyNames = new ReadOnlyCollection<string>(Properties
.Select(kvp => kvp.Key).OrderBy(s => s).ToArray();
ReadWritePropertyNames = Properties
.Where(kvp => kvp.Value.CanRead && kvp.Value.CanWrite)
.Select(kvp => kvp.Key).OrderBy(s => s).ToArray());
.Select(kvp => kvp.Key).OrderBy(s => s).ToArray();
}

/// <summary>
Expand Down
8 changes: 3 additions & 5 deletions Unosquare.FFME.MediaElement/Platform/PropertyMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
Expand All @@ -24,16 +23,15 @@ internal static class PropertyMapper
/// <exception cref="KeyNotFoundException">When a property exposed by the underlying MediaCore is not mapped.</exception>
static PropertyMapper()
{
MissingPropertyMappings = new ReadOnlyCollection<string>(
MediaEngineProxy.PropertyNames
MissingPropertyMappings = MediaEngineProxy.PropertyNames
.Where(p => !MediaElementProxy.PropertyNames.Contains(p))
.ToArray());
.ToArray();
}

/// <summary>
/// Contains the property names found in the Media Engine State type, but not found in the Media Element.
/// </summary>
public static IReadOnlyCollection<string> MissingPropertyMappings { get; }
public static IReadOnlyList<string> MissingPropertyMappings { get; }

/// <summary>
/// Sets the value for the specified property name on the given instance.
Expand Down
8 changes: 4 additions & 4 deletions Unosquare.FFME.Windows/Common/RenderingSubtitlesEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public sealed class RenderingSubtitlesEventArgs : RenderingEventArgs
/// <param name="duration">The duration.</param>
/// <param name="clock">The clock.</param>
internal RenderingSubtitlesEventArgs(
List<string> text,
List<string> originalText,
IList<string> text,
IList<string> originalText,
AVSubtitleType format,
IMediaEngineState engineState,
StreamInfo stream,
Expand All @@ -42,13 +42,13 @@ internal RenderingSubtitlesEventArgs(
/// This is what the default subtitle renderer will display
/// on the screen.
/// </summary>
public List<string> Text { get; }
public IList<string> Text { get; }

/// <summary>
/// Gets the text as originally decoded including
/// all markup and formatting.
/// </summary>
public List<string> OriginalText { get; }
public IList<string> OriginalText { get; }

/// <summary>
/// Gets the type of subtitle format the original
Expand Down
6 changes: 3 additions & 3 deletions Unosquare.FFME.Windows/Common/RenderingVideoEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
using ClosedCaptions;
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

/// <summary>
/// The video rendering event arguments.
Expand All @@ -24,7 +24,7 @@ public sealed class RenderingVideoEventArgs : RenderingEventArgs
/// <param name="clock">The clock.</param>
internal RenderingVideoEventArgs(
BitmapDataBuffer bitmap,
ReadOnlyCollection<ClosedCaptionPacket> closedCaptions,
IReadOnlyList<ClosedCaptionPacket> closedCaptions,
string smtpeTimeCode,
long pictureNumber,
IMediaEngineState engineState,
Expand All @@ -49,7 +49,7 @@ internal RenderingVideoEventArgs(
/// <summary>
/// Gets the closed caption decoded packets.
/// </summary>
public ReadOnlyCollection<ClosedCaptionPacket> ClosedCaptions { get; }
public IReadOnlyList<ClosedCaptionPacket> ClosedCaptions { get; }

/// <summary>
/// Gets the display picture number (frame number).
Expand Down
4 changes: 2 additions & 2 deletions Unosquare.FFME/Common/IMediaEngineState.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Unosquare.FFME.Common
{
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

/// <summary>
/// Provides Media Engine state as read-only properties.
Expand Down Expand Up @@ -203,7 +203,7 @@ public interface IMediaEngineState
/// <summary>
/// Gets the media metadata such as title, language, etc.
/// </summary>
ReadOnlyDictionary<string, string> Metadata { get; }
IReadOnlyDictionary<string, string> Metadata { get; }

/// <summary>
/// Gets the duration of the media.
Expand Down
50 changes: 23 additions & 27 deletions Unosquare.FFME/Common/MediaInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using FFmpeg.AutoGen;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

/// <summary>
Expand All @@ -30,10 +29,10 @@ internal MediaInfo(MediaContainer container)
Duration = ic->duration != ffmpeg.AV_NOPTS_VALUE ? ic->duration.ToTimeSpan() : TimeSpan.MinValue;
BitRate = ic->bit_rate < 0 ? 0 : ic->bit_rate;

Streams = new ReadOnlyDictionary<int, StreamInfo>(ExtractStreams(ic).ToDictionary(k => k.StreamIndex, v => v));
Chapters = new ReadOnlyCollection<ChapterInfo>(ExtractChapters(ic));
Programs = new ReadOnlyCollection<ProgramInfo>(ExtractPrograms(ic, Streams));
BestStreams = new ReadOnlyDictionary<AVMediaType, StreamInfo>(FindBestStreams(ic, Streams));
Streams = ExtractStreams(ic).ToDictionary(k => k.StreamIndex, v => v);
Chapters = ExtractChapters(ic);
Programs = ExtractPrograms(ic, Streams);
BestStreams = FindBestStreams(ic, Streams);
}

#endregion
Expand All @@ -54,7 +53,7 @@ internal MediaInfo(MediaContainer container)
/// Gets the metadata for the input. This may include stuff like title, creation date, company name, etc.
/// Individual stream components, chapters and programs may contain additional metadata.
/// </summary>
public ReadOnlyDictionary<string, string> Metadata { get; }
public IReadOnlyDictionary<string, string> Metadata { get; }

/// <summary>
/// Gets the duration of the input as reported by the container format.
Expand All @@ -78,23 +77,23 @@ internal MediaInfo(MediaContainer container)
/// <summary>
/// Gets a list of chapters.
/// </summary>
public ReadOnlyCollection<ChapterInfo> Chapters { get; }
public IReadOnlyList<ChapterInfo> Chapters { get; }

/// <summary>
/// Gets a list of programs with their associated streams.
/// </summary>
public ReadOnlyCollection<ProgramInfo> Programs { get; }
public IReadOnlyList<ProgramInfo> Programs { get; }

/// <summary>
/// Gets the dictionary of stream information components by stream index.
/// </summary>
public ReadOnlyDictionary<int, StreamInfo> Streams { get; }
public IReadOnlyDictionary<int, StreamInfo> Streams { get; }

/// <summary>
/// Provides access to the best streams of each media type found in the container.
/// This uses some internal FFmpeg heuristics.
/// </summary>
public ReadOnlyDictionary<AVMediaType, StreamInfo> BestStreams { get; }
public IReadOnlyDictionary<AVMediaType, StreamInfo> BestStreams { get; }

#endregion

Expand Down Expand Up @@ -147,7 +146,7 @@ private static List<StreamInfo> ExtractStreams(AVFormatContext* inputContext)
{
StreamId = s->id,
StreamIndex = s->index,
Metadata = new ReadOnlyDictionary<string, string>(FFDictionary.ToDictionary(s->metadata)),
Metadata = FFDictionary.ToDictionary(s->metadata),
CodecType = codecContext->codec_type,
CodecTypeName = ffmpeg.av_get_media_type_string(codecContext->codec_type),
Codec = codecContext->codec_id,
Expand Down Expand Up @@ -184,11 +183,8 @@ private static List<StreamInfo> ExtractStreams(AVFormatContext* inputContext)
};

// Extract valid hardware configurations
stream.HardwareDevices = new ReadOnlyCollection<HardwareDeviceInfo>(
HardwareAccelerator.GetCompatibleDevices(stream.Codec));

stream.HardwareDecoders = new ReadOnlyCollection<string>(
GetHardwareDecoders(stream.Codec));
stream.HardwareDevices = HardwareAccelerator.GetCompatibleDevices(stream.Codec);
stream.HardwareDecoders = GetHardwareDecoders(stream.Codec);

// TODO: I chose not to include Side data but I could easily do so
// https://ffmpeg.org/doxygen/3.2/dump_8c_source.html
Expand All @@ -207,7 +203,7 @@ private static List<StreamInfo> ExtractStreams(AVFormatContext* inputContext)
/// <param name="ic">The ic.</param>
/// <param name="streams">The streams.</param>
/// <returns>The star infos.</returns>
private static Dictionary<AVMediaType, StreamInfo> FindBestStreams(AVFormatContext* ic, ReadOnlyDictionary<int, StreamInfo> streams)
private static Dictionary<AVMediaType, StreamInfo> FindBestStreams(AVFormatContext* ic, IReadOnlyDictionary<int, StreamInfo> streams)
{
// Initialize and clear all the stream indexes.
var streamIndexes = new Dictionary<AVMediaType, int>();
Expand Down Expand Up @@ -278,7 +274,7 @@ private static List<ChapterInfo> ExtractChapters(AVFormatContext* ic)
EndTime = c->end.ToTimeSpan(c->time_base),
Index = i,
ChapterId = c->id,
Metadata = new ReadOnlyDictionary<string, string>(FFDictionary.ToDictionary(c->metadata))
Metadata = FFDictionary.ToDictionary(c->metadata)
};

result.Add(chapter);
Expand All @@ -293,7 +289,7 @@ private static List<ChapterInfo> ExtractChapters(AVFormatContext* ic)
/// <param name="ic">The ic.</param>
/// <param name="streams">The streams.</param>
/// <returns>The program information.</returns>
private static List<ProgramInfo> ExtractPrograms(AVFormatContext* ic, ReadOnlyDictionary<int, StreamInfo> streams)
private static List<ProgramInfo> ExtractPrograms(AVFormatContext* ic, IReadOnlyDictionary<int, StreamInfo> streams)
{
var result = new List<ProgramInfo>(128);
if (ic->programs == null) return result;
Expand All @@ -304,7 +300,7 @@ private static List<ProgramInfo> ExtractPrograms(AVFormatContext* ic, ReadOnlyDi

var program = new ProgramInfo
{
Metadata = new ReadOnlyDictionary<string, string>(FFDictionary.ToDictionary(p->metadata)),
Metadata = FFDictionary.ToDictionary(p->metadata),
ProgramId = p->id,
ProgramNumber = p->program_num
};
Expand All @@ -317,7 +313,7 @@ private static List<ProgramInfo> ExtractPrograms(AVFormatContext* ic, ReadOnlyDi
associatedStreams.Add(streams[streamIndex]);
}

program.Streams = new ReadOnlyCollection<StreamInfo>(associatedStreams);
program.Streams = associatedStreams;

result.Add(program);
}
Expand Down Expand Up @@ -535,17 +531,17 @@ public class StreamInfo
/// <summary>
/// Gets the stream's metadata.
/// </summary>
public ReadOnlyDictionary<string, string> Metadata { get; internal set; }
public IReadOnlyDictionary<string, string> Metadata { get; internal set; }

/// <summary>
/// Gets the compatible hardware device configurations for the stream's codec.
/// </summary>
public ReadOnlyCollection<HardwareDeviceInfo> HardwareDevices { get; internal set; }
public IReadOnlyList<HardwareDeviceInfo> HardwareDevices { get; internal set; }

/// <summary>
/// Gets a list of compatible hardware decoder names.
/// </summary>
public ReadOnlyCollection<string> HardwareDecoders { get; internal set; }
public IReadOnlyList<string> HardwareDecoders { get; internal set; }

/// <summary>
/// Gets the language string from the stream's metadata.
Expand Down Expand Up @@ -582,7 +578,7 @@ public class ChapterInfo
/// <summary>
/// Gets the chapter metadata.
/// </summary>
public ReadOnlyDictionary<string, string> Metadata { get; internal set; }
public IReadOnlyDictionary<string, string> Metadata { get; internal set; }
}

/// <summary>
Expand All @@ -603,12 +599,12 @@ public class ProgramInfo
/// <summary>
/// Gets the program metadata.
/// </summary>
public ReadOnlyDictionary<string, string> Metadata { get; internal set; }
public IReadOnlyDictionary<string, string> Metadata { get; internal set; }

/// <summary>
/// Gets the associated program streams.
/// </summary>
public ReadOnlyCollection<StreamInfo> Streams { get; internal set; }
public IReadOnlyList<StreamInfo> Streams { get; internal set; }

/// <summary>
/// Gets the name of the program. Empty if unavailable.
Expand Down
13 changes: 6 additions & 7 deletions Unosquare.FFME/Container/MediaComponentSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Primitives;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;

/// <summary>
Expand All @@ -23,8 +22,8 @@ internal sealed class MediaComponentSet : IDisposable
private readonly object BufferSyncLock = new object();
private readonly AtomicBoolean m_IsDisposed = new AtomicBoolean(false);

private ReadOnlyCollection<MediaComponent> m_All = new ReadOnlyCollection<MediaComponent>(new List<MediaComponent>(0));
private ReadOnlyCollection<MediaType> m_MediaTypes = new ReadOnlyCollection<MediaType>(new List<MediaType>(0));
private IReadOnlyList<MediaComponent> m_All = new List<MediaComponent>(0);
private IReadOnlyList<MediaType> m_MediaTypes = new List<MediaType>(0);

private int m_Count;
private TimeSpan? m_PlaybackStartTime;
Expand Down Expand Up @@ -81,15 +80,15 @@ public int Count
/// <summary>
/// Gets the available component media types.
/// </summary>
public ReadOnlyCollection<MediaType> MediaTypes
public IReadOnlyList<MediaType> MediaTypes
{
get { lock (ComponentSyncLock) return m_MediaTypes; }
}

/// <summary>
/// Gets all the components in a read-only collection.
/// </summary>
public ReadOnlyCollection<MediaComponent> All
public IReadOnlyList<MediaComponent> All
{
get { lock (ComponentSyncLock) return m_All; }
}
Expand Down Expand Up @@ -541,8 +540,8 @@ private unsafe void UpdateComponentBackingFields()
allMediaTypes.Add(MediaType.Subtitle);
}

m_All = new ReadOnlyCollection<MediaComponent>(allComponents);
m_MediaTypes = new ReadOnlyCollection<MediaType>(allMediaTypes);
m_All = allComponents;
m_MediaTypes = allMediaTypes;
m_Count = allComponents.Count;

// Find Start time, duration and end time
Expand Down
Loading

0 comments on commit 918a448

Please sign in to comment.