using MediaBrowser.Model.Extensions ;
using MediaBrowser.Model.Logging ;
using System ;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Text ;
namespace MediaBrowser.MediaEncoding.Encoder
{
public class JobLogger
{
private readonly CultureInfo _usCulture = new CultureInfo ( "en-US" ) ;
private readonly ILogger _logger ;
public JobLogger ( ILogger logger )
{
_logger = logger ;
}
public async void StartStreamingLog ( EncodingJob transcodingJob , Stream source , Stream target )
{
try
{
using ( var reader = new StreamReader ( source ) )
{
while ( ! reader . EndOfStream )
{
var line = await reader . ReadLineAsync ( ) . ConfigureAwait ( false ) ;
ParseLogLine ( line , transcodingJob ) ;
var bytes = Encoding . UTF8 . GetBytes ( Environment . NewLine + line ) ;
await target . WriteAsync ( bytes , 0 , bytes . Length ) . ConfigureAwait ( false ) ;
}
}
}
catch ( Exception ex )
{
_logger . ErrorException ( "Error reading ffmpeg log" , ex ) ;
}
}
private void ParseLogLine ( string line , EncodingJob transcodingJob )
{
float? framerate = null ;
double? percent = null ;
TimeSpan ? transcodingPosition = null ;
long? bytesTranscoded = null ;
var parts = line . Split ( ' ' ) ;
var totalMs = transcodingJob . RunTimeTicks . HasValue
? TimeSpan . FromTicks ( transcodingJob . RunTimeTicks . Value ) . TotalMilliseconds
: 0 ;
var startMs = transcodingJob . Options . StartTimeTicks . HasValue
? TimeSpan . FromTicks ( transcodingJob . Options . StartTimeTicks . Value ) . TotalMilliseconds
: 0 ;
for ( var i = 0 ; i < parts . Length ; i + + )
{
var part = parts [ i ] ;
if ( string . Equals ( part , "fps=" , StringComparison . OrdinalIgnoreCase ) & &
( i + 1 < parts . Length ) )
{
var rate = parts [ i + 1 ] ;
float val ;
if ( float . TryParse ( rate , NumberStyles . Any , _usCulture , out val ) )
{
framerate = val ;
}
}
else if ( transcodingJob . RunTimeTicks . HasValue & &
part . StartsWith ( "time=" , StringComparison . OrdinalIgnoreCase ) )
{
var time = part . Split ( new [ ] { '=' } , 2 ) . Last ( ) ;
TimeSpan val ;
if ( TimeSpan . TryParse ( time , _usCulture , out val ) )
{
var currentMs = startMs + val . TotalMilliseconds ;
var percentVal = currentMs / totalMs ;
percent = 100 * percentVal ;
transcodingPosition = val ;
}
}
else if ( part . StartsWith ( "size=" , StringComparison . OrdinalIgnoreCase ) )
{
var size = part . Split ( new [ ] { '=' } , 2 ) . Last ( ) ;
int? scale = null ;
if ( size . IndexOf ( "kb" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
{
scale = 1024 ;
size = size . Replace ( "kb" , string . Empty , StringComparison . OrdinalIgnoreCase ) ;
}
if ( scale . HasValue )
{
long val ;
if ( long . TryParse ( size , NumberStyles . Any , _usCulture , out val ) )
{
bytesTranscoded = val * scale . Value ;
}
}
}
}
if ( framerate . HasValue | | percent . HasValue )
{
transcodingJob . ReportTranscodingProgress ( transcodingPosition , framerate , percent , bytesTranscoded ) ;
}
}
}
}