Skip to content

Commit

Permalink
Merge pull request #1429 from shogo4405/feature/fixed-1423
Browse files Browse the repository at this point in the history
Allow dynamic changes of format description.
  • Loading branch information
shogo4405 authored Apr 23, 2024
2 parents 78a945a + cbf1ed9 commit 7fb91c4
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 20 deletions.
4 changes: 4 additions & 0 deletions HaishinKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@
BCA3A5252BC4ED220083BBB1 /* RTMPTimestamp.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCA3A5242BC4ED220083BBB1 /* RTMPTimestamp.swift */; };
BCA3A5272BC507880083BBB1 /* RTMPTimestampTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCA3A5262BC507880083BBB1 /* RTMPTimestampTests.swift */; };
BCA7C24F2A91AA0500882D85 /* IOStreamRecorderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCA7C24E2A91AA0500882D85 /* IOStreamRecorderTests.swift */; };
BCABED082BD8286400CC7E73 /* change_video_resolution.ts in Resources */ = {isa = PBXBuildFile; fileRef = BCABED072BD8284800CC7E73 /* change_video_resolution.ts */; };
BCB976DF26107B5600C9A649 /* TSField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB976DE26107B5600C9A649 /* TSField.swift */; };
BCB9773F2621812800C9A649 /* AVCFormatStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB9773E2621812800C9A649 /* AVCFormatStream.swift */; };
BCC1A72B264FAC1800661156 /* ESSpecificData.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCC1A72A264FAC1800661156 /* ESSpecificData.swift */; };
Expand Down Expand Up @@ -644,6 +645,7 @@
BCA3A5242BC4ED220083BBB1 /* RTMPTimestamp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTMPTimestamp.swift; sourceTree = "<group>"; };
BCA3A5262BC507880083BBB1 /* RTMPTimestampTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTMPTimestampTests.swift; sourceTree = "<group>"; };
BCA7C24E2A91AA0500882D85 /* IOStreamRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOStreamRecorderTests.swift; sourceTree = "<group>"; };
BCABED072BD8284800CC7E73 /* change_video_resolution.ts */ = {isa = PBXFileReference; explicitFileType = video.quicktime; fileEncoding = 4; path = change_video_resolution.ts; sourceTree = "<group>"; };
BCB976DE26107B5600C9A649 /* TSField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSField.swift; sourceTree = "<group>"; };
BCB9773E2621812800C9A649 /* AVCFormatStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVCFormatStream.swift; sourceTree = "<group>"; };
BCC1A72A264FAC1800661156 /* ESSpecificData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESSpecificData.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -865,6 +867,7 @@
291C2AD11CE9FF3E006F042B /* Asset */ = {
isa = PBXGroup;
children = (
BCABED072BD8284800CC7E73 /* change_video_resolution.ts */,
29B876D71CD70CE700FC07DA /* SampleVideo_360x240_5mb */,
294637A91EC8A79F008EEC71 /* SampleVideo_360x240_5mb.flv */,
29B876D81CD70CE700FC07DA /* SampleVideo_360x240_5mb.m3u8 */,
Expand Down Expand Up @@ -1585,6 +1588,7 @@
files = (
BCFF640B29C0C44B004EFF2F /* SampleVideo_360x240_5mb_2ch.ts in Resources */,
294637AA1EC8A79F008EEC71 /* SampleVideo_360x240_5mb.flv in Resources */,
BCABED082BD8286400CC7E73 /* change_video_resolution.ts in Resources */,
29798E751CE614FE00F5CBD0 /* SampleVideo_360x240_5mb in Resources */,
29798E761CE614FE00F5CBD0 /* SampleVideo_360x240_5mb.m3u8 in Resources */,
29798E771CE614FE00F5CBD0 /* SampleVideo_360x240_5mb.mp4 in Resources */,
Expand Down
5 changes: 3 additions & 2 deletions Sources/Codec/VideoCodec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,16 @@ final class VideoCodec<T: VideoCodecDelegate> {
private var startedAt: CMTime = .zero
private(set) var inputFormat: CMFormatDescription? {
didSet {
guard !CMFormatDescriptionEqual(inputFormat, otherFormatDescription: oldValue) else {
guard inputFormat != oldValue else {
return
}
invalidateSession = true
outputFormat = nil
}
}
private(set) var outputFormat: CMFormatDescription? {
didSet {
guard !CMFormatDescriptionEqual(outputFormat, otherFormatDescription: oldValue) else {
guard outputFormat != oldValue else {
return
}
delegate?.videoCodec(self, didOutput: outputFormat)
Expand Down
2 changes: 1 addition & 1 deletion Sources/ISO/ESSpecificData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum ESStreamType: UInt8 {
}
}

struct ESSpecificData {
struct ESSpecificData: Equatable {
static let fixedHeaderSize: Int = 5

var streamType: ESStreamType = .unspecific
Expand Down
13 changes: 6 additions & 7 deletions Sources/ISO/TSReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class TSReader<T: TSReaderDelegate> {
}
private var pmt: [UInt16: TSProgramMap] = [:] {
didSet {
for (_, pmt) in pmt {
for data in pmt.elementaryStreamSpecificData {
for pmt in pmt.values {
for data in pmt.elementaryStreamSpecificData where esSpecData[data.elementaryPID] != data {
esSpecData[data.elementaryPID] = data
}
}
Expand Down Expand Up @@ -103,11 +103,10 @@ public class TSReader<T: TSReaderDelegate> {
defer {
packetizedElementaryStreams[id] = nil
}
if formatDescriptions[id] == nil {
formatDescriptions[id] = makeFormatDescription(data, pes: pes)
if let formatDescription = formatDescriptions[id] {
delegate?.reader(self, id: id, didRead: formatDescription)
}
let formatDescription = makeFormatDescription(data, pes: pes)
if let formatDescription, formatDescriptions[id] != formatDescription {
formatDescriptions[id] = formatDescription
delegate?.reader(self, id: id, didRead: formatDescription)
}
var isNotSync = true
switch data.streamType {
Expand Down
Binary file added Tests/Asset/change_video_resolution.ts
Binary file not shown.
48 changes: 38 additions & 10 deletions Tests/ISO/TSReaderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,71 @@ final class TSReaderTests: XCTestCase {
let bundle = Bundle(for: type(of: self))
let url = URL(fileURLWithPath: bundle.path(forResource: "SampleVideo_360x240_5mb_2ch", ofType: "ts")!)
do {
let readerDelegate = TSReaderAudioCodec()
let readerDelegate = TSReaderTestsResult()
let fileHandle = try FileHandle(forReadingFrom: url)
let reader = TSReader<TSReaderAudioCodec>()
let reader = TSReader<TSReaderTestsResult>()
reader.delegate = readerDelegate
_ = reader.read(fileHandle.readDataToEndOfFile())
} catch {
}
}

func testTSFileRead_changeResolution() {
let bundle = Bundle(for: type(of: self))
let url = URL(fileURLWithPath: bundle.path(forResource: "change_video_resolution", ofType: "ts")!)
do {
let readerDelegate = TSReaderTestsResult()
let fileHandle = try FileHandle(forReadingFrom: url)
let reader = TSReader<TSReaderTestsResult>()
reader.delegate = readerDelegate
_ = reader.read(fileHandle.readDataToEndOfFile())
XCTAssertEqual(readerDelegate.videoFormats[0].dimensions.width, 640)
XCTAssertEqual(readerDelegate.videoFormats[0].dimensions.height, 360)
XCTAssertEqual(readerDelegate.videoFormats[1].dimensions.width, 1280)
XCTAssertEqual(readerDelegate.videoFormats[1].dimensions.height, 720)
XCTAssertEqual(readerDelegate.videoFormats[2].dimensions.width, 1920)
XCTAssertEqual(readerDelegate.videoFormats[2].dimensions.height, 1080)
} catch {
}
}
}

private final class TSReaderAudioCodec: TSReaderDelegate, AudioCodecDelegate {
private var audioCodec: HaishinKit.AudioCodec<TSReaderAudioCodec> = .init(lockQueue: DispatchQueue(label: "TSReaderAudioCodec"))
private final class TSReaderTestsResult: TSReaderDelegate, AudioCodecDelegate {
private var audioCodec: HaishinKit.AudioCodec<TSReaderTestsResult> = .init(lockQueue: DispatchQueue(label: "TSReaderAudioCodec"))

var videoFormats: [CMFormatDescription] = []

init() {
audioCodec.delegate = self
audioCodec.settings.format = .pcm
audioCodec.startRunning()
}

func reader(_ reader: TSReader<TSReaderAudioCodec>, id: UInt16, didRead formatDescription: CMFormatDescription) {
audioCodec.inputFormat = AVAudioFormat(cmAudioFormatDescription: formatDescription)
func reader(_ reader: TSReader<TSReaderTestsResult>, id: UInt16, didRead formatDescription: CMFormatDescription) {
switch formatDescription.mediaType {
case .audio:
audioCodec.inputFormat = AVAudioFormat(cmAudioFormatDescription: formatDescription)
case .video:
videoFormats.append(formatDescription)
default:
break
}
}

func reader(_ reader: TSReader<TSReaderAudioCodec>, id: UInt16, didRead sampleBuffer: CMSampleBuffer) {
func reader(_ reader: TSReader<TSReaderTestsResult>, id: UInt16, didRead sampleBuffer: CMSampleBuffer) {
if sampleBuffer.formatDescription?.mediaType == .audio {
audioCodec.append(sampleBuffer)
}
}

func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderAudioCodec>, didOutput outputFormat: AVAudioFormat?) {
func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderTestsResult>, didOutput outputFormat: AVAudioFormat?) {
}

func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderAudioCodec>, errorOccurred error: HaishinKit.IOAudioUnitError) {
func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderTestsResult>, errorOccurred error: HaishinKit.IOAudioUnitError) {
// XCTFail()
}

func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderAudioCodec>, didOutput audioBuffer: AVAudioBuffer, when: AVAudioTime) {
func audioCodec(_ codec: HaishinKit.AudioCodec<TSReaderTestsResult>, didOutput audioBuffer: AVAudioBuffer, when: AVAudioTime) {
}
}

0 comments on commit 7fb91c4

Please sign in to comment.