fix(flv): stop recording on unsupported codec

This commit is contained in:
genteure 2022-11-23 23:33:42 +08:00
parent 07a203d46d
commit 1e8bab25d6
7 changed files with 55 additions and 59 deletions

View File

@ -12,6 +12,7 @@ using BililiveRecorder.Core.ProcessingRules;
using BililiveRecorder.Core.Scripting;
using BililiveRecorder.Flv;
using BililiveRecorder.Flv.Amf;
using BililiveRecorder.Flv.Parser;
using BililiveRecorder.Flv.Pipeline;
using BililiveRecorder.Flv.Pipeline.Actions;
using Microsoft.Extensions.DependencyInjection;
@ -134,7 +135,7 @@ namespace BililiveRecorder.Core.Recording
if (bytesRead == 0)
break;
writer.Advance(bytesRead);
Interlocked.Add(ref this.ioNetworkDownloadedBytes, bytesRead);
_ = Interlocked.Add(ref this.ioNetworkDownloadedBytes, bytesRead);
}
catch (Exception ex)
{
@ -194,6 +195,12 @@ namespace BililiveRecorder.Core.Recording
}
}
}
catch (UnsupportedCodecException ex)
{
// 直播流不是 H.264
this.logger.Warning(ex, "不支持此直播流的视频编码格式(只支持 H.264),本场直播不再自动启动录制。");
this.room.StopRecord(); // 停止自动重试
}
catch (OperationCanceledException ex)
{
this.logger.Debug(ex, "录制被取消");
@ -260,7 +267,7 @@ namespace BililiveRecorder.Core.Recording
switch (this.room.RoomConfig.CuttingMode)
{
case CuttingMode.ByTime:
if (e.FileMaxTimestamp > this.room.RoomConfig.CuttingNumber * (60u * 1000u))
if (e.FileMaxTimestamp > this.room.RoomConfig.CuttingNumber * 60u * 1000u)
this.splitFileRule.SetSplitBeforeFlag();
break;
case CuttingMode.BySize:
@ -290,7 +297,7 @@ namespace BililiveRecorder.Core.Recording
var paths = this.task.CreateFileName();
try
{ Directory.CreateDirectory(Path.GetDirectoryName(paths.fullPath)); }
{ _ = Directory.CreateDirectory(Path.GetDirectoryName(paths.fullPath)); }
catch (Exception) { }
this.last_path = paths.fullPath;
@ -307,7 +314,7 @@ namespace BililiveRecorder.Core.Recording
: Path.ChangeExtension(this.last_path, "txt");
try
{ Directory.CreateDirectory(Path.GetDirectoryName(path)); }
{ _ = Directory.CreateDirectory(Path.GetDirectoryName(path)); }
catch (Exception) { }
var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read);

View File

@ -317,7 +317,7 @@ namespace BililiveRecorder.Core
}
finally
{
this.recordRetryDelaySemaphoreSlim.Release();
_ = this.recordRetryDelaySemaphoreSlim.Release();
}
// 如果状态是非直播中,跳过重试尝试。当状态切换到直播中时会开始新的录制任务。

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Runtime.Serialization;
namespace BililiveRecorder.Flv.Parser
@ -14,4 +14,28 @@ namespace BililiveRecorder.Flv.Parser
/// <inheritdoc/>
protected FlvException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public class UnknownFlvTagTypeException : FlvException
{
public UnknownFlvTagTypeException() { }
public UnknownFlvTagTypeException(string message) : base(message) { }
public UnknownFlvTagTypeException(string message, Exception innerException) : base(message, innerException) { }
protected UnknownFlvTagTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public class NotFlvFileException : FlvException
{
public NotFlvFileException() { }
public NotFlvFileException(string message) : base(message) { }
public NotFlvFileException(string message, Exception innerException) : base(message, innerException) { }
protected NotFlvFileException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public class UnsupportedCodecException : FlvException
{
public UnsupportedCodecException() { }
public UnsupportedCodecException(string message) : base(message) { }
public UnsupportedCodecException(string message, Exception innerException) : base(message, innerException) { }
protected UnsupportedCodecException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -227,7 +227,7 @@ namespace BililiveRecorder.Flv.Parser
if (tagBodyStream.Length > 2)
{
tagBodyStream.Seek(0, SeekOrigin.Begin);
_ = tagBodyStream.Seek(0, SeekOrigin.Begin);
switch (tagType)
{
case TagType.Audio:
@ -243,8 +243,10 @@ namespace BililiveRecorder.Flv.Parser
case TagType.Video:
{
var frame = tagBodyStream.ReadByte();
if ((frame & 0x0F) != 7) // AVC
break;
throw new UnsupportedCodecException(string.Format("Unsupported Video Codec: {0}.", frame & 0x0F));
if (frame == 0x17)
tagFlag |= TagFlag.Keyframe;
var packet = tagBodyStream.ReadByte();
@ -272,7 +274,7 @@ namespace BililiveRecorder.Flv.Parser
};
// Read Tag Type Specific Data
tagBodyStream.Seek(0, SeekOrigin.Begin);
_ = tagBodyStream.Seek(0, SeekOrigin.Begin);
if (tag.Type == TagType.Script)
{
@ -320,7 +322,7 @@ namespace BililiveRecorder.Flv.Parser
}
finally
{
this.peekSemaphoreSlim.Release();
_ = this.peekSemaphoreSlim.Release();
}
}
@ -344,7 +346,7 @@ namespace BililiveRecorder.Flv.Parser
}
finally
{
this.peekSemaphoreSlim.Release();
_ = this.peekSemaphoreSlim.Release();
}
}
}

View File

@ -1,16 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace BililiveRecorder.Flv.Parser
{
public class NotFlvFileException : FlvException
{
public NotFlvFileException() { }
public NotFlvFileException(string message) : base(message) { }
public NotFlvFileException(string message, Exception innerException) : base(message, innerException) { }
protected NotFlvFileException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -1,16 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace BililiveRecorder.Flv.Parser
{
public class UnknownFlvTagTypeException : FlvException
{
public UnknownFlvTagTypeException() { }
public UnknownFlvTagTypeException(string message) : base(message) { }
public UnknownFlvTagTypeException(string message, Exception innerException) : base(message, innerException) { }
protected UnknownFlvTagTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -81,8 +81,8 @@ namespace BililiveRecorder.Flv
if (this.BinaryData != null)
{
binaryData = provider?.CreateMemoryStream(nameof(Tag) + ":" + nameof(Clone)) ?? new MemoryStream();
this.BinaryData.Seek(0, SeekOrigin.Begin);
this.BinaryData.CopyToAsync(binaryData);
_ = this.BinaryData.Seek(0, SeekOrigin.Begin);
_ = this.BinaryData.CopyToAsync(binaryData);
}
ScriptTagBody? scriptData = null;
@ -90,7 +90,7 @@ namespace BililiveRecorder.Flv
{
using var stream = provider?.CreateMemoryStream(nameof(Tag) + ":" + nameof(Clone) + ":Temp") ?? new MemoryStream();
this.ScriptData.WriteTo(stream);
stream.Seek(0, SeekOrigin.Begin);
_ = stream.Seek(0, SeekOrigin.Begin);
scriptData = ScriptTagBody.Parse(stream);
}
@ -126,7 +126,7 @@ namespace BililiveRecorder.Flv
var buffer = ArrayPool<byte>.Shared.Rent(5);
try
{
binaryData.Read(buffer, 0, 5);
_ = binaryData.Read(buffer, 0, 5);
extra.FirstBytes = BinaryConvertUtilities.ByteArrayToHexString(buffer, 0, 2);
if (this.Type == TagType.Video)
@ -176,14 +176,9 @@ namespace BililiveRecorder.Flv
{
var bytesLeft = buffer.Length - nalu.StartPosition;
if (bytesLeft >= nalu.FullSize)
{
nalu.NaluHash = BinaryConvertUtilities.ByteArrayToHexString(farmHash64.ComputeHash(buffer, nalu.StartPosition, (int)nalu.FullSize));
}
else
{
nalu.NaluHash = BinaryConvertUtilities.ByteArrayToHexString(farmHash64.ComputeHash(buffer, nalu.StartPosition, Math.Min(buffer.Length - nalu.StartPosition, (int)nalu.FullSize))) + "-PARTIAL";
}
nalu.NaluHash = bytesLeft >= nalu.FullSize
? BinaryConvertUtilities.ByteArrayToHexString(farmHash64.ComputeHash(buffer, nalu.StartPosition, (int)nalu.FullSize))
: BinaryConvertUtilities.ByteArrayToHexString(farmHash64.ComputeHash(buffer, nalu.StartPosition, Math.Min(buffer.Length - nalu.StartPosition, (int)nalu.FullSize))) + "-PARTIAL";
}
}
}
@ -229,7 +224,7 @@ namespace BililiveRecorder.Flv
{
var val = lookup32[bytes[i]];
result[2 * i] = (char)val;
result[2 * i + 1] = (char)(val >> 16);
result[(2 * i) + 1] = (char)(val >> 16);
}
return new string(result);
}
@ -245,13 +240,13 @@ namespace BililiveRecorder.Flv
internal static string StreamToHexString(Stream stream)
{
var lookup32 = _lookup32;
stream.Seek(0, SeekOrigin.Begin);
_ = stream.Seek(0, SeekOrigin.Begin);
var result = new char[stream.Length * 2];
for (var i = 0; i < stream.Length; i++)
{
var val = lookup32[stream.ReadByte()];
result[2 * i] = (char)val;
result[2 * i + 1] = (char)(val >> 16);
result[(2 * i) + 1] = (char)(val >> 16);
}
return new string(result);
}