Skip to content

Commit

Permalink
closes issue #216
Browse files Browse the repository at this point in the history
  • Loading branch information
mariodivece committed May 14, 2018
1 parent 2c272b9 commit 8a9cf23
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 12 deletions.
16 changes: 15 additions & 1 deletion Unosquare.FFME.Common/Decoding/SubtitleComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ internal sealed unsafe class SubtitleComponent : MediaComponent
internal SubtitleComponent(MediaContainer container, int streamIndex)
: base(container, streamIndex)
{
// placeholder. Nothing else to change here.
// Adjust the offset according to options
Delay = container.MediaOptions.SubtitlesDelay;
}

/// <summary>
/// Gets the amount of time to offset the subtitles by for this component
/// </summary>
public TimeSpan Delay { get; } = TimeSpan.Zero;

/// <summary>
/// Converts decoded, raw frame data in the frame source into a a usable frame. <br />
/// The process includes performing picture, samples or text conversions
Expand Down Expand Up @@ -50,6 +56,14 @@ public override MediaBlock MaterializeFrame(MediaFrame input, ref MediaBlock out
target.Duration = source.Duration;
target.StreamIndex = input.StreamIndex;

// Process time offsets
if (Delay != TimeSpan.Zero)
{
target.StartTime = TimeSpan.FromTicks(target.StartTime.Ticks + Delay.Ticks);
target.EndTime = TimeSpan.FromTicks(target.EndTime.Ticks + Delay.Ticks);
target.Duration = TimeSpan.FromTicks(target.EndTime.Ticks - target.StartTime.Ticks);
}

target.OriginalText.Clear();
if (source.Text.Count > 0)
target.OriginalText.AddRange(source.Text);
Expand Down
2 changes: 2 additions & 0 deletions Unosquare.FFME.Common/Decoding/VideoComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,12 @@ public override MediaBlock MaterializeFrame(MediaFrame input, ref MediaBlock out
target.SmtpeTimecode = source.SmtpeTimecode;
}

// Fill out other properties
target.CodedPictureNumber = source.CodedPictureNumber;
target.StreamIndex = source.StreamIndex;
target.ClosedCaptions = new ReadOnlyCollection<ClosedCaptions.ClosedCaptionPacket>(source.ClosedCaptions);

// Process the aspect ratio
var aspectRatio = source.Pointer->sample_aspect_ratio;
if (aspectRatio.num == 0 || aspectRatio.den == 0)
{
Expand Down
14 changes: 14 additions & 0 deletions Unosquare.FFME.Common/MediaEngine.Workers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ internal void PreloadSubtitles()
try
{
m_PreloadedSubtitles = LoadBlocks(subtitlesUrl, MediaType.Subtitle, this);

// Process and adjust subtitle delays if necessary
if (Container.MediaOptions.SubtitlesDelay != TimeSpan.Zero)
{
var delay = Container.MediaOptions.SubtitlesDelay;
for (var i = 0; i < m_PreloadedSubtitles.Count; i++)
{
var target = m_PreloadedSubtitles[i];
target.StartTime = TimeSpan.FromTicks(target.StartTime.Ticks + delay.Ticks);
target.EndTime = TimeSpan.FromTicks(target.EndTime.Ticks + delay.Ticks);
target.Duration = TimeSpan.FromTicks(target.EndTime.Ticks - target.StartTime.Ticks);
}
}

Container.MediaOptions.IsSubtitleDisabled = true;
}
catch (MediaContainerException mex)
Expand Down
7 changes: 5 additions & 2 deletions Unosquare.FFME.Common/Primitives/MediaBlockBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,11 @@ public MediaBlock Next(MediaBlock current)
{
using (Locker.AcquireReaderLock())
{
var currentIndex = PlaybackBlocks.IndexOf(current);
if (currentIndex < 0) return null;
var currentIndex = current == null && PlaybackBlocks.Count > 0 ?
0 : PlaybackBlocks.IndexOf(current);

if (currentIndex < 0)
return null;

if (currentIndex + 1 < PlaybackBlocks.Count)
return PlaybackBlocks[currentIndex + 1];
Expand Down
9 changes: 8 additions & 1 deletion Unosquare.FFME.Common/Shared/MediaOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Unosquare.FFME.Shared
{
using System;
using System.Collections.Generic;

/// <summary>
Expand All @@ -26,7 +27,13 @@ internal MediaOptions()
/// This is equivalent to the -codec Main option.
/// See: https://www.ffmpeg.org/ffmpeg-all.html#Main-options (-codec option)
/// </summary>
public Dictionary<int, string> DecoderCodec { get; } = new Dictionary<int, string>();
public Dictionary<int, string> DecoderCodec { get; } = new Dictionary<int, string>(32);

/// <summary>
/// Gets or sets the amount of time to offset the subtitles by
/// This is an FFME-only property -- Not a port of ffmpeg.
/// </summary>
public TimeSpan SubtitlesDelay { get; set; } = TimeSpan.Zero;

/// <summary>
/// Use Stream's HardwareDevices property to get a list of
Expand Down
5 changes: 5 additions & 0 deletions Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ private void OnMediaInitializing(object sender, MediaInitializingRoutedEventArgs
/// <param name="e">The <see cref="MediaOpeningRoutedEventArgs"/> instance containing the event data.</param>
private void OnMediaOpening(object sender, MediaOpeningRoutedEventArgs e)
{
// You can start off by adjusting subtitles delay
// e.Options.SubtitlesDelay = TimeSpan.FromSeconds(7); // See issue #216

// Example of automatically side-loading SRT subs
try
{
Expand All @@ -126,7 +129,9 @@ private void OnMediaOpening(object sender, MediaOpeningRoutedEventArgs e)
var subtitleStreams = e.Info.Streams.Where(kvp => kvp.Value.CodecType == AVMediaType.AVMEDIA_TYPE_SUBTITLE).Select(kvp => kvp.Value);
var englishSubtitleStream = subtitleStreams.FirstOrDefault(s => s.Language.StartsWith("en"));
if (englishSubtitleStream != null)
{
e.Options.SubtitleStream = englishSubtitleStream;
}

var videoStream = e.Options.VideoStream;
if (videoStream != null)
Expand Down
26 changes: 18 additions & 8 deletions Unosquare.FFME.Windows/Rendering/SubtitleRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,25 @@ public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
var subtitleBlock = mediaBlock as SubtitleBlock;
if (subtitleBlock == null) return;

// Save the start and end times. We will need
// them in order to make the subtitles disappear
StartTime = subtitleBlock.StartTime;
EndTime = subtitleBlock.EndTime;

// Raise the subtitles event and keep track of the text.
BlockText = MediaElement.RaiseRenderingSubtitlesEvent(subtitleBlock, clockPosition)
? string.Empty
: string.Join("\r\n", subtitleBlock.Text);
var cancelRender = MediaElement.RaiseRenderingSubtitlesEvent(subtitleBlock, clockPosition);

if (cancelRender)
{
BlockText = string.Empty;
StartTime = null;
EndTime = null;
}
else
{
// Save the block text lines to display
BlockText = string.Join("\r\n", subtitleBlock.Text);

// Save the start and end times. We will need
// them in order to make the subtitles disappear
StartTime = subtitleBlock.StartTime;
EndTime = subtitleBlock.EndTime;
}

// Call the selective update method
Update(clockPosition);
Expand Down

0 comments on commit 8a9cf23

Please sign in to comment.