static bool EncodeH264Stream(Options opt, Transcoder transcoder) { bool success = false; try { using (var file = System.IO.File.OpenRead(opt.InputFile)) { int videoBufferSize = MediaSample.VideoBufferSizeInBytes(opt.Width, opt.Height, opt.Color.Id); if (videoBufferSize <= 0) { return(false); } MediaSample mediaSample = new MediaSample(); MediaBuffer mediaBuffer = new MediaBuffer(videoBufferSize); mediaSample.Buffer = mediaBuffer; int readBytes; while (true) { mediaBuffer.SetData(0, videoBufferSize); readBytes = file.Read(mediaBuffer.Start, 0, mediaBuffer.DataSize); if (readBytes == videoBufferSize) { mediaBuffer.SetData(0, readBytes); if (!transcoder.Push(0, mediaSample)) { PrintStatus("Transcoder push", transcoder.Error); success = false; break; } success = true; } else { if (!transcoder.Flush()) { success = false; } PrintStatus("Transcoder flush", transcoder.Error); break; } } } } catch (System.IO.DirectoryNotFoundException dnfe) { Console.WriteLine(dnfe); success = false; } return(success); }
static void PrintNalus(MediaBuffer buffer) { // This parsing code assumes that MediaBuffer contains // a single Access Unit of one or more complete NAL Units while (buffer.DataSize > 1) { int dataOffset = buffer.DataOffset; int dataSize = buffer.DataSize; // is this a NALU with a 3 byte start code prefix if (dataSize >= 3 && 0x00 == buffer.Start[dataOffset + 0] && 0x00 == buffer.Start[dataOffset + 1] && 0x01 == buffer.Start[dataOffset + 2]) { PrintNaluHeader(buffer.Start[dataOffset + 3]); // advance in the buffer buffer.SetData(dataOffset + 3, dataSize - 3); } // OR is this a NALU with a 4 byte start code prefix else if (dataSize >= 4 && 0x00 == buffer.Start[dataOffset + 0] && 0x00 == buffer.Start[dataOffset + 1] && 0x00 == buffer.Start[dataOffset + 2] && 0x01 == buffer.Start[dataOffset + 3]) { PrintNaluHeader(buffer.Start[dataOffset + 4]); // advance in the buffer buffer.SetData(dataOffset + 4, dataSize - 4); } else { // advance in the buffer buffer.SetData(dataOffset + 1, dataSize - 1); } // NOTE: Some NALUs may have a trailing zero byte. The `while` // condition `buffer->dataSize() > 1` will effectively // skip the trailing zero byte. } }
public bool NextAudioBuffer(byte[] buffer, ref int length) { if (_cancellationPending) { length = 0; return(false); } lock (_csAVQueue) { int bytesWritten = 0; while ((_audioQueue.Count > 0) && (bytesWritten < buffer.Length)) { MediaSample mediaSample = _audioQueue.First.Value; if (_unmanaged) { UnmanagedMediaBuffer mediaBuffer = mediaSample.UnmanagedBuffer; int chunk = Math.Min(mediaBuffer.DataSize, buffer.Length - bytesWritten); Marshal.Copy(mediaBuffer.DataPtr, buffer, bytesWritten, chunk); bytesWritten += chunk; mediaBuffer.Remove(chunk); if (mediaBuffer.DataSize == 0) { mediaBuffer.Release(); _audioQueue.RemoveFirst(); } } else { MediaBuffer mediaBuffer = mediaSample.Buffer; int chunk = Math.Min(mediaBuffer.DataSize, buffer.Length - bytesWritten); Array.Copy(mediaBuffer.Start, mediaBuffer.DataOffset, buffer, bytesWritten, chunk); bytesWritten += chunk; { int newDataOffset = mediaBuffer.DataOffset + chunk; int newDataSize = mediaBuffer.DataSize - chunk; if (0 == newDataSize) { newDataOffset = 0; } mediaBuffer.SetData(newDataOffset, newDataSize); } if (mediaBuffer.DataSize == 0) { _audioQueue.RemoveFirst(); } } } length = bytesWritten; } return(true); }
static bool SplitFile(string inputFile) { string outputFileExt = ".mpg"; string encodingPreset = Preset.Video.DVD.NTSC_4x3_PCM; const double splitPartDuration = 10; // seconds int audioStreamIndex = -1; int videoStreamIndex = -1; int audioFrameSize = 0; int audioSampleRate = 0; using (var transcoder1 = new Transcoder()) { // In order to use the OEM release for testing (without a valid license) the transcoder demo mode must be enabled. transcoder1.AllowDemoMode = true; using (var inputInfo = new MediaInfo()) { inputInfo.Inputs[0].File = inputFile; if (!inputInfo.Open()) { PrintError("Open MediaInfo", inputInfo.Error); return(false); } // Configure transcoder1 input and output var inputSocket = MediaSocket.FromMediaInfo(inputInfo); transcoder1.Inputs.Add(inputSocket); for (int i = 0; i < inputSocket.Pins.Count; i++) { StreamInfo inputStreamInfo = inputSocket.Pins[i].StreamInfo; if ((inputStreamInfo.MediaType == MediaType.Video) && videoStreamIndex < 0) { var streamInfo = new VideoStreamInfo(); VideoStreamInfo inputVideoStreamInfo = inputStreamInfo as VideoStreamInfo; streamInfo.ColorFormat = ColorFormat.YUV420; streamInfo.StreamType = StreamType.UncompressedVideo; streamInfo.ScanType = inputVideoStreamInfo.ScanType; streamInfo.FrameWidth = inputVideoStreamInfo.FrameWidth; streamInfo.FrameHeight = inputVideoStreamInfo.FrameHeight; streamInfo.DisplayRatioWidth = inputVideoStreamInfo.DisplayRatioWidth; streamInfo.DisplayRatioHeight = inputVideoStreamInfo.DisplayRatioHeight; var outputPin = new MediaPin(); outputPin.StreamInfo = streamInfo; var outputSocket = new MediaSocket(); outputSocket.Pins.Add(outputPin); outputSocket.StreamType = streamInfo.StreamType; videoStreamIndex = transcoder1.Outputs.Count; transcoder1.Outputs.Add(outputSocket); } if ((inputStreamInfo.MediaType == MediaType.Audio) && audioStreamIndex < 0) { var streamInfo = new AudioStreamInfo(); AudioStreamInfo inputAudioStreamInfo = inputStreamInfo as AudioStreamInfo; streamInfo.StreamType = StreamType.LPCM; streamInfo.PcmFlags = inputAudioStreamInfo.PcmFlags; streamInfo.Channels = inputAudioStreamInfo.Channels; streamInfo.SampleRate = inputAudioStreamInfo.SampleRate; streamInfo.BitsPerSample = inputAudioStreamInfo.BitsPerSample; var outputPin = new MediaPin(); outputPin.StreamInfo = streamInfo; var outputSocket = new MediaSocket(); outputSocket.Pins.Add(outputPin); outputSocket.StreamType = streamInfo.StreamType; audioStreamIndex = transcoder1.Outputs.Count; transcoder1.Outputs.Add(outputSocket); audioFrameSize = inputAudioStreamInfo.Channels * inputAudioStreamInfo.BitsPerSample / 8; audioSampleRate = inputAudioStreamInfo.SampleRate; } } } bool res = transcoder1.Open(); PrintError("Open Transcoder1", transcoder1.Error); if (!res) { return(false); } var sample = new MediaSample(); int outputIndex; int splitPartNum = 0; double splitTime = splitPartDuration; double partStartTime = 0; Transcoder transcoder2 = null; List <SplitRecord> splitStats = new List <SplitRecord>(); List <MediaSample> audioSamplesQueue = new List <MediaSample>(); try { for (; ;) { if ((audioSamplesQueue.Count > 0) && (audioSamplesQueue[0].StartTime < splitTime)) { outputIndex = audioStreamIndex; sample = audioSamplesQueue[0]; audioSamplesQueue.RemoveAt(0); } else { if (!transcoder1.Pull(out outputIndex, sample)) { break; } if ((outputIndex != audioStreamIndex) && (outputIndex != videoStreamIndex)) { continue; } } if (outputIndex == audioStreamIndex) { double sampleDuration = (double)(sample.Buffer.DataSize) / (double)(audioFrameSize * audioSampleRate); if (sample.StartTime >= splitTime) { audioSamplesQueue.Add(sample); sample = new MediaSample(); continue; } else if ((sample.StartTime + sampleDuration) > splitTime) { double sample1Duration = splitTime - sample.StartTime; int sample1BufferSize = (int)(sample1Duration * audioSampleRate) * audioFrameSize; if (sample1BufferSize < sample.Buffer.DataSize) { int buffer2Size = sample.Buffer.DataSize - sample1BufferSize; var buffer2 = new MediaBuffer(new byte[buffer2Size]); buffer2.SetData(0, buffer2Size); Array.Copy(sample.Buffer.Start, sample1BufferSize, buffer2.Start, 0, buffer2Size); var sample2 = new MediaSample(); sample2.StartTime = sample.StartTime + sample1Duration; sample2.Buffer = buffer2; if (sample1BufferSize > 0) { sample.Buffer.SetData(sample.Buffer.DataOffset, sample1BufferSize); } else { sample.Buffer.SetData(0, 0); } audioSamplesQueue.Add(sample2); } } } if ((transcoder2 == null) || ((sample.StartTime + 0.0001 >= splitTime) && (outputIndex == videoStreamIndex))) { if (transcoder2 != null) { transcoder2.Flush(); transcoder2.Close(); transcoder2.Dispose(); } SplitRecord splitStat = new SplitRecord(); splitStat.StartTime = splitTime; splitStat.StartTimeActual = sample.StartTime; splitPartNum += 1; splitTime = splitPartNum * splitPartDuration; partStartTime = sample.StartTime; transcoder2 = new Transcoder(); transcoder2.AllowDemoMode = true; // Configure transcoder2 input and output { for (int i = 0; i < transcoder1.Outputs.Count; i++) { var streamInfo = transcoder1.Outputs[i].Pins[0].StreamInfo.Clone() as StreamInfo; var pin = new MediaPin(); pin.StreamInfo = streamInfo; var socket = new MediaSocket(); socket.Pins.Add(pin); socket.StreamType = streamInfo.StreamType; transcoder2.Inputs.Add(socket); } var outputSocket = MediaSocket.FromPreset(encodingPreset); string fileName = GenerateOutputFileName(inputFile, splitPartNum) + outputFileExt; string filePath = Path.Combine(GetExeDir(), fileName); try { File.Delete(filePath); } catch { } outputSocket.File = filePath; transcoder2.Outputs.Add(outputSocket); splitStat.FileName = fileName; } if (splitStats.Count > 0) { SplitRecord lastRecord = splitStats[splitStats.Count - 1]; lastRecord.EndTime = splitStat.StartTime; lastRecord.EndTimeActual = splitStat.StartTimeActual; } splitStats.Add(splitStat); res = transcoder2.Open(); PrintError("Open Transcoder2", transcoder2.Error); if (!res) { return(false); } } if ((splitStats.Count > 0)) { SplitRecord lastRecord = splitStats[splitStats.Count - 1]; lastRecord.EndTime = sample.StartTime; lastRecord.EndTimeActual = lastRecord.EndTime; } if (sample.StartTime >= 0) { sample.StartTime = sample.StartTime - partStartTime; } res = transcoder2.Push(outputIndex, sample); if (!res) { PrintError("Push Transcoder2", transcoder2.Error); return(false); } } } finally { if (transcoder2 != null) { transcoder2.Flush(); transcoder2.Close(); transcoder2.Dispose(); transcoder2 = null; } } if ((transcoder1.Error.Facility != ErrorFacility.Codec) || (transcoder1.Error.Code != (int)CodecError.EOS)) { PrintError("Pull Transcoder1", transcoder1.Error); return(false); } transcoder1.Close(); // print split stats Console.WriteLine(); foreach (var record in splitStats) { Console.WriteLine("{0} start: {1} end: {2} act. start: {3} act. end: {4}", record.FileName, FormatTime(record.StartTime), FormatTime(record.EndTime), FormatTime(record.StartTimeActual), FormatTime(record.EndTimeActual)); } Console.WriteLine(); } return(true); }