mirror of
				https://github.com/rofafor/vdr-plugin-femon.git
				synced 2023-10-10 11:36:53 +00:00 
			
		
		
		
	Fixed H.264 parser.
This commit is contained in:
		
							
								
								
									
										3
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -365,7 +365,8 @@ VDR Plugin 'femon' Revision History | ||||
| - Cleaned up compilation warnings. | ||||
| - Fixed font handling to be thread-safe. | ||||
|  | ||||
| 2009-07-xx: Version 1.7.3 | ||||
| 2009-08-28: Version 1.7.3 | ||||
|  | ||||
| - Removed OSD offset and height options. | ||||
| - Added PES assembler. | ||||
| - Added bitstream parsers for all codecs. | ||||
|   | ||||
							
								
								
									
										227
									
								
								femonh264.c
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								femonh264.c
									
									
									
									
									
								
							| @@ -42,9 +42,23 @@ const eVideoFormat cFemonH264::s_VideoFormats[] = | ||||
|   VIDEO_FORMAT_RESERVED | ||||
| }; | ||||
|  | ||||
| const uint8_t cFemonH264::s_SeiNumClockTsTable[9] = | ||||
| { | ||||
|   1, 1, 1, 2, 2, 3, 3, 2, 3 | ||||
| }; | ||||
|  | ||||
| cFemonH264::cFemonH264(cFemonVideoIf *videohandler) | ||||
| : m_VideoHandler(videohandler) | ||||
| : m_VideoHandler(videohandler), | ||||
|   m_Width(0), | ||||
|   m_Height(0), | ||||
|   m_AspectRatio(VIDEO_ASPECT_RATIO_INVALID), | ||||
|   m_Format(VIDEO_FORMAT_INVALID), | ||||
|   m_FrameRate(0), | ||||
|   m_BitRate(0), | ||||
|   m_Scan(VIDEO_SCAN_INVALID), | ||||
|   m_CpbDpbDelaysPresentFlag(false), | ||||
|   m_PicStructPresentFlag(false), | ||||
|   m_TimeOffsetLength(0) | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -54,7 +68,10 @@ cFemonH264::~cFemonH264() | ||||
|  | ||||
| bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
| { | ||||
|   bool aud_found = false, sps_found = false, sei_found = true; // sei currently disabled | ||||
|   uint8_t nal_data[len]; | ||||
|   bool aud_found = false, sps_found = false, sei_found = false; | ||||
|   const uint8_t *start = buf; | ||||
|   const uint8_t *end = start + len; | ||||
|  | ||||
|   if (!m_VideoHandler) | ||||
|      return false; | ||||
| @@ -63,10 +80,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
|   if (!PesLongEnough(len)) | ||||
|       return false; | ||||
|   buf += PesPayloadOffset(buf); | ||||
|  | ||||
|   const uint8_t *start = buf; | ||||
|   const uint8_t *end = start + len; | ||||
|   uint8_t nal_data[len]; | ||||
|   start = buf; | ||||
|  | ||||
|   for (;;) { | ||||
|       int consumed = 0; | ||||
| @@ -81,7 +95,6 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
|                  switch (buf[4] >> 5) { | ||||
|                    case 0: case 3: case 5: // I_FRAME | ||||
|                        //Dprintf("H.264: Found NAL AUD at offset %d/%d", buf - start, len); | ||||
|                        m_VideoHandler->SetVideoCodec(VIDEO_CODEC_H264); | ||||
|                        aud_found = true; | ||||
|                        break; | ||||
|                    case 1: case 4: case 6: // P_FRAME; | ||||
| @@ -101,7 +114,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
|                   sps_found = true; | ||||
|              } | ||||
|              break; | ||||
|  | ||||
| #if 0 | ||||
|         case NAL_SEI: | ||||
|              if (!sei_found) { | ||||
|                //Dprintf("H.264: Found NAL SEI at offset %d/%d", buf - start, len); | ||||
| @@ -111,7 +124,7 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
|                   sei_found = true; | ||||
|              } | ||||
|              break; | ||||
|  | ||||
| #endif | ||||
|         default: | ||||
|              break; | ||||
|         } | ||||
| @@ -122,6 +135,22 @@ bool cFemonH264::processVideo(const uint8_t *buf, int len) | ||||
|       buf += consumed + 4; | ||||
|       } | ||||
|  | ||||
|   if (aud_found) { | ||||
|      m_VideoHandler->SetVideoCodec(VIDEO_CODEC_H264); | ||||
|      if (sps_found) { | ||||
|         //Dprintf("H.264 SPS: -> video size %dx%d, aspect %d format %d", m_Width, m_Height, m_AspectRatio, m_Format); | ||||
|         m_VideoHandler->SetVideoFormat(m_Format); | ||||
|         m_VideoHandler->SetVideoSize(m_Width, m_Height); | ||||
|         m_VideoHandler->SetVideoAspectRatio(m_AspectRatio); | ||||
|         } | ||||
|      if (sei_found) { | ||||
|         //Dprintf("H.264 SEI: -> stream bitrate %.1f, frame rate %.1f scan %d", m_BitRate, m_FrameRate, m_Scan); | ||||
|         m_VideoHandler->SetVideoFramerate(m_FrameRate); | ||||
|         m_VideoHandler->SetVideoBitrate(m_BitRate); | ||||
|         m_VideoHandler->SetVideoScan(m_Scan); | ||||
|         } | ||||
|   } | ||||
|  | ||||
|   return aud_found; | ||||
| } | ||||
|  | ||||
| @@ -159,11 +188,16 @@ int cFemonH264::nalUnescape(uint8_t *dst, const uint8_t *src, int len) | ||||
| int cFemonH264::parseSPS(const uint8_t *buf, int len) | ||||
| { | ||||
|   int profile_idc, pic_order_cnt_type, frame_mbs_only, i, j; | ||||
|   unsigned int width = 0, height = 0; | ||||
|   eVideoAspectRatio aspect_ratio = VIDEO_ASPECT_RATIO_INVALID; | ||||
|   eVideoFormat format = VIDEO_FORMAT_INVALID; | ||||
|   cBitStream bs(buf, len); | ||||
|  | ||||
|   unsigned int width = m_Width; | ||||
|   unsigned int height = m_Height; | ||||
|   eVideoAspectRatio aspect_ratio = m_AspectRatio; | ||||
|   eVideoFormat format = m_Format; | ||||
|   bool cpb_dpb_delays_present_flag = m_CpbDpbDelaysPresentFlag; | ||||
|   bool pic_struct_present_flag = m_PicStructPresentFlag; | ||||
|   unsigned int time_offset_length = m_TimeOffsetLength; | ||||
|  | ||||
|   profile_idc = bs.getU8(); | ||||
|  | ||||
|   //Dprintf("H.264 SPS: profile_idc %d", profile_idc); | ||||
| @@ -255,21 +289,83 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len) | ||||
|      if (bs.getBit())                       // overscan_info_present_flag | ||||
|         bs.skipBit();                       // overscan_approriate_flag | ||||
|      if (bs.getBit()) {                     // video_signal_type_present_flag | ||||
|         uint32_t video_format = bs.getBits(3); | ||||
|         uint32_t video_format; | ||||
|         video_format = bs.getBits(3);       // video_format | ||||
|         if (video_format < sizeof(s_VideoFormats) / sizeof(s_VideoFormats[0])) { | ||||
|            format = s_VideoFormats[video_format]; | ||||
|            //Dprintf("H.264 SPS: -> video format %d", format); | ||||
|            } | ||||
|         bs.skipBit();                       // video_full_range_flag | ||||
|         bs.skipBit();                       // video_full_range_flag | ||||
|         if (bs.getBit()) {                  // colour_description_present_flag | ||||
|            bs.skipBits(8);                  // colour_primaries | ||||
|            bs.skipBits(8);                  // transfer_characteristics | ||||
|            bs.skipBits(8);                  // matrix_coefficients | ||||
|            } | ||||
|         } | ||||
|      if (bs.getBit()) {                     // chroma_loc_info_present_flag | ||||
|         bs.skipUeGolomb();                  // chroma_sample_loc_type_top_field | ||||
|         bs.skipUeGolomb();                  // chroma_sample_loc_type_bottom_field | ||||
|         } | ||||
|      if (bs.getBit()) {                     // timing_info_present_flag | ||||
|         bs.skipBits(32);                    // num_units_in_tick | ||||
|         bs.skipBits(32);                    // time_scale | ||||
|         bs.skipBit();                       // fixed_frame_rate_flag | ||||
|         } | ||||
|      int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag | ||||
|      if (nal_hrd_parameters_present_flag) { | ||||
|         int cpb_cnt_minus1; | ||||
|         cpb_cnt_minus1 = bs.getUeGolomb();  // cpb_cnt_minus1 | ||||
|         bs.skipBits(4);                     // bit_rate_scale | ||||
|         bs.skipBits(4);                     // cpb_size_scale | ||||
|         for (int i = 0; i < cpb_cnt_minus1; ++i) { | ||||
|             bs.skipUeGolomb();              // bit_rate_value_minus1[i] | ||||
|             bs.skipUeGolomb();              // cpb_size_value_minus1[i] | ||||
|             bs.skipBit();                   // cbr_flag[i] | ||||
|             } | ||||
|         bs.skipBits(5);                     // initial_cpb_removal_delay_length_minus1 | ||||
|         bs.skipBits(5);                     // cpb_removal_delay_length_minus1 | ||||
|         bs.skipBits(5);                     // dpb_output_delay_length_minus1 | ||||
|         time_offset_length = bs.getBits(5); // time_offset_length | ||||
|         } | ||||
|      int vlc_hrd_parameters_present_flag = bs.getBit(); // vlc_hrd_parameters_present_flag | ||||
|      if (vlc_hrd_parameters_present_flag) { | ||||
|          int cpb_cnt_minus1; | ||||
|          cpb_cnt_minus1 = bs.getUeGolomb();  // cpb_cnt_minus1 | ||||
|          bs.skipBits(4);                     // bit_rate_scale | ||||
|          bs.skipBits(4);                     // cpb_size_scale | ||||
|          for (int i = 0; i < cpb_cnt_minus1; ++i) { | ||||
|              bs.skipUeGolomb();              // bit_rate_value_minus1[i] | ||||
|              bs.skipUeGolomb();              // cpb_size_value_minus1[i] | ||||
|              bs.skipBit();                   // cbr_flag[i] | ||||
|              } | ||||
|          bs.skipBits(5);                     // initial_cpb_removal_delay_length_minus1 | ||||
|          bs.skipBits(5);                     // cpb_removal_delay_length_minus1 | ||||
|          bs.skipBits(5);                     // dpb_output_delay_length_minus1 | ||||
|          time_offset_length = bs.getBits(5); // time_offset_length | ||||
|         } | ||||
|      cpb_dpb_delays_present_flag = (nal_hrd_parameters_present_flag | vlc_hrd_parameters_present_flag); | ||||
|      if (cpb_dpb_delays_present_flag) | ||||
|         bs.skipBit();                       // low_delay_hrd_flag | ||||
|      pic_struct_present_flag = bs.getBit(); // pic_struct_present_flag | ||||
|      if (bs.getBit()) {                     // bitstream_restriction_flag | ||||
|         bs.skipBit();                       // motion_vectors_over_pic_boundaries_flag | ||||
|         bs.skipUeGolomb();                  // max_bytes_per_pic_denom | ||||
|         bs.skipUeGolomb();                  // max_bits_per_mb_denom | ||||
|         bs.skipUeGolomb();                  // log2_max_mv_length_horizontal | ||||
|         bs.skipUeGolomb();                  // log2_max_mv_length_vertical | ||||
|         bs.skipUeGolomb();                  // num_reorder_frames | ||||
|         bs.skipUeGolomb();                  // max_dec_frame_buffering | ||||
|         } | ||||
|      } | ||||
|  | ||||
|   //Dprintf("H.264 SPS: -> video size %dx%d, aspect %d", width, height, aspect_ratio); | ||||
|  | ||||
|   if (m_VideoHandler) { | ||||
|      m_VideoHandler->SetVideoFormat(format); | ||||
|      m_VideoHandler->SetVideoSize(width, height); | ||||
|      m_VideoHandler->SetVideoAspectRatio(aspect_ratio); | ||||
|      } | ||||
|   m_Width = width; | ||||
|   m_Height = height; | ||||
|   m_AspectRatio = aspect_ratio; | ||||
|   m_Format = format; | ||||
|   m_CpbDpbDelaysPresentFlag = cpb_dpb_delays_present_flag; | ||||
|   m_PicStructPresentFlag = pic_struct_present_flag; | ||||
|   m_TimeOffsetLength = time_offset_length; | ||||
|  | ||||
|   return (bs.getIndex() / 8); | ||||
| } | ||||
| @@ -277,10 +373,12 @@ int cFemonH264::parseSPS(const uint8_t *buf, int len) | ||||
| int cFemonH264::parseSEI(const uint8_t *buf, int len) | ||||
| { | ||||
|   int num_referenced_subseqs, i; | ||||
|   double frame_rate = 0, bit_rate = 0; | ||||
|   eVideoScan scan = VIDEO_SCAN_INVALID; | ||||
|   cBitStream bs(buf, len); | ||||
|  | ||||
|   double frame_rate = m_FrameRate; | ||||
|   double bit_rate = m_BitRate; | ||||
|   eVideoScan scan = m_Scan; | ||||
|  | ||||
|   while ((bs.getIndex() * 8 + 16) < len) {               // sei_message | ||||
|     int lastByte, payloadSize = 0, payloadType = 0; | ||||
|  | ||||
| @@ -297,23 +395,60 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len) | ||||
|     } while (lastByte == 0xFF); | ||||
|  | ||||
|     switch (payloadType) {                               // sei_payload | ||||
|       //case 1:                                          // pic_timing | ||||
|       //     ... | ||||
|       //     switch (bs.getBits(2)) {                    // ct_type | ||||
|       //       case 0: | ||||
|       //            scan = VIDEO_SCAN_PROGRESSIVE; | ||||
|       //            break; | ||||
|       //       case 1: | ||||
|       //            scan = VIDEO_SCAN_INTERLACED; | ||||
|       //            break; | ||||
|       //       case 2: | ||||
|       //            scan = VIDEO_SCAN_UNKNOWN; | ||||
|       //            break; | ||||
|       //       default: | ||||
|       //            scan = VIDEO_SCAN_RESERVED; | ||||
|       //            break; | ||||
|       //       } | ||||
|       //     break; | ||||
|       case 1:                                            // pic_timing | ||||
|            if (m_CpbDpbDelaysPresentFlag) {              // cpb_dpb_delays_present_flag | ||||
|               bs.skipUeGolomb();                         // cpb_removal_delay | ||||
|               bs.skipUeGolomb();                         // dpb_output_delay | ||||
|               } | ||||
|            if (m_PicStructPresentFlag) {                // pic_struct_present_flag | ||||
|               unsigned int pic_struct = bs.getBits(4);  // pic_struct | ||||
|               if (pic_struct >= (sizeof(s_SeiNumClockTsTable) ) / sizeof(s_SeiNumClockTsTable[0])) | ||||
|                  return 0; | ||||
|               for (int i = 0; i < s_SeiNumClockTsTable[pic_struct]; ++i) { | ||||
|                   if (bs.getBit()) {                     // clock_timestamp_flag[i] | ||||
|                      int full_timestamp_flag; | ||||
|                      switch (bs.getBits(2)) {            // ct_type | ||||
|                        case 0: | ||||
|                             scan = VIDEO_SCAN_PROGRESSIVE; | ||||
|                             break; | ||||
|                        case 1: | ||||
|                             scan = VIDEO_SCAN_INTERLACED; | ||||
|                             break; | ||||
|                        case 2: | ||||
|                             scan = VIDEO_SCAN_UNKNOWN; | ||||
|                             break; | ||||
|                        default: | ||||
|                             scan = VIDEO_SCAN_RESERVED; | ||||
|                             break; | ||||
|                        } | ||||
|                      //Dprintf("\nH.264 SEI: -> scan type %d", bit_rate, scan); | ||||
|                      bs.skipBit();                       // nuit_field_based_flag | ||||
|                      bs.skipBits(5);                     // counting_type | ||||
|                      full_timestamp_flag = bs.getBit();  // full_timestamp_flag | ||||
|                      bs.skipBit();                       // discontinuity_flag | ||||
|                      bs.skipBit();                       // cnt_dropped_flag | ||||
|                      bs.skipBits(8);                     // n_frames | ||||
|                      if (full_timestamp_flag) { | ||||
|                         bs.skipBits(6);                  // seconds_value | ||||
|                         bs.skipBits(6);                  // minutes_value | ||||
|                         bs.skipBits(5);                  // hours_value | ||||
|                         } | ||||
|                      else { | ||||
|                         if (bs.getBit()) {               // seconds_flag | ||||
|                            bs.skipBits(6);               // seconds_value | ||||
|                            if (bs.getBit()) {            // minutes_flag | ||||
|                               bs.skipBits(6);            // minutes_value | ||||
|                               if (bs.getBit())           // hours_flag | ||||
|                                   bs.skipBits(5);        // hours_value | ||||
|                               } | ||||
|                            } | ||||
|                         } | ||||
|                      if (m_TimeOffsetLength > 0) | ||||
|                         bs.skipBits(m_TimeOffsetLength); // time_offset | ||||
|                      } | ||||
|                   } | ||||
|               } | ||||
|            break; | ||||
|  | ||||
|       case 12:                                          // sub_seq_characteristics | ||||
|            bs.skipUeGolomb();                           // sub_seq_layer_num | ||||
| @@ -322,9 +457,9 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len) | ||||
|               bs.skipBits(32);                          // sub_seq_duration | ||||
|            if (bs.getBit()) {                           // average_rate_flag | ||||
|               bs.skipBit();                             // accurate_statistics_flag | ||||
|               bit_rate   = bs.getU16();                 // average_bit_rate | ||||
|               frame_rate = bs.getU16();                 // average_frame_rate | ||||
|               //Dprintf("H.264 SEI: -> stream bitrate %.1f, frame rate %.1f", sei->bitrate, sei->frame_rate); | ||||
|               bit_rate   = bs.getU16() / 1048.51;       // average_bit_rate (1000 bit/s -> Mbit/s) | ||||
|               frame_rate = bs.getU16() / 256.0;         // average_frame_rate (frames/256s) | ||||
|               //Dprintf("\nH.264 SEI: -> stream bitrate %.1f, frame rate %.1f", bit_rate, frame_rate); | ||||
|               } | ||||
|            num_referenced_subseqs = bs.getUeGolomb();   // num_referenced_subseqs | ||||
|            for (i = 0; i < num_referenced_subseqs; ++i) { | ||||
| @@ -343,11 +478,9 @@ int cFemonH264::parseSEI(const uint8_t *buf, int len) | ||||
|     bs.byteAlign(); | ||||
|     } | ||||
|  | ||||
|   if (m_VideoHandler) { | ||||
|      m_VideoHandler->SetVideoFramerate(frame_rate); | ||||
|      m_VideoHandler->SetVideoBitrate(bit_rate); | ||||
|      m_VideoHandler->SetVideoScan(scan); | ||||
|      } | ||||
|   m_FrameRate = frame_rate; | ||||
|   m_BitRate = bit_rate; | ||||
|   m_Scan = scan; | ||||
|  | ||||
|   return (bs.getIndex() / 8); | ||||
| } | ||||
|   | ||||
							
								
								
									
										11
									
								
								femonh264.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								femonh264.h
									
									
									
									
									
								
							| @@ -20,6 +20,16 @@ private: | ||||
|   }; | ||||
|  | ||||
|   cFemonVideoIf *m_VideoHandler; | ||||
|   unsigned int m_Width; | ||||
|   unsigned int m_Height; | ||||
|   eVideoAspectRatio m_AspectRatio; | ||||
|   eVideoFormat m_Format; | ||||
|   double m_FrameRate; | ||||
|   double m_BitRate; | ||||
|   eVideoScan m_Scan; | ||||
|   bool m_CpbDpbDelaysPresentFlag; | ||||
|   bool m_PicStructPresentFlag; | ||||
|   unsigned int m_TimeOffsetLength; | ||||
|  | ||||
|   const uint8_t *nextStartCode(const uint8_t *start, const uint8_t *end); | ||||
|   int nalUnescape(uint8_t *dst, const uint8_t *src, int len); | ||||
| @@ -28,6 +38,7 @@ private: | ||||
|  | ||||
|   static const eVideoAspectRatio s_AspectRatios[]; | ||||
|   static const eVideoFormat s_VideoFormats[]; | ||||
|   static const uint8_t s_SeiNumClockTsTable[9]; | ||||
|  | ||||
| public: | ||||
|   cFemonH264(cFemonVideoIf *videohandler); | ||||
|   | ||||
							
								
								
									
										14
									
								
								femonosd.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								femonosd.c
									
									
									
									
									
								
							| @@ -493,7 +493,7 @@ void cFemonOsd::Action(void) | ||||
|        DrawStatusWindow(); | ||||
|        } | ||||
|     else if (m_SvdrpConnection.handle >= 0) { | ||||
|        cmd.handle = m_SvdrpConnection.handle;  | ||||
|        cmd.handle = m_SvdrpConnection.handle; | ||||
|        m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd); | ||||
|        if (cmd.responseCode == 900) { | ||||
|           for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) { | ||||
| @@ -576,7 +576,7 @@ void cFemonOsd::Show(void) | ||||
|         if (channel) { | ||||
|            IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0); | ||||
|            IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0); | ||||
|            m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid); | ||||
|            m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid); | ||||
|            cDevice::ActualDevice()->AttachReceiver(m_Receiver); | ||||
|            } | ||||
|         } | ||||
| @@ -621,7 +621,7 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber) | ||||
|      if (channel) { | ||||
|         IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0); | ||||
|         IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0); | ||||
|         m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid); | ||||
|         m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid); | ||||
|         cDevice::ActualDevice()->AttachReceiver(m_Receiver); | ||||
|         } | ||||
|      } | ||||
| @@ -642,7 +642,7 @@ void cFemonOsd::SetAudioTrack(int Index, const char * const *Tracks) | ||||
|      if (channel) { | ||||
|         IS_AUDIO_TRACK(track) ? apid[0] = channel->Apid(int(track - ttAudioFirst)) : apid[0] = channel->Apid(0); | ||||
|         IS_DOLBY_TRACK(track) ? dpid[0] = channel->Dpid(int(track - ttDolbyFirst)) : dpid[0] = channel->Dpid(0); | ||||
|         m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vpid(), apid, dpid); | ||||
|         m_Receiver = new cFemonReceiver(channel->GetChannelID(), channel->Ca(), channel->Vtype(), channel->Vpid(), apid, dpid); | ||||
|         cDevice::ActualDevice()->AttachReceiver(m_Receiver); | ||||
|         } | ||||
|      } | ||||
| @@ -693,7 +693,7 @@ bool cFemonOsd::SvdrpConnect(void) | ||||
|          m_SvdrpPlugin->Service("SvdrpConnection-v1.0", &m_SvdrpConnection); | ||||
|          if (m_SvdrpConnection.handle >= 0) { | ||||
|             SvdrpCommand_v1_0 cmd; | ||||
|             cmd.handle = m_SvdrpConnection.handle;  | ||||
|             cmd.handle = m_SvdrpConnection.handle; | ||||
|             cmd.command = cString::sprintf("PLUG %s\r\n", PLUGIN_NAME_I18N); | ||||
|             m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd); | ||||
|             if (cmd.responseCode != 214) { | ||||
| @@ -716,7 +716,7 @@ bool cFemonOsd::SvdrpTune(void) | ||||
|       cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); | ||||
|       if (channel) { | ||||
|          SvdrpCommand_v1_0 cmd; | ||||
|          cmd.handle = m_SvdrpConnection.handle;  | ||||
|          cmd.handle = m_SvdrpConnection.handle; | ||||
|          cmd.command = cString::sprintf("CHAN %s\r\n", *channel->GetChannelID().ToString()); | ||||
|          m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd); | ||||
|          if (cmd.responseCode == 250) | ||||
| @@ -765,7 +765,7 @@ double cFemonOsd::GetDolbyBitrate(void) | ||||
| } | ||||
|  | ||||
| eOSState cFemonOsd::ProcessKey(eKeys Key) | ||||
| {  | ||||
| { | ||||
|   eOSState state = cOsdObject::ProcessKey(Key); | ||||
|   if (state == osUnknown) { | ||||
|      switch (Key) { | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #include "femoncfg.h" | ||||
| #include "femonreceiver.h" | ||||
|  | ||||
| cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[]) | ||||
| cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid, int Apid[], int Dpid[]) | ||||
| : cReceiver(ChannelID, -1, Vpid, Apid, Dpid, NULL), | ||||
|   cThread("femon receiver"), | ||||
|   m_Sleep(), | ||||
| @@ -19,6 +19,7 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[ | ||||
|   m_DetectMPEG(this, this), | ||||
|   m_DetectAAC(this), | ||||
|   m_DetectAC3(this), | ||||
|   m_VideoType(Vtype), | ||||
|   m_VideoPid(Vpid), | ||||
|   m_VideoPacketCount(0), | ||||
|   m_VideoBitrate(0.0), | ||||
| @@ -28,7 +29,7 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[ | ||||
|   m_AudioBitrate(0.0), | ||||
|   m_AudioValid(false), | ||||
|   m_AC3Pid(Dpid[0]), | ||||
|   m_AC3PacketCount(0),  | ||||
|   m_AC3PacketCount(0), | ||||
|   m_AC3Bitrate(0), | ||||
|   m_AC3Valid(false) | ||||
| { | ||||
| @@ -93,10 +94,18 @@ void cFemonReceiver::Receive(uchar *Data, int Length) | ||||
|         m_VideoPacketCount++; | ||||
|         if (TsPayloadStart(Data)) { | ||||
|            while (const uint8_t *p = m_VideoAssembler.GetPes(len)) { | ||||
|              if (m_DetectMPEG.processVideo(p, len) || m_DetectH264.processVideo(p, len)) { | ||||
|                 m_VideoValid = true; | ||||
|                 break; | ||||
|                 } | ||||
|                if (m_VideoType == 0x1B) { // MPEG4 | ||||
|                   if (m_DetectH264.processVideo(p, len)) { | ||||
|                      m_VideoValid = true; | ||||
|                      break; | ||||
|                      } | ||||
|                   } | ||||
|                else { | ||||
|                   if (m_DetectMPEG.processVideo(p, len)) { | ||||
|                      m_VideoValid = true; | ||||
|                      break; | ||||
|                      } | ||||
|                   } | ||||
|              } | ||||
|            m_VideoAssembler.Reset(); | ||||
|          } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ private: | ||||
|   cFemonAC3     m_DetectAC3; | ||||
|  | ||||
|   cTsToPes      m_VideoAssembler; | ||||
|   int           m_VideoType; | ||||
|   int           m_VideoPid; | ||||
|   int           m_VideoPacketCount; | ||||
|   double        m_VideoBitrate; | ||||
| @@ -81,7 +82,7 @@ public: | ||||
|   virtual void SetAC3LFE(bool onoff)                 { m_AC3Info.lfe = onoff; } | ||||
|  | ||||
| public: | ||||
|   cFemonReceiver(tChannelID ChannelID, int Ca, int Vpid, int Apid[], int Dpid[]); | ||||
|   cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid, int Apid[], int Dpid[]); | ||||
|   virtual ~cFemonReceiver(); | ||||
|   void Deactivate(void); | ||||
|  | ||||
|   | ||||
							
								
								
									
										36
									
								
								femontools.h
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								femontools.h
									
									
									
									
									
								
							| @@ -79,23 +79,25 @@ public: | ||||
|   cBitStream(const uint8_t *buf, const int len); | ||||
|   ~cBitStream(); | ||||
|  | ||||
|   int      getBit(); | ||||
|   uint32_t getBits(uint32_t n); | ||||
|   void     skipBits(uint32_t n); | ||||
|   uint32_t getUeGolomb(); | ||||
|   int32_t  getSeGolomb(); | ||||
|   void     skipGolomb(); | ||||
|   void     skipUeGolomb(); | ||||
|   void     skipSeGolomb(); | ||||
|   void     byteAlign(); | ||||
|   void     skipBit()      { skipBits(1); } | ||||
|   uint32_t getU8()        { return getBits(8); } | ||||
|   uint32_t getU16()       { return ((getBits(8) << 8) | getBits(8)); } | ||||
|   uint32_t getU24()       { return ((getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); } | ||||
|   uint32_t getU32()       { return ((getBits(8) << 24) | (getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); } | ||||
|   bool     isEOF()        { return (index >= count); } | ||||
|   void     reset()        { index = 0; } | ||||
|   int      getIndex()     { return (isEOF() ? count : index);} | ||||
|   int            getBit(); | ||||
|   uint32_t       getBits(uint32_t n); | ||||
|   void           skipBits(uint32_t n); | ||||
|   uint32_t       getUeGolomb(); | ||||
|   int32_t        getSeGolomb(); | ||||
|   void           skipGolomb(); | ||||
|   void           skipUeGolomb(); | ||||
|   void           skipSeGolomb(); | ||||
|   void           byteAlign(); | ||||
|  | ||||
|   void           skipBit()  { skipBits(1); } | ||||
|   uint32_t       getU8()    { return getBits(8); } | ||||
|   uint32_t       getU16()   { return ((getBits(8) << 8) | getBits(8)); } | ||||
|   uint32_t       getU24()   { return ((getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); } | ||||
|   uint32_t       getU32()   { return ((getBits(8) << 24) | (getBits(8) << 16) | (getBits(8) << 8) | getBits(8)); } | ||||
|   bool           isEOF()    { return (index >= count); } | ||||
|   void           reset()    { index = 0; } | ||||
|   int            getIndex() { return (isEOF() ? count : index); } | ||||
|   const uint8_t *getData()  { return (isEOF() ? NULL : data + (index / 8)); } | ||||
| }; | ||||
|  | ||||
| #endif // __FEMONTOOLS_H | ||||
|   | ||||
		Reference in New Issue
	
	Block a user