public IDataPacket GetVideoData(IResultNode resultNode) { if (!IsIntraSlice(resultNode)) { return(null); } if (resultNode.Parent == null) { // Slice without headers (won't decode!) return(resultNode.Append(resultNode)); } uint?firstMacroblockInSlice = GetFirstMacroblockInSlice(resultNode); if (!firstMacroblockInSlice.HasValue) { return(resultNode.Append(resultNode)); } int index = GetParentIndex(resultNode); IList <IResultNode> siblings = resultNode.Parent.Children; IDataPacket dataPacket = resultNode; for (int i = (index + 1); i < siblings.Count; i++) { IResultNode sibling = siblings[i]; if (!IsIntraSlice(sibling)) { break; // Not an intra-coded slice, so not part of the same IDR picture } uint?nextFirstMacroblockInSlice = GetFirstMacroblockInSlice(sibling); if (!nextFirstMacroblockInSlice.HasValue || (nextFirstMacroblockInSlice <= firstMacroblockInSlice)) { break; // Slice is not part of the same picture } firstMacroblockInSlice = nextFirstMacroblockInSlice.Value; dataPacket = dataPacket.Append(sibling); } // Duplicate the frame data, because otherwise, FFmpeg won't decode it. return(dataPacket.Append(dataPacket)); }
public IDataPacket FindReferenceHeader(IDataReader dataReader, ICodecParametersSpec codecParameters) { // Note: Loop to detect reference headers preceeded by a block of video frames // (e.g. for 3GP files with 'mdat' before the 'moov' atom, so that the slices are located before the SPS/PPS pair) while (dataReader.State == DataReaderState.Ready) { IScanContext scanContext = new ReferenceHeaderScanContext { Detectors = new[] { this } }; var dataBlock = _carver.Carve(new BitStreamDataReader(dataReader), new ReferenceHeaderDataBlockBuilder(), scanContext); if (dataBlock == null) { break; // No (more) data blocks detected } IResultNode sequenceParameterSet = scanContext.Results.FindChild(SequenceParameterSet.Name); if (sequenceParameterSet != null) { IResultNode pictureParameterSet = sequenceParameterSet.FindChild(PictureParameterSet.Name); if (pictureParameterSet != null) { // TODO: perhaps we need to include the headers between the SPS and PPS !? IDataPacket data = sequenceParameterSet.Append(pictureParameterSet); // Report codec parameters for reference header codecParameters.Codec = CodecID.H264; codecParameters.Width = GetWidth(sequenceParameterSet); codecParameters.Height = GetHeight(sequenceParameterSet); var entropyCodingMode = GetAttributeValue <bool>(pictureParameterSet, PictureParameterSet.Attribute.EntropyCodingMode); codecParameters["EntropyCodingMode"] = entropyCodingMode ? "CABAC" : "CAVLC"; // TODO: codecParameters["FrameRate"] = GetAttributeStringValue(sequenceParameterSet, ???); return(data); } } // Sequence- or Picture Parameter Set is missing: Continue scanning after current data block ... dataReader.Position = dataBlock.EndOffset; } return(null); // No reference header detected }
public IDataPacket Append(IDataPacket dataPacket) { return(_result.Append(dataPacket)); }