In this article, we'll show how to get up and running quickly with a simple app that inserts ASYNC Klv or SYNC Klv data into a transport stream. We'll use KlvInjector SDK.
// Create Player instance CKlvInjector m_KlvInjector = new CKlvInjector(); // Setup events m_KlvInjector.PlayerEvent += new NotifyPlayerEvent(OnPlayerEvent); m_KlvInjector.PidDetectionEvent += new NotifyPidDetection(OnPidDetectionEvent); m_KlvInjector.SyncFrameEvent += new NotifySyncFrame(OnSyncFrameEvent); m_KlvInjector.ErrorEvent += new NotifyError(OnErrorEvent);
m_KlvInjector.RenderVideo = true; // to show video m_KlvInjector.Caching = 200; // Caching delay, needed to get smooth video playback (if you have jitter) m_KlvInjector.Hwnd = 0; // Where to render video m_KlvInjector.VideoCaptureMode.uncompressedVideo = UncompressedVideoModeWr.UncompressedVideoMode_None; m_KlvInjector.VideoCaptureMode.fCompressedVideo = true; // Set the output target m_KlvInjector.NetTarget.Url = targetUrl; m_KlvInjector.NetTarget.Use = true; // Initialize m_KlvInjector.Init("udp://227.1.1.1:30120"); // source stream Url // Set required KlvProcessing mode KlvDataPropsWr m_klvProps = new KlvDataPropsWr(ProcessingModeWr.INSERT_KLV_ASYNC); // Read packet m_klvProps.DefaultPacket = System.IO.File.ReadAllBytes("KlvPacket.bin");
// Start Processing m_KlvInjector.Start();
void OnPidDetectionEvent(List<PidInfoWr> pidList) { int firstKlvPidFound = 0; pidList.ForEach(pid => { Console.WriteLine("Pid 0X{0} type {1}", pid.streamId.ToString("X"), pid.streamType, Color.LightGray); if (pid.streamType == StreamType.KLV && firstKlvPidFound == 0) { firstKlvPidFound = pid.streamId; m_KlvInjector.IgnorePidInOutput(firstKlvPidFound); } }); m_KlvPid = firstKlvPidFound != 0 ? firstKlvPidFound : 0X1F1; // If the stream has no Klv, we have to add a new Klv Pid. m_KlvInjector.AddDataPidToOutput(m_KlvPid, m_klvProps); }
m_KlvInjector.WritePacketToOutputPid(m_KlvPid, klvData, klvTimestamp);
void OnSyncFrameEvent(List<StreamFrameInfoWr> streamList) { streamList.ForEach(delegate(StreamFrameInfoWr streamFrame) { switch (streamFrame.streamType) { case StreamType.VIDEO: { // Here we got an uncompressed frame VideoFrameInfoWr vf = streamFrame as VideoFrameInfoWr; // Modify and insert Klv Packet m_KlvInjector.WritePacketToOutputPid(m_KlvPid, m_KlvInjector.KlvRemux.AdjustTime(m_DefaultPcktBuffer, m_firstKlvTime.Add(dt.Subtract(m_FramesFirstReceivedTime))), vf.timeStamp); } break; case StreamType.KLV: { // Here we got a klv packet KlvFrameInfoWr kf = streamFrame as KlvFrameInfoWr; } break; case StreamType.PRIVATE_DATA: { // Here we got a private data packet DataFrameInfoWr df = streamFrame as DataFrameInfoWr; } break; } }); }
KlvStreamInjector has to receive (especially when working with files) timing info in order to be able sync Klv data (insert it at the correct place in the file). This can be achieved with or without actual decoding. If no decoding is done, the offline process can be a lot faster (and real time / stream mode use less CPU). So, when no preview is needed, set CaptureMode to Compressed (fCompressedVideo = true) and disable Uncompressed capture (VideoCaptureMode.uncompressedVideo = UncompressedVideoModeWr.UncompressedVideoMode_None;) to avoid unnecessary video decoding.
No Comments