//////////////////////////////////////////////////////////////////////////// /// /// De-packetize incoming data and pass it to the elementary stream handler. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::Input(PlayerInputDescriptor_t *Input, unsigned int DataLength, void *Data, bool NonBlocking, unsigned int *DataLengthRemaining) { CollatorStatus_t Status; // st_relayfs_write(ST_RELAY_TYPE_PES_AUDIO_BUFFER, ST_RELAY_SOURCE_AUDIO_COLLATOR, (unsigned char *)Data, DataLength, 0); COLLATOR_ASSERT(!NonBlocking); AssertComponentState("Collator_PesAudio_c::Input", ComponentRunning); InputEntry(Input, DataLength, Data, NonBlocking); ActOnInputDescriptor(Input); // // Copy our arguments to class members so the utility functions can // act upon it. // RemainingData = (unsigned char *)Data; RemainingLength = DataLength; // // Continually handle units of input until all input is exhausted (or an error occurs). // // Be aware that our helper functions may, during their execution, cause state changes // that result in a different branch being taken next time round the loop. // Status = CollatorNoError; while (Status == CollatorNoError && RemainingLength != 0) { //COLLATOR_DEBUG("De-PESing loop has %d bytes remaining\n", RemainingLength); //report_dump_hex( severity_note, RemainingData, min(RemainingLength, 188), 32, 0); if (SeekingPesHeader) { // // Try to lock to incoming PES headers // Status = SearchForPesHeader(); } else if (GotPartialPesHeader) { // // Read in the remains of the PES header // Status = ReadPartialPesHeader(); } else { // // Send the PES packet for frame level analysis // Status = ReadPesPacket(); } } if (Status != CollatorNoError) { // if anything when wrong then we need to resynchronize COLLATOR_DEBUG("General failure; seeking new PES header\n"); DiscardAccumulatedData(); SeekingPesHeader = true; } InputExit(); return Status; }
CollatorStatus_t Collator_PesVideoRaw_c::Input(PlayerInputDescriptor_t *Input, unsigned int DataLength, void *Data, bool NonBlocking, unsigned int *DataLengthRemaining) { PlayerStatus_t Status = PlayerNoError; COLLATOR_ASSERT(!NonBlocking); AssertComponentState("Collator_PesRaw_c::Input", ComponentRunning); InputEntry(Input, DataLength, Data, NonBlocking); // Extract the descriptor timing information ActOnInputDescriptor(Input); COLLATOR_DEBUG("DataLength : %d\n", DataLength); if (DataRemaining == 0) //{{{ Treat the packet as a header, read metadata and build stream info { BufferStructure_t BufferStructure; class Buffer_c* Buffer; unsigned int Format; unsigned char* DataBlock; unsigned char* PesHeader = (unsigned char*)Data; unsigned int PesLength; unsigned int PesHeaderLength; unsigned int PayloadLength; COLLATOR_DEBUG("Header : %d\n", DataLength); //{{{ Read pes header // Read the length of the payload PesLength = (PesHeader[4] << 8) + PesHeader[5]; PesHeaderLength = PesHeader[8]; if (PesLength != 0) PayloadLength = PesLength - PesHeaderLength - 3; else PayloadLength = 0; COLLATOR_DEBUG("DataLength %d, PesLength %d, PesHeaderLength %d, PayloadLength %d\n", DataLength, PesLength, PesHeaderLength, PayloadLength); Bits.SetPointer(PesHeader + 9); // Set bits pointer ready to process optional fields if ((PesHeader[7] & 0x80) == 0x80) // PTS present? //{{{ read PTS { Bits.FlushUnseen(4); PlaybackTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15); Bits.FlushUnseen(1); PlaybackTimeValid = true; COLLATOR_DEBUG("PTS %llu.\n", PlaybackTime); } //}}} if ((PesHeader[7] & 0xC0) == 0xC0) // DTS present? //{{{ read DTS { Bits.FlushUnseen(4); DecodeTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15); Bits.FlushUnseen(1); DecodeTimeValid = true; } //}}} else if ((PesHeader[7] & 0xC0) == 0x40) { COLLATOR_ERROR("Malformed pes header contains DTS without PTS.\n"); InputExit(); return CollatorError; } //}}} DataBlock = PesHeader + 9 + PesHeaderLength; //{{{ Trace #if 0 report(severity_info, "(%d)\n%06d: ", PayloadLength, 0); for (int i = 0; i < PayloadLength; i++) { report(severity_info, "%02x ", DataBlock[i]); if (((i + 1) & 0x1f) == 0) report(severity_info, "\n%06d: ", i + 1); } report(severity_info, "\n"); #endif //}}} // Check that this is what we think it is if (strcmp((char*)DataBlock, "STMicroelectronics") != 0) { //COLLATOR_TRACE("Id : %s\n", Id); InputExit(); return FrameParserNoError; } DataBlock += strlen((char*)DataBlock) + 1; // Fill in stream info for frame parser memcpy(&StreamInfo.width, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); memcpy(&StreamInfo.height, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); memcpy(&StreamInfo.FrameRateNumerator, DataBlock, sizeof(unsigned long long)); DataBlock += sizeof(unsigned long long); memcpy(&StreamInfo.FrameRateDenominator, DataBlock, sizeof(unsigned long long)); DataBlock += sizeof(unsigned long long); memcpy(&Format, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); //memcpy (&StreamInfo.interlaced, DataBlock, sizeof (unsigned int)); //DataBlock += sizeof (unsigned int); memcpy(&DataRemaining, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); StreamInfo.interlaced = 0; StreamInfo.pixel_aspect_ratio.Numerator = 1; StreamInfo.pixel_aspect_ratio.Denominator = 1; //StreamInfo.FrameRateNumerator = 25; //StreamInfo.FrameRateDenominator = 1; StreamInfo.InputWindow.X = 0; StreamInfo.InputWindow.Y = 0; StreamInfo.InputWindow.Width = StreamInfo.width; StreamInfo.InputWindow.Height = StreamInfo.height; StreamInfo.OutputWindow = StreamInfo.InputWindow; memset(&StreamInfo.OutputWindow, 0, sizeof(StreamInfo.OutputWindow)); if (DecodeBuffer == NULL) { // Fill out the buffer structure request memset(&BufferStructure, 0x00, sizeof(BufferStructure_t)); BufferStructure.DimensionCount = 2; BufferStructure.Dimension[0] = StreamInfo.width; BufferStructure.Dimension[1] = StreamInfo.height; //{{{ determine buffer format switch (Format) { case CodeToInteger('N', 'V', '2', '2'): BufferStructure.Format = FormatVideo422_Raster; break; case CodeToInteger('R', 'G', 'B', 'P'): BufferStructure.Format = FormatVideo565_RGB; break; case CodeToInteger('R', 'G', 'B', '3'): BufferStructure.Format = FormatVideo888_RGB; break; case CodeToInteger('R', 'G', 'B', '4'): BufferStructure.Format = FormatVideo8888_ARGB; break; case CodeToInteger('Y', 'U', 'Y', 'V'): BufferStructure.Format = FormatVideo422_YUYV; break; default: COLLATOR_ERROR("Unsupported decode buffer format request %.4s\n", (char*) &Format); InputExit(); return CollatorError; } //}}} // Ask the manifestor for the buffer Status = Manifestor->GetDecodeBuffer(&BufferStructure, &Buffer); if (Status != ManifestorNoError) { COLLATOR_ERROR("Failed to get decode buffer\n"); InputExit(); return CollatorError; } StreamInfo.buffer_class = (unsigned int*)Buffer; // Get physical address of data buffer (not actually used later in pipeline) Status = Buffer->ObtainDataReference(NULL, NULL, (void**)&StreamInfo.buffer, PhysicalAddress); if (Status != BufferNoError) { COLLATOR_ERROR("Failed to get decode buffer data reference\n"); InputExit(); return CollatorError; } // Remember cached address so we can write to it Status = Buffer->ObtainDataReference(NULL, NULL, (void**)&DecodeBuffer, CachedAddress); if (Status != BufferNoError) { COLLATOR_ERROR("Failed to get decode buffer data reference\n"); InputExit(); return CollatorError; } CodedFrameBuffer->AttachBuffer(Buffer); // Attach to decode buffer (so it will be freed at the same time) Buffer->DecrementReferenceCount(); // and release ownership of the buffer to the decode buffer } COLLATOR_DEBUG("%s: ImageSize %6d\n", __FUNCTION__, DataRemaining); COLLATOR_DEBUG("%s: ImageWidth %6d\n", __FUNCTION__, StreamInfo.width); COLLATOR_DEBUG("%s: ImageHeight %6d\n", __FUNCTION__, StreamInfo.height); COLLATOR_DEBUG("%s: Format %.4s\n", __FUNCTION__, (char *) &Format); Status = CollatorNoError; } //}}} else //{{{ Assume packet is part of data - copy to decode buffer { if (DecodeBuffer == NULL) { COLLATOR_ERROR("No decode buffer available\n"); InputExit(); return CodecError; } // Transfer the packet to the next coded data frame and pass on memcpy(DecodeBuffer + DataCopied, Data, DataLength); DataRemaining -= DataLength; DataCopied += DataLength; if (DataRemaining <= 0) { Status = AccumulateData(sizeof(StreamInfo_t), (unsigned char*)&StreamInfo); DataRemaining = 0; DataCopied = 0; DecodeBuffer = NULL; if (Status != CollatorNoError) { COLLATOR_ERROR("Failed to accumulate StreamInfo\n"); InputExit(); return Status; } Status = InternalFrameFlush(); if (Status != CollatorNoError) COLLATOR_ERROR("Failed to flush frame\n"); } } //}}} InputExit(); return Status; }