1212#include " jsonl_source.hh"
1313#include " logging.hh"
1414#include " packet_sink.hh"
15+ #include " packet_stats_collector.hh"
1516#include " tsduck_helper.hh"
1617
1718#define MIRAKC_ARIB_SERVICE_RECORDER_TRACE (...) MIRAKC_ARIB_TRACE(" service-recorder: " __VA_ARGS__)
@@ -28,6 +29,7 @@ struct ServiceRecorderOption final {
2829 size_t chunk_size = 0 ;
2930 size_t num_chunks = 0 ;
3031 uint64_t start_pos = 0 ;
32+ bool packet_stats = false ;
3133};
3234
3335class ServiceRecorder final : public PacketSink,
@@ -91,6 +93,10 @@ class ServiceRecorder final : public PacketSink,
9193
9294 demux_.feedPacket (packet);
9395
96+ if (option_.packet_stats ) {
97+ packet_stats_collector_.CollectPacketStats (packet);
98+ }
99+
94100 switch (state_) {
95101 case State::kPreparing :
96102 return OnPreparing (packet);
@@ -113,6 +119,7 @@ class ServiceRecorder final : public PacketSink,
113119 // The application may purge expired programs in the message handler for
114120 // the `chunk` message. So, the program data must be updated before that.
115121 SendEventUpdateMessage (eit_, now, pos);
122+ SendPacketStatsMessage ();
116123 SendChunkMessage (now, pos);
117124 }
118125
@@ -310,17 +317,15 @@ class ServiceRecorder final : public PacketSink,
310317 if (event_changed) {
311318 MIRAKC_ARIB_SERVICE_RECORDER_WARN (" Event#{:04X} has started before Event#{:04X} ends" ,
312319 GetEvent (new_eit).event_id , GetEvent (eit).event_id );
313- UpdateEventBoundary (now, sink_->pos ());
314- SendEventEndMessage (eit);
320+ HandleEventEnd (now, eit);
315321 SendEventStartMessage (new_eit);
316322 } else {
317323 if (IsUnspecifiedEventEndTime (GetEvent (eit))) {
318324 // Continue recording as the current program until the event changes.
319325 } else {
320326 auto end_time = GetEventEndTime (GetEvent (eit));
321327 if (now >= end_time) {
322- UpdateEventBoundary (end_time, sink_->pos ());
323- SendEventEndMessage (eit);
328+ HandleEventEnd (end_time, eit);
324329 event_started_ = false ; // wait for new event
325330 }
326331 }
@@ -340,6 +345,12 @@ class ServiceRecorder final : public PacketSink,
340345 event_boundary_pos_ = pos;
341346 }
342347
348+ void HandleEventEnd (const ts::Time& endTime, const std::shared_ptr<ts::EIT>& eit) {
349+ UpdateEventBoundary (endTime, sink_->pos ());
350+ SendPacketStatsMessage ();
351+ SendEventEndMessage (eit);
352+ }
353+
343354 void SendStartMessage () {
344355 MIRAKC_ARIB_SERVICE_RECORDER_INFO (" Started recording SID#{:04X}" , option_.sid );
345356
@@ -411,6 +422,32 @@ class ServiceRecorder final : public PacketSink,
411422 SendEventMessage (" event-end" , eit, event_boundary_time_, event_boundary_pos_);
412423 }
413424
425+ void SendPacketStatsMessage () {
426+ if (!option_.packet_stats ) {
427+ return ;
428+ }
429+
430+ auto error_packets = packet_stats_collector_.GetErrorPackets ();
431+ auto dropped_packets = packet_stats_collector_.GetDroppedPackets ();
432+ auto encrypted_packets = packet_stats_collector_.GetEncryptedPackets ();
433+ MIRAKC_ARIB_SERVICE_RECORDER_INFO (" PacketStats: Error: {}, Dropped {}, Encrypted: {}" ,
434+ error_packets, dropped_packets, encrypted_packets);
435+
436+ rapidjson::Document doc (rapidjson::kObjectType );
437+ auto & allocator = doc.GetAllocator ();
438+
439+ rapidjson::Value data (rapidjson::kObjectType );
440+ data.AddMember (" errorPackets" , error_packets, allocator);
441+ data.AddMember (" droppedPackets" , dropped_packets, allocator);
442+ data.AddMember (" encryptedPackets" , encrypted_packets, allocator);
443+
444+ doc.AddMember (" type" , " packet-stats" , allocator);
445+ doc.AddMember (" data" , data, allocator);
446+
447+ FeedDocument (doc);
448+ packet_stats_collector_.ResetPacketStats ();
449+ }
450+
414451 void SendEventMessage (const std::string& type, const std::shared_ptr<ts::EIT>& eit,
415452 const ts::Time& time, uint64_t pos) {
416453 MIRAKC_ARIB_ASSERT (eit);
@@ -466,6 +503,7 @@ class ServiceRecorder final : public PacketSink,
466503 ts::PID pmt_pid_ = ts::PID_NULL;
467504 State state_ = State::kPreparing ;
468505 bool event_started_ = false ;
506+ PacketStatsCollector packet_stats_collector_;
469507
470508 MIRAKC_ARIB_NON_COPYABLE (ServiceRecorder);
471509};
0 commit comments