Live streaming v2

This commit is contained in:
Isaac 2024-07-12 14:16:07 +04:00
parent 649b7e4ee6
commit b97b8c369e
5 changed files with 29 additions and 130 deletions

View File

@ -76,13 +76,15 @@
ret = AVERROR(ENOMEM);
goto end;
}
bool hasAudio = false;
for (i = 0; i < input_format_context->nb_streams; i++) {
AVStream *out_stream;
AVStream *in_stream = input_format_context->streams[i];
AVCodecParameters *in_codecpar = in_stream->codecpar;
if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO && in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
if (/*in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO && */in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
streams_list[i] = -1;
continue;
}
@ -110,6 +112,8 @@
ret = AVERROR_UNKNOWN;
goto end;
}
hasAudio = true;
// Set the codec parameters for the AAC encoder
aac_codec_context->sample_rate = in_codecpar->sample_rate;
@ -156,20 +160,22 @@
}
}
// Set up the resampling context
swr_ctx = swr_alloc_set_opts(NULL,
aac_codec_context->channel_layout, aac_codec_context->sample_fmt, aac_codec_context->sample_rate,
opus_decoder_context->channel_layout, opus_decoder_context->sample_fmt, opus_decoder_context->sample_rate,
0, NULL);
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
ret = AVERROR(ENOMEM);
goto end;
}
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
goto end;
if (hasAudio) {
// Set up the resampling context
swr_ctx = swr_alloc_set_opts(NULL,
aac_codec_context->channel_layout, aac_codec_context->sample_fmt, aac_codec_context->sample_rate,
opus_decoder_context->channel_layout, opus_decoder_context->sample_fmt, opus_decoder_context->sample_rate,
0, NULL);
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
ret = AVERROR(ENOMEM);
goto end;
}
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
goto end;
}
}
if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) {

View File

@ -75,9 +75,9 @@ public final class MediaStreamComponent: CombinedComponent {
var videoStalled: Bool = true
var videoIsPlayable: Bool {
!videoStalled && hasVideo
return true
//!videoStalled && hasVideo
}
// var wantsPiP: Bool = false
let deactivatePictureInPictureIfVisible = StoredActionSlot(Void.self)

View File

@ -806,116 +806,6 @@ private final class ProxyVideoView: UIView {
self.id = Int64.random(in: Int64.min ... Int64.max)
/*if #available(iOS 13.0, *) {
do {
let server = try HTTPServer(port: NWEndpoint.Port(integerLiteral: 8012), tcpOptions: nil, queue: .main, handler: { request, response in
if request.url == "/master.m3u8" {
let _ = (call.externalMediaStream.get()
|> take(1)
|> mapToSignal { externalMediaStream in
return externalMediaStream.masterPlaylistData()
}
|> take(1)
|> deliverOnMainQueue).start(next: { masterPlaylistData in
response.send(masterPlaylistData.data(using: .utf8)!)
})
} else if request.url == "/hls_level_0.m3u8" {
let _ = (call.externalMediaStream.get()
|> take(1)
|> mapToSignal { externalMediaStream in
return externalMediaStream.playlistData(quality: 0)
}
|> take(1)
|> deliverOnMainQueue).start(next: { playlistData in
response.send(playlistData.data(using: .utf8)!)
})
} else if request.url == "/hls_level_1.m3u8" {
let _ = (call.externalMediaStream.get()
|> take(1)
|> mapToSignal { externalMediaStream in
return externalMediaStream.playlistData(quality: 1)
}
|> take(1)
|> deliverOnMainQueue).start(next: { playlistData in
response.send(playlistData.data(using: .utf8)!)
})
} else if request.url.hasPrefix("/hls_stream0_") && request.url.hasSuffix(".ts") {
if let partIndex = Int(request.url[request.url.index(request.url.startIndex, offsetBy: "/hls_stream0_".count)..<request.url.index(request.url.endIndex, offsetBy: -".ts".count)]) {
let _ = (call.externalMediaStream.get()
|> take(1)
|> mapToSignal { externalMediaStream in
return externalMediaStream.partData(index: partIndex, quality: 0)
}
|> take(1)
|> deliverOnMainQueue).start(next: { partData in
guard let partData else {
return
}
let sourceTempFile = TempBox.shared.tempFile(fileName: "part.mp4")
let tempFile = TempBox.shared.tempFile(fileName: "part.ts")
defer {
TempBox.shared.dispose(sourceTempFile)
TempBox.shared.dispose(tempFile)
}
let _ = try? partData.write(to: URL(fileURLWithPath: sourceTempFile.path))
let sourcePath = sourceTempFile.path
FFMpegLiveMuxer.remux(sourcePath, to: tempFile.path, offsetSeconds: Double(partIndex))
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path)) {
response.send(data)
} else {
let _ = try? response.send("Error")
}
})
} else {
try response.send("Error")
}
} else if request.url.hasPrefix("/hls_stream1_") && request.url.hasSuffix(".ts") {
if let partIndex = Int(request.url[request.url.index(request.url.startIndex, offsetBy: "/hls_stream1_".count)..<request.url.index(request.url.endIndex, offsetBy: -".ts".count)]) {
let _ = (call.externalMediaStream.get()
|> take(1)
|> mapToSignal { externalMediaStream in
return externalMediaStream.partData(index: partIndex, quality: 1)
}
|> take(1)
|> deliverOnMainQueue).start(next: { partData in
guard let partData else {
return
}
let sourceTempFile = TempBox.shared.tempFile(fileName: "part.mp4")
let tempFile = TempBox.shared.tempFile(fileName: "part.ts")
defer {
TempBox.shared.dispose(sourceTempFile)
TempBox.shared.dispose(tempFile)
}
let _ = try? partData.write(to: URL(fileURLWithPath: sourceTempFile.path))
let sourcePath = sourceTempFile.path
FFMpegLiveMuxer.remux(sourcePath, to: tempFile.path, offsetSeconds: Double(partIndex))
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path)) {
response.send(data)
} else {
let _ = try? response.send("Error")
}
})
} else {
try response.send("Error")
}
} else {
try response.send("Error")
}
})
self.server = server
server.resume()
} catch let e {
print("HTTPServer start error: \(e)")
}
}*/
let assetUrl = "http://127.0.0.1:\(SharedHLSServer.shared.port)/\(call.internalId)/master.m3u8"
Logger.shared.log("MediaStreamVideoComponent", "Initializing HLS asset at \(assetUrl)")
#if DEBUG
@ -924,6 +814,7 @@ private final class ProxyVideoView: UIView {
let asset = AVURLAsset(url: URL(string: assetUrl)!, options: [:])
self.playerItem = AVPlayerItem(asset: asset)
self.player = AVPlayer(playerItem: self.playerItem)
self.player.allowsExternalPlayback = true
self.playerLayer = AVPlayerLayer(player: self.player)
super.init(frame: CGRect())

View File

@ -202,9 +202,9 @@ extension ChatControllerImpl {
}
var historyView: Signal<ChatHistoryViewUpdate, NoError>
let subject: ChatControllerSubject = .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: quote), timecode: nil)
let subject: ChatControllerSubject = .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: quote), timecode: nil, setupReply: false)
historyView = preloadedChatHistoryViewForLocation(ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: searchLocation, quote: nil), count: 50, highlight: true), id: 0), context: self.context, chatLocation: preloadChatLocation, subject: subject, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), fixedCombinedReadStates: nil, tag: nil, additionalData: [])
historyView = preloadedChatHistoryViewForLocation(ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: searchLocation, quote: nil), count: 50, highlight: true, setupReply: false), id: 0), context: self.context, chatLocation: preloadChatLocation, subject: subject, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), fixedCombinedReadStates: nil, tag: nil, additionalData: [])
var signal: Signal<(MessageIndex?, Bool), NoError>
signal = historyView

View File

@ -235,7 +235,7 @@ public final class ExternalMediaStreamingContext {
playlistData.append("hls_stream\(quality)_\(index).ts\n")
}
print("Player: updating playlist \(quality) \(minIndex) ... \(headIndex)")
//print("Player: updating playlist \(quality) \(minIndex) ... \(headIndex)")
if quality == 0 {
self.playlistData.set(.single(playlistData))
@ -393,6 +393,8 @@ public final class SharedHLSServer {
case let .failed(error):
Logger.shared.log("SharedHLSServer", "Server failed with error: \(error)")
self.listener?.cancel()
self.listener?.start(queue: self.queue.queue)
default:
break
}