public bool Init(int targetWidth, int targetHeight) { bool success = true; m_targetWidth = targetWidth; m_targetHeight = targetHeight; if (m_mp4Reader != IntPtr.Zero) { Mp4.DestroyMp4Reader(m_mp4Reader); m_mp4Reader = IntPtr.Zero; } m_mp4Reader = Mp4.CreateMp4Reader(m_mp4Filename); if (m_mp4Reader != IntPtr.Zero) { // Get the video metadata from the file if (!Mp4.GetVideoProperties(m_mp4Reader, out m_durationMilliseconds, out m_frameRate, out m_width, out m_height, out m_sampleCount)) { OnVideoCacheEvent(new VideoCache_EventArgs(VideoCache_Status_Type.ERROR, "Failed to get properties of this video file: " + m_mp4Filename, null)); success = false; } } else { success = false; } return(success); }
/// <summary> /// An MP4 muxing will be created for with the Per-Title video stream template and the audio stream. /// This muxing must define either {uuid} or {bitrate} in the output path. /// These placeholders will be replaced during the generation of the Per-Title. /// </summary> /// <param name="encoding">The reference of the encoding</param> /// <param name="output">The output the files should be written to</param> /// <param name="videoStream">The Per-Title template video stream</param> /// <param name="audioStream">The audio stream</param> private static Mp4 CreateMP4Muxing(Encoding.Encoding encoding, BaseOutput output, Stream videoStream, Stream audioStream) { var encodingOutput = new Encoding.Output { OutputPath = System.IO.Path.Combine(S3_OUTPUT_BASE_PATH, "{width}_{bitrate}_{uuid}"), OutputId = output.Id, Acl = new List <Acl> { new Acl { Permission = Permission.PUBLIC_READ } } }; var muxing = new Mp4 { Filename = "video.mp4", Outputs = new List <Encoding.Output> { encodingOutput }, Streams = new List <MuxingStream> { new MuxingStream { StreamId = videoStream.Id }, new MuxingStream { StreamId = audioStream.Id } } }; return(bitmovin.Encoding.Encoding.Mp4.Create(encoding.Id, muxing)); }
static void Main(string[] args) { Mp4 mp4 = new Mp4(); Mp4adapter mp5 = new Mp4adapter(mp4); mp5.Play(); Console.ReadKey(); }
public static Mp4Status ToMp4Status(this Mp4 @this) { Mp4Status output; if (@this == null || @this.mp4 == null || string.IsNullOrEmpty(@this.mp4.status)) { return(Mp4Status.NotAvailable); } return(Enum.TryParse(@this.mp4.status.Replace("_", string.Empty), true, out output) ? output : Mp4Status.NotAvailable); }
public bool GetGopList(string mp4Filename, SortedList <int, GopRecord> gopList) { bool success = true; if (gopList == null) { gopList = m_gopList; } gopList.Clear(); m_gopIndexLookup.Clear(); if (m_mp4Reader != IntPtr.Zero) { double[] timestamps; Mp4.GetVideoKeyFrameTimestamps(m_mp4Reader, out timestamps); int[] framesInGop = new int[timestamps.Length]; // FIX Mp4.GetVideoGOPLengths(m_mp4Reader, out framesInGop); int ndx = 0; for (int i = 0; i < timestamps.Length; i++) { gopList.Add(i, new GopRecord(ndx, timestamps[i], framesInGop[i])); m_gopIndexLookup.Add(timestamps[i], ndx); ndx += framesInGop[i]; } } else { success = false; } if (gopList.Count > 0) { GopRecord gop = gopList[gopList.Keys.Max()]; m_maxFrameIndex = gop.frameIndex + gop.numFrames - 1; } else { m_maxFrameIndex = 0; } return(success); }
public Mp4adapter(Mp4 mp4) { this.mp4 = mp4; }
async Task <long> PlayMp4FileAsync(string path, int targetWidth, int targetHeight, double startTimestamp, double endTimestamp, DNNTools.DNNengine dnnEngine, float confidence, bool useTracker, IProgress <ProgressStruct> progress, CancellationToken token, WPFTools.PauseToken pauseToken, bool paceOutput, Dictionary <double, int> frameIndexLookup) { // path - filename/path to Mp4 file // startingAt - point in time to start decoding/playback, given in milliseconds // targetWidth, targetHeight - desired pixel dimension of decoded frames // paceOutput - flag indicating whether to pace the output, using frame // timestamps and framerate, so that playback is at video rate long count = -1; if (File.Exists(path)) { count = await Task.Run <long>(async() => { double timestamp = 0.0f; Stopwatch sw = new Stopwatch(); IntPtr mp4Reader = IntPtr.Zero; try { mp4Reader = Mp4.CreateMp4Reader(path); } catch (Exception ex) { string message = ex.Message; } DNNTools.NonMaximumSuppression nms = new DNNTools.NonMaximumSuppression(); nms.Init(); DNNTools.MultiTracker multiTracker = new DNNTools.MultiTracker(); if (mp4Reader != IntPtr.Zero) { try { long durationMilliseconds; double frameRate; long timestampDelta; long timestampWindow; int height; int width; int sampleCount; // Get the video metadata from the file if (Mp4.GetVideoProperties(mp4Reader, out durationMilliseconds, out frameRate, out width, out height, out sampleCount)) { timestampDelta = (long)(1000.0f / frameRate); timestampWindow = timestampDelta / 2; // Ask the decoder to resample to targetWidth x targetHeight, and assume 24-bit RGB colorspace byte[] frame = new byte[targetWidth *targetHeight * 3]; bool key; ProgressStruct prog; m_frameCount = 0; // move to starting position double actualStart = Mp4.SetTimePositionAbsolute(mp4Reader, startTimestamp); int frameIndex = 0; // get the starting frame index int tempIndex = 0; if (frameIndexLookup != null) { if (frameIndexLookup.TryGetValue(actualStart, out tempIndex)) { frameIndex = tempIndex; } } // create flag used to quit early bool running = true; if (actualStart == -1) // failed to move to start position { running = false; } sw.Start(); while (running) { timestamp = (double)Mp4.GetNextVideoFrame(mp4Reader, frame, out key, targetWidth, targetHeight) / 1000.0; if (timestamp == -0.001) // EOF { running = false; break; } if (token.IsCancellationRequested) { // pause or stop requested running = false; break; } byte[] frameCopy = new byte[targetWidth *targetHeight * 3]; Buffer.BlockCopy(frame, 0, frameCopy, 0, targetWidth *targetHeight * 3); prog = new ProgressStruct(timestamp, durationMilliseconds, frameCopy, frameIndex, key, !running, targetWidth, targetHeight); if (dnnEngine != null) { prog.boxList = dnnEngine.EvalImage(frameCopy, targetWidth, targetHeight, 3, targetWidth, targetHeight, confidence); prog.boxList = nms.Execute(prog.boxList, 0.50f); if (useTracker) { List <DNNTools.BoundingBox> trackedBoxes = multiTracker.Update(frameCopy, targetWidth, targetHeight, prog.boxList); prog.boxList.AddRange(trackedBoxes); prog.boxList = nms.Execute(prog.boxList, 0.50f); } else { multiTracker.ClearTrackers(); } } if (progress != null && prog.data != null) { // if we're in playback mode, pace the frames appropriately if (paceOutput) { while (sw.ElapsedMilliseconds < timestampDelta) { Thread.Sleep(1); } sw.Restart(); } m_frameCount++; // send frame to UI thread progress.Report(prog); } await pauseToken.WaitWhilePausedAsync(); if (timestamp >= endTimestamp) { break; } frameIndex++; } } } catch (Exception ex) { m_errorMsg = ex.Message; timestamp = -2; // indicating an exception occurred } finally { try { Mp4.DestroyMp4Reader(mp4Reader); } catch (Exception ex) { string message = ex.Message; } progress.Report(new ProgressStruct(-0.001, 0, null, m_frameCount, false, true, 0, 0)); // signal that the player stopped (timestamp = -0.001) } } else { timestamp = -3; m_errorMsg = "Could not open file."; } return((long)timestamp); }, token); } // END File.Exists return(count); }
public bool LoadGopIntoCache(int gopIndex, SortedList <int, GopRecord> gopList, SortedList <int, FrameRecord> frameCache) { bool success = true; // TEMP GopRecord gop; if (gopList.TryGetValue(gopIndex, out gop)) { int firstFrameIndexInGop = gop.frameIndex; if (!frameCache.ContainsKey(firstFrameIndexInGop)) { // go get all frames for gop with a timestamp = gop.timestamp // then add them to the m_frameCache -- which means decoding them // and writing the decoded from to a file using the function // WriteFile(string filename, double timestamp, int width, int height, int depth, byte[] frameData) // NEW double actualPosition = Mp4.SetTimePositionAbsolute(m_mp4Reader, gop.timestamp + 0.001); byte[] frame = new byte[m_targetWidth * m_targetHeight * 3]; bool key; int ndx = 0; if (!frameCache.ContainsKey(gop.frameIndex)) { while (true) { double ts = (double)Mp4.GetNextVideoFrame(m_mp4Reader, frame, out key, m_targetWidth, m_targetHeight) / 1000.0; if (ts == -1) // EOF { break; } string filename = BuildFilenameFromTimestamp(ts); int frameIndex = gop.frameIndex + ndx; if (WriteFile(filename, ts, m_targetWidth, m_targetHeight, 3, frame)) { frameCache.Add(frameIndex, new FrameRecord(ts, Path.Combine(m_cacheDirectory, filename))); } else { success = false; break; } ndx++; if (ndx >= gop.numFrames) { break; } } } } } // END TEMP return(success); }