mirror of https://github.com/procxx/kepka.git
				
				
				
			Send packets for processing in batches.
This commit is contained in:
		
							parent
							
								
									c4319a7370
								
							
						
					
					
						commit
						f51f133832
					
				|  | @ -1188,7 +1188,7 @@ void Gif::createStreamedPlayer() { | ||||||
| 	if (_streamed->instance.ready()) { | 	if (_streamed->instance.ready()) { | ||||||
| 		streamingReady(base::duplicate(_streamed->instance.info())); | 		streamingReady(base::duplicate(_streamed->instance.info())); | ||||||
| 	} | 	} | ||||||
| 	startStreamedPlayer(); | 	checkStreamedIsStarted(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Gif::startStreamedPlayer() const { | void Gif::startStreamedPlayer() const { | ||||||
|  |  | ||||||
|  | @ -33,7 +33,11 @@ void Loaders::feedFromExternal(ExternalSoundPart &&part) { | ||||||
| 		QMutexLocker lock(&_fromExternalMutex); | 		QMutexLocker lock(&_fromExternalMutex); | ||||||
| 		invoke = _fromExternalQueues.empty() | 		invoke = _fromExternalQueues.empty() | ||||||
| 			&& _fromExternalForceToBuffer.empty(); | 			&& _fromExternalForceToBuffer.empty(); | ||||||
| 		_fromExternalQueues[part.audio].push_back(std::move(part.packet)); | 		auto &queue = _fromExternalQueues[part.audio]; | ||||||
|  | 		queue.insert( | ||||||
|  | 			end(queue), | ||||||
|  | 			std::make_move_iterator(part.packets.begin()), | ||||||
|  | 			std::make_move_iterator(part.packets.end())); | ||||||
| 	} | 	} | ||||||
| 	if (invoke) { | 	if (invoke) { | ||||||
| 		_fromExternalNotify.call(); | 		_fromExternalNotify.call(); | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ struct ExternalSoundData { | ||||||
| 
 | 
 | ||||||
| struct ExternalSoundPart { | struct ExternalSoundPart { | ||||||
| 	AudioMsgId audio; | 	AudioMsgId audio; | ||||||
| 	FFmpeg::Packet packet; | 	gsl::span<FFmpeg::Packet> packets; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ChildFFMpegLoader : public AbstractAudioFFMpegLoader { | class ChildFFMpegLoader : public AbstractAudioFFMpegLoader { | ||||||
|  |  | ||||||
|  | @ -490,9 +490,10 @@ FFMpegReaderImplementation::PacketResult FFMpegReaderImplementation::readPacket( | ||||||
| 		if (res == AVERROR_EOF) { | 		if (res == AVERROR_EOF) { | ||||||
| 			if (_audioStreamId >= 0) { | 			if (_audioStreamId >= 0) { | ||||||
| 				// queue terminating packet to audio player
 | 				// queue terminating packet to audio player
 | ||||||
|  | 				auto empty = FFmpeg::Packet(); | ||||||
| 				Player::mixer()->feedFromExternal({ | 				Player::mixer()->feedFromExternal({ | ||||||
| 					_audioMsgId, | 					_audioMsgId, | ||||||
| 					FFmpeg::Packet() | 					gsl::make_span(&empty, 1) | ||||||
| 				}); | 				}); | ||||||
| 			} | 			} | ||||||
| 			return PacketResult::EndOfFile; | 			return PacketResult::EndOfFile; | ||||||
|  | @ -519,7 +520,7 @@ void FFMpegReaderImplementation::processPacket(FFmpeg::Packet &&packet) { | ||||||
| 			// queue packet to audio player
 | 			// queue packet to audio player
 | ||||||
| 			Player::mixer()->feedFromExternal({ | 			Player::mixer()->feedFromExternal({ | ||||||
| 				_audioMsgId, | 				_audioMsgId, | ||||||
| 				std::move(packet) | 				gsl::make_span(&packet, 1) | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -47,14 +47,21 @@ crl::time AudioTrack::streamDuration() const { | ||||||
| 	return _stream.duration; | 	return _stream.duration; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AudioTrack::process(FFmpeg::Packet &&packet) { | void AudioTrack::process(std::vector<FFmpeg::Packet> &&packets) { | ||||||
| 	if (packet.empty()) { | 	if (packets.empty()) { | ||||||
|  | 		return; | ||||||
|  | 	} else if (packets.front().empty()) { | ||||||
|  | 		Assert(packets.size() == 1); | ||||||
| 		_readTillEnd = true; | 		_readTillEnd = true; | ||||||
| 	} | 	} | ||||||
|  | 	for (auto i = begin(packets), e = end(packets); i != e; ++i) { | ||||||
| 		if (initialized()) { | 		if (initialized()) { | ||||||
| 		mixerEnqueue(std::move(packet)); | 			mixerEnqueue(gsl::make_span(&*i, (e - i))); | ||||||
| 	} else if (!tryReadFirstFrame(std::move(packet))) { | 			break; | ||||||
|  | 		} else if (!tryReadFirstFrame(std::move(*i))) { | ||||||
| 			_error(Error::InvalidData); | 			_error(Error::InvalidData); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -148,10 +155,10 @@ void AudioTrack::callReady() { | ||||||
| 	base::take(_ready)({ VideoInformation(), data }); | 	base::take(_ready)({ VideoInformation(), data }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AudioTrack::mixerEnqueue(FFmpeg::Packet &&packet) { | void AudioTrack::mixerEnqueue(gsl::span<FFmpeg::Packet> packets) { | ||||||
| 	Media::Player::mixer()->feedFromExternal({ | 	Media::Player::mixer()->feedFromExternal({ | ||||||
| 		_audioId, | 		_audioId, | ||||||
| 		std::move(packet) | 		packets | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -172,8 +179,6 @@ void AudioTrack::resume(crl::time time) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AudioTrack::stop() { | void AudioTrack::stop() { | ||||||
| 	Expects(initialized()); |  | ||||||
| 
 |  | ||||||
| 	if (_audioId.externalPlayId()) { | 	if (_audioId.externalPlayId()) { | ||||||
| 		Media::Player::mixer()->stop(_audioId); | 		Media::Player::mixer()->stop(_audioId); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ public: | ||||||
| 	[[nodiscard]] crl::time streamDuration() const; | 	[[nodiscard]] crl::time streamDuration() const; | ||||||
| 
 | 
 | ||||||
| 	// Called from the same unspecified thread.
 | 	// Called from the same unspecified thread.
 | ||||||
| 	void process(FFmpeg::Packet &&packet); | 	void process(std::vector<FFmpeg::Packet> &&packets); | ||||||
| 	void waitForData(); | 	void waitForData(); | ||||||
| 
 | 
 | ||||||
| 	// Called from the main thread.
 | 	// Called from the main thread.
 | ||||||
|  | @ -59,7 +59,7 @@ private: | ||||||
| 	[[nodiscard]] bool fillStateFromFrame(); | 	[[nodiscard]] bool fillStateFromFrame(); | ||||||
| 	[[nodiscard]] bool processFirstFrame(); | 	[[nodiscard]] bool processFirstFrame(); | ||||||
| 	void mixerInit(); | 	void mixerInit(); | ||||||
| 	void mixerEnqueue(FFmpeg::Packet &&packet); | 	void mixerEnqueue(gsl::span<FFmpeg::Packet> packets); | ||||||
| 	void mixerForceToBuffer(); | 	void mixerForceToBuffer(); | ||||||
| 	void callReady(); | 	void callReady(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ namespace Streaming { | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
| constexpr auto kMaxSingleReadAmount = 8 * 1024 * 1024; | constexpr auto kMaxSingleReadAmount = 8 * 1024 * 1024; | ||||||
|  | constexpr auto kMaxQueuedPackets = 1024; | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
|  | @ -54,6 +55,7 @@ int File::Context::read(bytes::span buffer) { | ||||||
| 
 | 
 | ||||||
| 	buffer = buffer.subspan(0, amount); | 	buffer = buffer.subspan(0, amount); | ||||||
| 	while (!_reader->fill(_offset, buffer, &_semaphore)) { | 	while (!_reader->fill(_offset, buffer, &_semaphore)) { | ||||||
|  | 		processQueuedPackets(SleepPolicy::Disallowed); | ||||||
| 		_delegate->fileWaitingForData(); | 		_delegate->fileWaitingForData(); | ||||||
| 		_semaphore.acquire(); | 		_semaphore.acquire(); | ||||||
| 		if (_interrupted) { | 		if (_interrupted) { | ||||||
|  | @ -264,6 +266,13 @@ void File::Context::start(crl::time position) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (video.codec) { | ||||||
|  | 		_queuedPackets[video.index].reserve(kMaxQueuedPackets); | ||||||
|  | 	} | ||||||
|  | 	if (audio.codec) { | ||||||
|  | 		_queuedPackets[audio.index].reserve(kMaxQueuedPackets); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	const auto header = _reader->headerSize(); | 	const auto header = _reader->headerSize(); | ||||||
| 	if (!_delegate->fileReady(header, std::move(video), std::move(audio))) { | 	if (!_delegate->fileReady(header, std::move(video), std::move(audio))) { | ||||||
| 		return fail(Error::OpenFailed); | 		return fail(Error::OpenFailed); | ||||||
|  | @ -287,24 +296,28 @@ void File::Context::readNextPacket() { | ||||||
| 	if (unroll()) { | 	if (unroll()) { | ||||||
| 		return; | 		return; | ||||||
| 	} else if (const auto packet = base::get_if<FFmpeg::Packet>(&result)) { | 	} else if (const auto packet = base::get_if<FFmpeg::Packet>(&result)) { | ||||||
| 		const auto more = _delegate->fileProcessPacket(std::move(*packet)); | 		const auto index = packet->fields().stream_index; | ||||||
| 		if (!more) { | 		const auto i = _queuedPackets.find(index); | ||||||
| 			do { | 		if (i == end(_queuedPackets)) { | ||||||
| 				_reader->startSleep(&_semaphore); | 			return; | ||||||
| 				_semaphore.acquire(); | 		} | ||||||
| 				_reader->stopSleep(); | 		i->second.push_back(std::move(*packet)); | ||||||
| 			} while (!unroll() && !_delegate->fileReadMore()); | 		if (i->second.size() == kMaxQueuedPackets) { | ||||||
|  | 			processQueuedPackets(SleepPolicy::Allowed); | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		// Still trying to read by drain.
 | 		// Still trying to read by drain.
 | ||||||
| 		Assert(result.is<FFmpeg::AvErrorWrap>()); | 		Assert(result.is<FFmpeg::AvErrorWrap>()); | ||||||
| 		Assert(result.get<FFmpeg::AvErrorWrap>().code() == AVERROR_EOF); | 		Assert(result.get<FFmpeg::AvErrorWrap>().code() == AVERROR_EOF); | ||||||
|  | 		processQueuedPackets(SleepPolicy::Allowed); | ||||||
|  | 		if (!finished()) { | ||||||
| 			handleEndOfFile(); | 			handleEndOfFile(); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void File::Context::handleEndOfFile() { | void File::Context::handleEndOfFile() { | ||||||
| 	const auto more = _delegate->fileProcessPacket(FFmpeg::Packet()); | 	const auto more = _delegate->fileProcessEndOfFile(); | ||||||
| 	if (_delegate->fileReadMore()) { | 	if (_delegate->fileReadMore()) { | ||||||
| 		_readTillEnd = false; | 		_readTillEnd = false; | ||||||
| 		auto error = FFmpeg::AvErrorWrap(av_seek_frame( | 		auto error = FFmpeg::AvErrorWrap(av_seek_frame( | ||||||
|  | @ -320,6 +333,17 @@ void File::Context::handleEndOfFile() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void File::Context::processQueuedPackets(SleepPolicy policy) { | ||||||
|  | 	const auto more = _delegate->fileProcessPackets(_queuedPackets); | ||||||
|  | 	if (!more && policy == SleepPolicy::Allowed) { | ||||||
|  | 		do { | ||||||
|  | 			_reader->startSleep(&_semaphore); | ||||||
|  | 			_semaphore.acquire(); | ||||||
|  | 			_reader->stopSleep(); | ||||||
|  | 		} while (!unroll() && !_delegate->fileReadMore()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void File::Context::interrupt() { | void File::Context::interrupt() { | ||||||
| 	_interrupted = true; | 	_interrupted = true; | ||||||
| 	_semaphore.release(); | 	_semaphore.release(); | ||||||
|  |  | ||||||
|  | @ -58,6 +58,10 @@ private: | ||||||
| 		void waitTillInterrupted(); | 		void waitTillInterrupted(); | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
|  | 		enum class SleepPolicy { | ||||||
|  | 			Allowed, | ||||||
|  | 			Disallowed, | ||||||
|  | 		}; | ||||||
| 		static int Read(void *opaque, uint8_t *buffer, int bufferSize); | 		static int Read(void *opaque, uint8_t *buffer, int bufferSize); | ||||||
| 		static int64_t Seek(void *opaque, int64_t offset, int whence); | 		static int64_t Seek(void *opaque, int64_t offset, int whence); | ||||||
| 
 | 
 | ||||||
|  | @ -82,6 +86,7 @@ private: | ||||||
| 		// TODO base::expected.
 | 		// TODO base::expected.
 | ||||||
| 		[[nodiscard]] auto readPacket() | 		[[nodiscard]] auto readPacket() | ||||||
| 		-> base::variant<FFmpeg::Packet, FFmpeg::AvErrorWrap>; | 		-> base::variant<FFmpeg::Packet, FFmpeg::AvErrorWrap>; | ||||||
|  | 		void processQueuedPackets(SleepPolicy policy); | ||||||
| 
 | 
 | ||||||
| 		void handleEndOfFile(); | 		void handleEndOfFile(); | ||||||
| 		void sendFullInCache(bool force = false); | 		void sendFullInCache(bool force = false); | ||||||
|  | @ -89,6 +94,7 @@ private: | ||||||
| 		const not_null<FileDelegate*> _delegate; | 		const not_null<FileDelegate*> _delegate; | ||||||
| 		const not_null<Reader*> _reader; | 		const not_null<Reader*> _reader; | ||||||
| 
 | 
 | ||||||
|  | 		base::flat_map<int, std::vector<FFmpeg::Packet>> _queuedPackets; | ||||||
| 		int _offset = 0; | 		int _offset = 0; | ||||||
| 		int _size = 0; | 		int _size = 0; | ||||||
| 		bool _failed = false; | 		bool _failed = false; | ||||||
|  |  | ||||||
|  | @ -29,9 +29,10 @@ public: | ||||||
| 
 | 
 | ||||||
| 	// Return true if reading and processing more packets is desired.
 | 	// Return true if reading and processing more packets is desired.
 | ||||||
| 	// Return false if sleeping until 'wake()' is called is desired.
 | 	// Return false if sleeping until 'wake()' is called is desired.
 | ||||||
| 	// Return true after the EOF packet if looping is desired.
 | 	[[nodiscard]] virtual bool fileProcessPackets( | ||||||
| 	[[nodiscard]] virtual bool fileProcessPacket( | 		base::flat_map<int, std::vector<FFmpeg::Packet>> &packets) = 0; | ||||||
| 		FFmpeg::Packet &&packet) = 0; | 	// Return true if looping is desired.
 | ||||||
|  | 	[[nodiscard]] virtual bool fileProcessEndOfFile() = 0; | ||||||
| 	[[nodiscard]] virtual bool fileReadMore() = 0; | 	[[nodiscard]] virtual bool fileReadMore() = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -343,54 +343,82 @@ void Player::fileWaitingForData() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Player::fileProcessPacket(FFmpeg::Packet &&packet) { | bool Player::fileProcessPackets( | ||||||
|  | 		base::flat_map<int, std::vector<FFmpeg::Packet>> &packets) { | ||||||
| 	_waitingForData = false; | 	_waitingForData = false; | ||||||
|  | 	auto audioTill = kTimeUnknown; | ||||||
|  | 	auto videoTill = kTimeUnknown; | ||||||
|  | 	for (auto &[index, list] : packets) { | ||||||
|  | 		if (list.empty()) { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (_audio && _audio->streamIndex() == index) { | ||||||
|  | 			//for (const auto &packet : list) {
 | ||||||
|  | 			//	// Maybe it is enough to count by list.back()?.. hope so.
 | ||||||
|  | 			//	accumulate_max(
 | ||||||
|  | 			//		_durationByLastAudioPacket,
 | ||||||
|  | 			//		durationByPacket(*_audio, packet));
 | ||||||
|  | 			//}
 | ||||||
|  | 			accumulate_max( | ||||||
|  | 				_durationByLastAudioPacket, | ||||||
|  | 				durationByPacket(*_audio, list.back())); | ||||||
|  | 			const auto till = _loopingShift + std::clamp( | ||||||
|  | 				FFmpeg::PacketPosition( | ||||||
|  | 					list.back(), | ||||||
|  | 					_audio->streamTimeBase()), | ||||||
|  | 				crl::time(0), | ||||||
|  | 				computeAudioDuration() - 1); | ||||||
|  | 			crl::on_main(&_sessionGuard, [=] { | ||||||
|  | 				audioReceivedTill(till); | ||||||
|  | 			}); | ||||||
|  | 			_audio->process(base::take(list)); | ||||||
|  | 		} else if (_video && _video->streamIndex() == index) { | ||||||
|  | 			//for (const auto &packet : list) {
 | ||||||
|  | 			//	// Maybe it is enough to count by list.back()?.. hope so.
 | ||||||
|  | 			//	accumulate_max(
 | ||||||
|  | 			//		_durationByLastVideoPacket,
 | ||||||
|  | 			//		durationByPacket(*_video, packet));
 | ||||||
|  | 			//}
 | ||||||
|  | 			accumulate_max( | ||||||
|  | 				_durationByLastVideoPacket, | ||||||
|  | 				durationByPacket(*_video, list.back())); | ||||||
|  | 			const auto till = _loopingShift + std::clamp( | ||||||
|  | 				FFmpeg::PacketPosition( | ||||||
|  | 					list.back(), | ||||||
|  | 					_video->streamTimeBase()), | ||||||
|  | 				crl::time(0), | ||||||
|  | 				computeVideoDuration() - 1); | ||||||
|  | 			crl::on_main(&_sessionGuard, [=] { | ||||||
|  | 				videoReceivedTill(till); | ||||||
|  | 			}); | ||||||
|  | 			_video->process(base::take(list)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return fileReadMore(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	const auto &native = packet.fields(); | bool Player::fileProcessEndOfFile() { | ||||||
| 	const auto index = native.stream_index; | 	_waitingForData = false; | ||||||
| 	if (packet.empty()) { |  | ||||||
| 	_readTillEnd = true; | 	_readTillEnd = true; | ||||||
| 	setDurationByPackets(); | 	setDurationByPackets(); | ||||||
|  | 	const auto generateEmptyQueue = [] { | ||||||
|  | 		auto result = std::vector<FFmpeg::Packet>(); | ||||||
|  | 		result.emplace_back(); | ||||||
|  | 		return result; | ||||||
|  | 	}; | ||||||
| 	if (_audio) { | 	if (_audio) { | ||||||
| 		const auto till = _loopingShift + computeAudioDuration(); | 		const auto till = _loopingShift + computeAudioDuration(); | ||||||
| 		crl::on_main(&_sessionGuard, [=] { | 		crl::on_main(&_sessionGuard, [=] { | ||||||
| 			audioReceivedTill(till); | 			audioReceivedTill(till); | ||||||
| 		}); | 		}); | ||||||
| 			_audio->process(FFmpeg::Packet()); | 		_audio->process(generateEmptyQueue()); | ||||||
| 	} | 	} | ||||||
| 	if (_video) { | 	if (_video) { | ||||||
| 		const auto till = _loopingShift + computeVideoDuration(); | 		const auto till = _loopingShift + computeVideoDuration(); | ||||||
| 		crl::on_main(&_sessionGuard, [=] { | 		crl::on_main(&_sessionGuard, [=] { | ||||||
| 			videoReceivedTill(till); | 			videoReceivedTill(till); | ||||||
| 		}); | 		}); | ||||||
| 			_video->process(FFmpeg::Packet()); | 		_video->process(generateEmptyQueue()); | ||||||
| 		} |  | ||||||
| 	} else if (_audio && _audio->streamIndex() == native.stream_index) { |  | ||||||
| 		accumulate_max( |  | ||||||
| 			_durationByLastAudioPacket, |  | ||||||
| 			durationByPacket(*_audio, packet)); |  | ||||||
| 
 |  | ||||||
| 		const auto till = _loopingShift + std::clamp( |  | ||||||
| 			FFmpeg::PacketPosition(packet, _audio->streamTimeBase()), |  | ||||||
| 			crl::time(0), |  | ||||||
| 			computeAudioDuration() - 1); |  | ||||||
| 		crl::on_main(&_sessionGuard, [=] { |  | ||||||
| 			audioReceivedTill(till); |  | ||||||
| 		}); |  | ||||||
| 		_audio->process(std::move(packet)); |  | ||||||
| 	} else if (_video && _video->streamIndex() == native.stream_index) { |  | ||||||
| 		accumulate_max( |  | ||||||
| 			_durationByLastVideoPacket, |  | ||||||
| 			durationByPacket(*_video, packet)); |  | ||||||
| 
 |  | ||||||
| 		const auto till = _loopingShift + std::clamp( |  | ||||||
| 			FFmpeg::PacketPosition(packet, _video->streamTimeBase()), |  | ||||||
| 			crl::time(0), |  | ||||||
| 			computeVideoDuration() - 1); |  | ||||||
| 		crl::on_main(&_sessionGuard, [=] { |  | ||||||
| 			videoReceivedTill(till); |  | ||||||
| 		}); |  | ||||||
| 		_video->process(std::move(packet)); |  | ||||||
| 	} | 	} | ||||||
| 	return fileReadMore(); | 	return fileReadMore(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -97,7 +97,9 @@ private: | ||||||
| 	void fileError(Error error) override; | 	void fileError(Error error) override; | ||||||
| 	void fileWaitingForData() override; | 	void fileWaitingForData() override; | ||||||
| 	void fileFullInCache(bool fullInCache) override; | 	void fileFullInCache(bool fullInCache) override; | ||||||
| 	bool fileProcessPacket(FFmpeg::Packet &&packet) override; | 	bool fileProcessPackets( | ||||||
|  | 		base::flat_map<int, std::vector<FFmpeg::Packet>> &packets) override; | ||||||
|  | 	bool fileProcessEndOfFile() override; | ||||||
| 	bool fileReadMore() override; | 	bool fileReadMore() override; | ||||||
| 
 | 
 | ||||||
| 	// Called from the main thread.
 | 	// Called from the main thread.
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ public: | ||||||
| 		FnMut<void(const Information &)> ready, | 		FnMut<void(const Information &)> ready, | ||||||
| 		Fn<void(Error)> error); | 		Fn<void(Error)> error); | ||||||
| 
 | 
 | ||||||
| 	void process(FFmpeg::Packet &&packet); | 	void process(std::vector<FFmpeg::Packet> &&packets); | ||||||
| 
 | 
 | ||||||
| 	[[nodisacrd]] rpl::producer<> checkNextFrame() const; | 	[[nodisacrd]] rpl::producer<> checkNextFrame() const; | ||||||
| 	[[nodisacrd]] rpl::producer<> waitingForData() const; | 	[[nodisacrd]] rpl::producer<> waitingForData() const; | ||||||
|  | @ -149,25 +149,42 @@ rpl::producer<> VideoTrackObject::waitingForData() const { | ||||||
| 		: _waitingForData.events(); | 		: _waitingForData.events(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void VideoTrackObject::process(FFmpeg::Packet &&packet) { | void VideoTrackObject::process(std::vector<FFmpeg::Packet> &&packets) { | ||||||
| 	if (interrupted()) { | 	if (interrupted() || packets.empty()) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	if (packet.empty()) { | 	if (packets.front().empty()) { | ||||||
|  | 		Assert(packets.size() == 1); | ||||||
| 		_readTillEnd = true; | 		_readTillEnd = true; | ||||||
| 	} else if (!_readTillEnd) { | 	} else if (!_readTillEnd) { | ||||||
|  | 		//for (const auto &packet : packets) {
 | ||||||
|  | 		//	// Maybe it is enough to count by list.back()?.. hope so.
 | ||||||
|  | 		//	accumulate_max(
 | ||||||
|  | 		//		_durationByLastPacket,
 | ||||||
|  | 		//		durationByPacket(packet));
 | ||||||
|  | 		//	if (interrupted()) {
 | ||||||
|  | 		//		return;
 | ||||||
|  | 		//	}
 | ||||||
|  | 		//}
 | ||||||
| 		accumulate_max( | 		accumulate_max( | ||||||
| 			_durationByLastPacket, | 			_durationByLastPacket, | ||||||
| 			durationByPacket(packet)); | 			durationByPacket(packets.back())); | ||||||
| 		if (interrupted()) { | 		if (interrupted()) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	for (auto i = begin(packets), e = end(packets); i != e; ++i) { | ||||||
| 		if (_shared->initialized()) { | 		if (_shared->initialized()) { | ||||||
| 		_stream.queue.push_back(std::move(packet)); | 			_stream.queue.insert( | ||||||
|  | 				end(_stream.queue), | ||||||
|  | 				std::make_move_iterator(i), | ||||||
|  | 				std::make_move_iterator(e)); | ||||||
| 			queueReadFrames(); | 			queueReadFrames(); | ||||||
| 	} else if (!tryReadFirstFrame(std::move(packet))) { | 			break; | ||||||
|  | 		} else if (!tryReadFirstFrame(std::move(*i))) { | ||||||
| 			fail(Error::InvalidData); | 			fail(Error::InvalidData); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -547,6 +564,7 @@ void VideoTrackObject::callReady() { | ||||||
| 		? _stream.duration | 		? _stream.duration | ||||||
| 		: _syncTimePoint.trackTime; | 		: _syncTimePoint.trackTime; | ||||||
| 	base::take(_ready)({ data }); | 	base::take(_ready)({ data }); | ||||||
|  | 	LOG(("READY CALLED!")); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TimePoint VideoTrackObject::trackTime() const { | TimePoint VideoTrackObject::trackTime() const { | ||||||
|  | @ -887,11 +905,12 @@ crl::time VideoTrack::streamDuration() const { | ||||||
| 	return _streamDuration; | 	return _streamDuration; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void VideoTrack::process(FFmpeg::Packet &&packet) { | void VideoTrack::process(std::vector<FFmpeg::Packet> &&packets) { | ||||||
|  | 	LOG(("PACKETS! (%1)").arg(packets.size())); | ||||||
| 	_wrapped.with([ | 	_wrapped.with([ | ||||||
| 		packet = std::move(packet) | 		packets = std::move(packets) | ||||||
| 	](Implementation &unwrapped) mutable { | 	](Implementation &unwrapped) mutable { | ||||||
| 		unwrapped.process(std::move(packet)); | 		unwrapped.process(std::move(packets)); | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ public: | ||||||
| 	[[nodiscard]] crl::time streamDuration() const; | 	[[nodiscard]] crl::time streamDuration() const; | ||||||
| 
 | 
 | ||||||
| 	// Called from the same unspecified thread.
 | 	// Called from the same unspecified thread.
 | ||||||
| 	void process(FFmpeg::Packet &&packet); | 	void process(std::vector<FFmpeg::Packet> &&packets); | ||||||
| 	void waitForData(); | 	void waitForData(); | ||||||
| 
 | 
 | ||||||
| 	// Called from the main thread.
 | 	// Called from the main thread.
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue