mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Implemented a frame parser for H.265 (HEVC) recordings
This commit is contained in:
		| @@ -3331,6 +3331,7 @@ Thomas Reufer <thomas@reufer.ch> | ||||
|  for improving handling frame numbers to have a smoother progress display during | ||||
|  replay of recordings with B-frames | ||||
|  for fixing replaying recordings to their very end, if they don't end with an I-frame | ||||
|  for implementing a frame parser for H.265 (HEVC) recordings | ||||
|  | ||||
| Eike Sauer <EikeSauer@t-online.de> | ||||
|  for reporting a problem with channels that need more than 5 TS packets for detecting | ||||
|   | ||||
							
								
								
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -8861,3 +8861,4 @@ Video Disk Recorder Revision History | ||||
|   replay of recordings with B-frames (thanks to Thomas Reufer). | ||||
| - Fixed replaying recordings to their very end, if they don't end with an I-frame | ||||
|   (thanks to Thomas Reufer). | ||||
| - Implemented a frame parser for H.265 (HEVC) recordings (thanks to Thomas Reufer). | ||||
|   | ||||
							
								
								
									
										3
									
								
								pat.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								pat.c
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  * See the main source file 'vdr.c' for copyright information and | ||||
|  * how to reach the author. | ||||
|  * | ||||
|  * $Id: pat.c 4.1 2015/08/17 08:46:55 kls Exp $ | ||||
|  * $Id: pat.c 4.2 2016/12/22 11:42:23 kls Exp $ | ||||
|  */ | ||||
|  | ||||
| #include "pat.h" | ||||
| @@ -439,6 +439,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length | ||||
|               case 1: // STREAMTYPE_11172_VIDEO | ||||
|               case 2: // STREAMTYPE_13818_VIDEO | ||||
|               case 0x1B: // H.264 | ||||
|               case 0x24: // H.265 | ||||
|                       Vpid = esPid; | ||||
|                       Ppid = pmt.getPCRPid(); | ||||
|                       Vtype = stream.getStreamType(); | ||||
|   | ||||
							
								
								
									
										88
									
								
								remux.c
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								remux.c
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  * See the main source file 'vdr.c' for copyright information and | ||||
|  * how to reach the author. | ||||
|  * | ||||
|  * $Id: remux.c 4.1 2015/03/11 09:49:38 kls Exp $ | ||||
|  * $Id: remux.c 4.2 2016/12/22 11:45:52 kls Exp $ | ||||
|  */ | ||||
|  | ||||
| #include "remux.h" | ||||
| @@ -708,6 +708,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) | ||||
|            case 0x01: // STREAMTYPE_11172_VIDEO | ||||
|            case 0x02: // STREAMTYPE_13818_VIDEO | ||||
|            case 0x1B: // H.264 | ||||
|            case 0x24: // H.265 | ||||
|                       vpid = stream.getPid(); | ||||
|                       vtype = stream.getStreamType(); | ||||
|                       ppid = Pmt.getPCRPid(); | ||||
| @@ -1204,16 +1205,16 @@ private: | ||||
|     nutSequenceParameterSet = 7, | ||||
|     nutAccessUnitDelimiter  = 9, | ||||
|     }; | ||||
|   cTsPayload tsPayload; | ||||
|   uchar byte; // holds the current byte value in case of bitwise access | ||||
|   int bit; // the bit index into the current byte (-1 if we're not in bit reading mode) | ||||
|   int zeroBytes; // the number of consecutive zero bytes (to detect 0x000003) | ||||
|   uint32_t scanner; | ||||
|   // Identifiers written in '_' notation as in "ITU-T H.264": | ||||
|   bool separate_colour_plane_flag; | ||||
|   int log2_max_frame_num; | ||||
|   bool frame_mbs_only_flag; | ||||
|   // | ||||
| protected: | ||||
|   cTsPayload tsPayload; | ||||
|   uint32_t scanner; | ||||
|   bool gotAccessUnitDelimiter; | ||||
|   bool gotSequenceParameterSet; | ||||
|   uchar GetByte(bool Raw = false); | ||||
| @@ -1430,6 +1431,81 @@ void cH264Parser::ParseSliceHeader(void) | ||||
|      } | ||||
| } | ||||
|  | ||||
| // --- cH265Parser ----------------------------------------------------------- | ||||
|  | ||||
| class cH265Parser : public cH264Parser { | ||||
| private: | ||||
|   enum eNalUnitType { | ||||
|     nutSliceSegmentTrailingN =  0, | ||||
|     nutSliceSegmentTrailingR =  1, | ||||
|     nutSliceSegmentTSAN      =  2, | ||||
|     nutSliceSegmentTSAR      =  3, | ||||
|     nutSliceSegmentSTSAN     =  4, | ||||
|     nutSliceSegmentSTSAR     =  5, | ||||
|     nutSliceSegmentRADLN     =  6, | ||||
|     nutSliceSegmentRADLR     =  7, | ||||
|     nutSliceSegmentRASLN     =  8, | ||||
|     nutSliceSegmentRASLR     =  9, | ||||
|     nutSliceSegmentBLAWLP    = 16, | ||||
|     nutSliceSegmentBLAWRADL  = 17, | ||||
|     nutSliceSegmentBLANLP    = 18, | ||||
|     nutSliceSegmentIDRWRADL  = 19, | ||||
|     nutSliceSegmentIDRNLP    = 20, | ||||
|     nutSliceSegmentCRANUT    = 21, | ||||
|     nutVideoParameterSet     = 32, | ||||
|     nutSequenceParameterSet  = 33, | ||||
|     nutPictureParameterSet   = 34, | ||||
|     nutAccessUnitDelimiter   = 35, | ||||
|     nutEndOfSequence         = 36, | ||||
|     nutEndOfBitstream        = 37, | ||||
|     nutFillerData            = 38, | ||||
|     nutPrefixSEI             = 39, | ||||
|     nutSuffixSEI             = 40, | ||||
|     nutNonVCLRes0            = 41, | ||||
|     nutNonVCLRes3            = 44, | ||||
|     nutUnspecified0          = 48, | ||||
|     nutUnspecified7          = 55, | ||||
|     }; | ||||
| public: | ||||
|   cH265Parser(void); | ||||
|   virtual int Parse(const uchar *Data, int Length, int Pid); | ||||
|   }; | ||||
|  | ||||
| cH265Parser::cH265Parser(void) | ||||
| :cH264Parser() | ||||
| { | ||||
| } | ||||
|  | ||||
| int cH265Parser::Parse(const uchar *Data, int Length, int Pid) | ||||
| { | ||||
|   newFrame = independentFrame = false; | ||||
|   tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid); | ||||
|   if (TsPayloadStart(Data)) { | ||||
|      tsPayload.SkipPesHeader(); | ||||
|      scanner = EMPTY_SCANNER; | ||||
|      } | ||||
|   for (;;) { | ||||
|       scanner = (scanner << 8) | GetByte(true); | ||||
|       if ((scanner & 0xFFFFFF00) == 0x00000100) { // NAL unit start | ||||
|          uchar NalUnitType = (scanner >> 1) & 0x3F; | ||||
|          GetByte(); // nuh_layer_id + nuh_temporal_id_plus1 | ||||
|          if (NalUnitType <= nutSliceSegmentRASLR || (NalUnitType >= nutSliceSegmentBLAWLP && NalUnitType <= nutSliceSegmentCRANUT)) { | ||||
|             if (NalUnitType == nutSliceSegmentIDRWRADL || NalUnitType == nutSliceSegmentIDRNLP || NalUnitType == nutSliceSegmentCRANUT) | ||||
|                independentFrame = true; | ||||
|             if (GetBit()) { // first_slice_segment_in_pic_flag | ||||
|                newFrame = true; | ||||
|                tsPayload.Statistics(); | ||||
|                } | ||||
|             break; | ||||
|             } | ||||
|          } | ||||
|       if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary | ||||
|          || tsPayload.Eof()) // or if we're out of data | ||||
|          break; | ||||
|       } | ||||
|   return tsPayload.Used(); | ||||
| } | ||||
|  | ||||
| // --- cFrameDetector -------------------------------------------------------- | ||||
|  | ||||
| cFrameDetector::cFrameDetector(int Pid, int Type) | ||||
| @@ -1456,13 +1532,15 @@ void cFrameDetector::SetPid(int Pid, int Type) | ||||
| { | ||||
|   pid = Pid; | ||||
|   type = Type; | ||||
|   isVideo = type == 0x01 || type == 0x02 || type == 0x1B; // MPEG 1, 2 or H.264 | ||||
|   isVideo = type == 0x01 || type == 0x02 || type == 0x1B || type == 0x24; // MPEG 1, 2, H.264 or H.265 | ||||
|   delete parser; | ||||
|   parser = NULL; | ||||
|   if (type == 0x01 || type == 0x02) | ||||
|      parser = new cMpeg2Parser; | ||||
|   else if (type == 0x1B) | ||||
|      parser = new cH264Parser; | ||||
|   else if (type == 0x24) | ||||
|      parser = new cH265Parser; | ||||
|   else if (type == 0x04 || type == 0x06) // MPEG audio or AC3 audio | ||||
|      parser = new cAudioParser; | ||||
|   else if (type != 0) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user