liveMedia/H264VideoStreamFramer.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
00018 // A filter that breaks up a H.264 Video Elementary Stream into NAL units.
00019 // Implementation
00020 
00021 #include "H264VideoStreamFramer.hh"
00022 #include "MPEGVideoStreamParser.hh"
00023 #include "BitVector.hh"
00024 #include "H264VideoRTPSource.hh" // for "parseSPropParameterSets()"
00025 
00027 
00028 class H264VideoStreamParser: public MPEGVideoStreamParser {
00029 public:
00030   H264VideoStreamParser(H264VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean includeStartCodeInOutput);
00031   virtual ~H264VideoStreamParser();
00032 
00033 private: // redefined virtual functions:
00034   virtual void flushInput();
00035   virtual unsigned parse();
00036 
00037 private:
00038   H264VideoStreamFramer* usingSource() {
00039     return (H264VideoStreamFramer*)fUsingSource;
00040   }
00041 
00042   void removeEmulationBytes(u_int8_t* nalUnitCopy, unsigned maxSize, unsigned& nalUnitCopySize);
00043 
00044   void analyze_seq_parameter_set_data(unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag);
00045   void analyze_vui_parameters(BitVector& bv,
00046                               unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag);
00047 #ifdef DO_FULL_SPS_PARSING
00048   void analyze_hrd_parameters(BitVector& bv);
00049 #endif
00050   void analyze_sei_data();
00051   void analyze_slice_header(u_int8_t* start, u_int8_t* end, u_int8_t nal_unit_type,
00052                             unsigned &frame_num, unsigned &pic_parameter_set_id, unsigned& idr_pic_id,
00053                             Boolean& field_pic_flag, Boolean& bottom_field_flag);
00054 
00055 private:
00056   unsigned fOutputStartCodeSize;
00057   Boolean fHaveSeenFirstStartCode, fHaveSeenFirstByteOfNALUnit;
00058   u_int8_t fFirstByteOfNALUnit;
00059 
00060   // Fields in H.264 headers, used in parsing:
00061   unsigned log2_max_frame_num; // log2_max_frame_num_minus4 + 4
00062   Boolean separate_colour_plane_flag;
00063   Boolean frame_mbs_only_flag;
00064 };
00065 
00066 
00068 
00069 H264VideoStreamFramer* H264VideoStreamFramer
00070 ::createNew(UsageEnvironment& env, FramedSource* inputSource, Boolean includeStartCodeInOutput) {
00071   return new H264VideoStreamFramer(env, inputSource, True, includeStartCodeInOutput);
00072 }
00073 
00074 H264VideoStreamFramer
00075 ::H264VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource, Boolean createParser, Boolean includeStartCodeInOutput)
00076   : MPEGVideoStreamFramer(env, inputSource),
00077     fIncludeStartCodeInOutput(includeStartCodeInOutput),
00078     fLastSeenSPS(NULL), fLastSeenSPSSize(0), fLastSeenPPS(NULL), fLastSeenPPSSize(0) {
00079   fParser = createParser
00080     ? new H264VideoStreamParser(this, inputSource, includeStartCodeInOutput)
00081     : NULL;
00082   fNextPresentationTime = fPresentationTimeBase;
00083   fFrameRate = 25.0; // We assume a frame rate of 25 fps, unless we learn otherwise (from parsing a Sequence Parameter Set NAL unit)
00084 }
00085 
00086 H264VideoStreamFramer::~H264VideoStreamFramer() {
00087   delete[] fLastSeenSPS;
00088   delete[] fLastSeenPPS;
00089 }
00090 
00091 void H264VideoStreamFramer::setSPSandPPS(char const* sPropParameterSetsStr) {
00092   unsigned numSPropRecords;
00093   SPropRecord* sPropRecords = parseSPropParameterSets(sPropParameterSetsStr, numSPropRecords);
00094   for (unsigned i = 0; i < numSPropRecords; ++i) {
00095     if (sPropRecords[i].sPropLength == 0) continue; // bad data
00096     u_int8_t nal_unit_type = (sPropRecords[i].sPropBytes[0])&0x1F;
00097     if (nal_unit_type == 7/*SPS*/) {
00098       saveCopyOfSPS(sPropRecords[i].sPropBytes, sPropRecords[i].sPropLength);
00099     } else if (nal_unit_type == 8/*PPS*/) {
00100       saveCopyOfPPS(sPropRecords[i].sPropBytes, sPropRecords[i].sPropLength);
00101     }
00102   }
00103   delete[] sPropRecords;
00104 }
00105 
00106 void H264VideoStreamFramer::saveCopyOfSPS(u_int8_t* from, unsigned size) {
00107   delete[] fLastSeenSPS;
00108   fLastSeenSPS = new u_int8_t[size];
00109   memmove(fLastSeenSPS, from, size);
00110 
00111   fLastSeenSPSSize = size;
00112 }
00113 
00114 void H264VideoStreamFramer::saveCopyOfPPS(u_int8_t* from, unsigned size) {
00115   delete[] fLastSeenPPS;
00116   fLastSeenPPS = new u_int8_t[size];
00117   memmove(fLastSeenPPS, from, size);
00118 
00119   fLastSeenPPSSize = size;
00120 }
00121 
00122 Boolean H264VideoStreamFramer::isH264VideoStreamFramer() const {
00123   return True;
00124 }
00125 
00126 
00128 
00129 H264VideoStreamParser
00130 ::H264VideoStreamParser(H264VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean includeStartCodeInOutput)
00131   : MPEGVideoStreamParser(usingSource, inputSource),
00132     fOutputStartCodeSize(includeStartCodeInOutput ? 4 : 0), fHaveSeenFirstStartCode(False), fHaveSeenFirstByteOfNALUnit(False),
00133     // Default values for our parser variables (in case they're not set explicitly in headers that we parse:
00134     log2_max_frame_num(5), separate_colour_plane_flag(False), frame_mbs_only_flag(True) {
00135 }
00136 
00137 H264VideoStreamParser::~H264VideoStreamParser() {
00138 }
00139 
00140 void H264VideoStreamParser::removeEmulationBytes(u_int8_t* nalUnitCopy, unsigned maxSize, unsigned& nalUnitCopySize) {
00141   u_int8_t* nalUnitOrig = fStartOfFrame + fOutputStartCodeSize;
00142   unsigned const NumBytesInNALunit = fTo - nalUnitOrig;
00143   if (NumBytesInNALunit > maxSize) return;
00144   nalUnitCopySize = 0;
00145   for (unsigned i = 0; i < NumBytesInNALunit; ++i) {
00146     if (i+2 < NumBytesInNALunit && nalUnitOrig[i] == 0 && nalUnitOrig[i+1] == 0 && nalUnitOrig[i+2] == 3) {
00147       nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i++];
00148       nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i++];
00149     } else {
00150       nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i];
00151     }
00152   }
00153 }
00154 
00155 #ifdef DEBUG
00156 char const* nal_unit_type_description[32] = {
00157   "Unspecified", //0
00158   "Coded slice of a non-IDR picture", //1
00159   "Coded slice data partition A", //2
00160   "Coded slice data partition B", //3
00161   "Coded slice data partition C", //4
00162   "Coded slice of an IDR picture", //5
00163   "Supplemental enhancement information (SEI)", //6
00164   "Sequence parameter set", //7
00165   "Picture parameter set", //8
00166   "Access unit delimiter", //9
00167   "End of sequence", //10
00168   "End of stream", //11
00169   "Filler data", //12
00170   "Sequence parameter set extension", //13
00171   "Prefix NAL unit", //14
00172   "Subset sequence parameter set", //15
00173   "Reserved", //16
00174   "Reserved", //17
00175   "Reserved", //18
00176   "Coded slice of an auxiliary coded picture without partitioning", //19
00177   "Coded slice extension", //20
00178   "Reserved", //21
00179   "Reserved", //22
00180   "Reserved", //23
00181   "Unspecified", //24
00182   "Unspecified", //25
00183   "Unspecified", //26
00184   "Unspecified", //27
00185   "Unspecified", //28
00186   "Unspecified", //29
00187   "Unspecified", //30
00188   "Unspecified" //31
00189 };
00190 #endif
00191 
00192 #ifdef DEBUG
00193 static unsigned numDebugTabs = 1;
00194 #define DEBUG_PRINT_TABS for (unsigned _i = 0; _i < numDebugTabs; ++_i) fprintf(stderr, "\t")
00195 #define DEBUG_PRINT(x) do { DEBUG_PRINT_TABS; fprintf(stderr, "%s: %d\n", #x, x); } while (0)
00196 #define DEBUG_STR(x) do { DEBUG_PRINT_TABS; fprintf(stderr, "%s\n", x); } while (0)
00197 class DebugTab {
00198 public:
00199   DebugTab() {++numDebugTabs;}
00200   ~DebugTab() {--numDebugTabs;}
00201 };
00202 #define DEBUG_TAB DebugTab dummy
00203 #else
00204 #define DEBUG_PRINT(x) do {x = x;} while (0)
00205     // Note: the "x=x;" statement is intended to eliminate "unused variable" compiler warning messages
00206 #define DEBUG_STR(x) do {} while (0)
00207 #define DEBUG_TAB do {} while (0)
00208 #endif
00209 
00210 #ifdef DO_FULL_SPS_PARSING
00211 void H264VideoStreamParser::analyze_hrd_parameters(BitVector& bv) {
00212   DEBUG_STR("BEGIN hrd_parameters");
00213   unsigned cpb_cnt_minus1 = bv.get_expGolomb();
00214   DEBUG_PRINT(cpb_cnt_minus1);
00215   unsigned bit_rate_scale = bv.getBits(4);
00216   DEBUG_PRINT(bit_rate_scale);
00217   unsigned cpb_size_scale = bv.getBits(4);
00218   DEBUG_PRINT(cpb_size_scale);
00219   for (unsigned SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; ++SchedSelIdx) {
00220     DEBUG_TAB;
00221     unsigned bit_rate_value_minus1 = bv.get_expGolomb();
00222     DEBUG_PRINT(bit_rate_value_minus1);
00223     unsigned cpb_size_value_minus1 = bv.get_expGolomb();
00224     DEBUG_PRINT(cpb_size_value_minus1);
00225     unsigned cbr_flag = bv.get1Bit();
00226     DEBUG_PRINT(cbr_flag);
00227   }
00228   unsigned initial_cpb_removal_delay_length_minus1 = bv.getBits(5);
00229   DEBUG_PRINT(initial_cpb_removal_delay_length_minus1);
00230   unsigned cpb_removal_delay_length_minus1 = bv.getBits(5);
00231   DEBUG_PRINT(cpb_removal_delay_length_minus1);
00232   unsigned dpb_output_delay_length_minus1 = bv.getBits(5);
00233   DEBUG_PRINT(dpb_output_delay_length_minus1);
00234   unsigned time_offset_length = bv.getBits(5);
00235   DEBUG_PRINT(time_offset_length);
00236   DEBUG_STR("END hrd_parameters");
00237 }
00238 #endif
00239 
00240 void H264VideoStreamParser
00241 ::analyze_vui_parameters(BitVector& bv,
00242                          unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag) {
00243   DEBUG_STR("BEGIN vui_parameters");
00244   unsigned aspect_ratio_info_present_flag = bv.get1Bit();
00245   DEBUG_PRINT(aspect_ratio_info_present_flag);
00246   if (aspect_ratio_info_present_flag) {
00247     DEBUG_TAB;
00248     unsigned aspect_ratio_idc = bv.getBits(8);
00249     DEBUG_PRINT(aspect_ratio_idc);
00250     if (aspect_ratio_idc == 255/*Extended_SAR*/) {
00251       bv.skipBits(32); // sar_width; sar_height
00252     }
00253   }
00254   unsigned overscan_info_present_flag = bv.get1Bit();
00255   DEBUG_PRINT(overscan_info_present_flag);
00256   if (overscan_info_present_flag) {
00257     bv.skipBits(1); // overscan_appropriate_flag
00258   }
00259   unsigned video_signal_type_present_flag = bv.get1Bit();
00260   DEBUG_PRINT(video_signal_type_present_flag);
00261   if (video_signal_type_present_flag) {
00262     DEBUG_TAB;
00263     bv.skipBits(4); // video_format; video_full_range_flag
00264     unsigned colour_description_present_flag = bv.get1Bit();
00265     DEBUG_PRINT(colour_description_present_flag);
00266     if (colour_description_present_flag) {
00267       bv.skipBits(24); // colour_primaries; transfer_characteristics; matrix_coefficients
00268     }
00269   }
00270   unsigned chroma_loc_info_present_flag = bv.get1Bit();
00271   DEBUG_PRINT(chroma_loc_info_present_flag);
00272   if (chroma_loc_info_present_flag) {
00273     (void)bv.get_expGolomb(); // chroma_sample_loc_type_top_field
00274     (void)bv.get_expGolomb(); // chroma_sample_loc_type_bottom_field
00275   }
00276   unsigned timing_info_present_flag = bv.get1Bit();
00277   DEBUG_PRINT(timing_info_present_flag);
00278   if (timing_info_present_flag) {
00279     DEBUG_TAB;
00280     num_units_in_tick = bv.getBits(32);
00281     DEBUG_PRINT(num_units_in_tick);
00282     time_scale = bv.getBits(32);
00283     DEBUG_PRINT(time_scale);
00284     fixed_frame_rate_flag = bv.get1Bit();
00285     DEBUG_PRINT(fixed_frame_rate_flag);
00286   }
00287 #ifdef DO_FULL_SPS_PARSING
00288   unsigned nal_hrd_parameters_present_flag = bv.get1Bit();
00289   DEBUG_PRINT(nal_hrd_parameters_present_flag);
00290   if (nal_hrd_parameters_present_flag) {
00291     DEBUG_TAB;
00292     analyze_hrd_parameters(bv);
00293   }
00294   unsigned vcl_hrd_parameters_present_flag = bv.get1Bit();
00295   DEBUG_PRINT(vcl_hrd_parameters_present_flag);
00296   if (vcl_hrd_parameters_present_flag) {
00297     DEBUG_TAB;
00298     analyze_hrd_parameters(bv);
00299   }
00300   if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
00301     bv.skipBits(1); // low_delay_hrd_flag
00302   }
00303   bv.skipBits(1); // pic_struct_present_flag
00304   unsigned bitstream_restriction_flag = bv.get1Bit();
00305   DEBUG_PRINT(bitstream_restriction_flag);
00306   if (bitstream_restriction_flag) {
00307     bv.skipBits(1); // motion_vectors_over_pic_boundaries_flag
00308     (void)bv.get_expGolomb(); // max_bytes_per_pic_denom
00309     (void)bv.get_expGolomb(); // max_bits_per_mb_denom
00310     (void)bv.get_expGolomb(); // log2_max_mv_length_horizontal
00311     (void)bv.get_expGolomb(); // log2_max_mv_length_vertical
00312     (void)bv.get_expGolomb(); // num_reorder_frames
00313     (void)bv.get_expGolomb(); // max_dec_frame_buffering
00314   }
00315   DEBUG_STR("END vui_parameters");
00316 #endif
00317 }
00318 
00319 #define SPS_MAX_SIZE 1000 // larger than the largest possible SPS (Sequence Parameter Set) NAL unit
00320 
00321 void H264VideoStreamParser
00322 ::analyze_seq_parameter_set_data(unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag) {
00323   num_units_in_tick = time_scale = fixed_frame_rate_flag = 0; // default values
00324 
00325   // Begin by making a copy of the NAL unit data, removing any 'emulation prevention' bytes:
00326   u_int8_t sps[SPS_MAX_SIZE];
00327   unsigned spsSize;
00328   removeEmulationBytes(sps, sizeof sps, spsSize);
00329 
00330   BitVector bv(sps, 0, 8*spsSize);
00331 
00332   bv.skipBits(8); // forbidden_zero_bit; nal_ref_idc; nal_unit_type
00333   unsigned profile_idc = bv.getBits(8);
00334   DEBUG_PRINT(profile_idc);
00335   unsigned constraint_setN_flag = bv.getBits(8); // also "reserved_zero_2bits" at end
00336   DEBUG_PRINT(constraint_setN_flag);
00337   unsigned level_idc = bv.getBits(8);
00338   DEBUG_PRINT(level_idc);
00339   unsigned seq_parameter_set_id = bv.get_expGolomb();
00340   DEBUG_PRINT(seq_parameter_set_id);
00341   if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ) {
00342     DEBUG_TAB;
00343     unsigned chroma_format_idc = bv.get_expGolomb();
00344     DEBUG_PRINT(chroma_format_idc);
00345     if (chroma_format_idc == 3) {
00346       DEBUG_TAB;
00347       separate_colour_plane_flag = bv.get1Bit();
00348       DEBUG_PRINT(separate_colour_plane_flag);
00349     }
00350     (void)bv.get_expGolomb(); // bit_depth_luma_minus8
00351     (void)bv.get_expGolomb(); // bit_depth_chroma_minus8
00352     bv.skipBits(1); // qpprime_y_zero_transform_bypass_flag
00353     unsigned seq_scaling_matrix_present_flag = bv.get1Bit();
00354     DEBUG_PRINT(seq_scaling_matrix_present_flag);
00355     if (seq_scaling_matrix_present_flag) {
00356       for (int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); ++i) {
00357         DEBUG_TAB;
00358         DEBUG_PRINT(i);
00359         unsigned seq_scaling_list_present_flag = bv.get1Bit();
00360         DEBUG_PRINT(seq_scaling_list_present_flag);
00361         if (seq_scaling_list_present_flag) {
00362           DEBUG_TAB;
00363           unsigned sizeOfScalingList = i < 6 ? 16 : 64;
00364           unsigned lastScale = 8;
00365           unsigned nextScale = 8;
00366           for (unsigned j = 0; j < sizeOfScalingList; ++j) {
00367             DEBUG_TAB;
00368             DEBUG_PRINT(j);
00369             DEBUG_PRINT(nextScale);
00370             if (nextScale != 0) {
00371               DEBUG_TAB;
00372               unsigned delta_scale = bv.get_expGolomb();
00373               DEBUG_PRINT(delta_scale);
00374               nextScale = (lastScale + delta_scale + 256) % 256;
00375             }
00376             lastScale = (nextScale == 0) ? lastScale : nextScale;
00377             DEBUG_PRINT(lastScale);
00378           }
00379         }
00380       }
00381     }
00382   }
00383   unsigned log2_max_frame_num_minus4 = bv.get_expGolomb();
00384   DEBUG_PRINT(log2_max_frame_num_minus4);
00385   log2_max_frame_num = log2_max_frame_num_minus4 + 4;
00386   unsigned pic_order_cnt_type = bv.get_expGolomb();
00387   DEBUG_PRINT(pic_order_cnt_type);
00388   if (pic_order_cnt_type == 0) {
00389     DEBUG_TAB;
00390     unsigned log2_max_pic_order_cnt_lsb_minus4 = bv.get_expGolomb();
00391     DEBUG_PRINT(log2_max_pic_order_cnt_lsb_minus4);
00392   } else if (pic_order_cnt_type == 1) {
00393     DEBUG_TAB;
00394     bv.skipBits(1); // delta_pic_order_always_zero_flag
00395     (void)bv.get_expGolomb(); // offset_for_non_ref_pic
00396     (void)bv.get_expGolomb(); // offset_for_top_to_bottom_field
00397     unsigned num_ref_frames_in_pic_order_cnt_cycle = bv.get_expGolomb();
00398     DEBUG_PRINT(num_ref_frames_in_pic_order_cnt_cycle);
00399     for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
00400       (void)bv.get_expGolomb(); // offset_for_ref_frame[i]
00401     }
00402   }
00403   unsigned max_num_ref_frames = bv.get_expGolomb();
00404   DEBUG_PRINT(max_num_ref_frames);
00405   unsigned gaps_in_frame_num_value_allowed_flag = bv.get1Bit();
00406   DEBUG_PRINT(gaps_in_frame_num_value_allowed_flag);
00407   unsigned pic_width_in_mbs_minus1 = bv.get_expGolomb();
00408   DEBUG_PRINT(pic_width_in_mbs_minus1);
00409   unsigned pic_height_in_map_units_minus1 = bv.get_expGolomb();
00410   DEBUG_PRINT(pic_height_in_map_units_minus1);
00411   frame_mbs_only_flag = bv.get1Bit();
00412   DEBUG_PRINT(frame_mbs_only_flag);
00413   if (!frame_mbs_only_flag) {
00414     bv.skipBits(1); // mb_adaptive_frame_field_flag
00415   }
00416   bv.skipBits(1); // direct_8x8_inference_flag
00417   unsigned frame_cropping_flag = bv.get1Bit();
00418   DEBUG_PRINT(frame_cropping_flag);
00419   if (frame_cropping_flag) {
00420     (void)bv.get_expGolomb(); // frame_crop_left_offset
00421     (void)bv.get_expGolomb(); // frame_crop_right_offset
00422     (void)bv.get_expGolomb(); // frame_crop_top_offset
00423     (void)bv.get_expGolomb(); // frame_crop_bottom_offset
00424   }
00425   unsigned vui_parameters_present_flag = bv.get1Bit();
00426   DEBUG_PRINT(vui_parameters_present_flag);
00427   if (vui_parameters_present_flag) {
00428     DEBUG_TAB;
00429     analyze_vui_parameters(bv,num_units_in_tick, time_scale, fixed_frame_rate_flag);
00430   }
00431 }
00432 
00433 #define SEI_MAX_SIZE 5000 // larger than the largest possible SEI NAL unit
00434 
00435 #ifdef DEBUG
00436 #define MAX_SEI_PAYLOAD_TYPE_DESCRIPTION 46
00437 char const* sei_payloadType_description[MAX_SEI_PAYLOAD_TYPE_DESCRIPTION+1] = {
00438   "buffering_period", //0
00439   "pic_timing", //1
00440   "pan_scan_rect", //2
00441   "filler_payload", //3
00442   "user_data_registered_itu_t_t35", //4
00443   "user_data_unregistered", //5
00444   "recovery_point", //6
00445   "dec_ref_pic_marking_repetition", //7
00446   "spare_pic", //8
00447   "scene_info", //9
00448   "sub_seq_info", //10
00449   "sub_seq_layer_characteristics", //11
00450   "sub_seq_characteristics", //12
00451   "full_frame_freeze", //13
00452   "full_frame_freeze_release", //14
00453   "full_frame_snapshot", //15
00454   "progressive_refinement_segment_start", //16
00455   "progressive_refinement_segment_end", //17
00456   "motion_constrained_slice_group_set", //18
00457   "film_grain_characteristics", //19
00458   "deblocking_filter_display_preference", //20
00459   "stereo_video_info", //21
00460   "post_filter_hint", //22
00461   "tone_mapping_info", //23
00462   "scalability_info", //24
00463   "sub_pic_scalable_layer", //25
00464   "non_required_layer_rep", //26
00465   "priority_layer_info", //27
00466   "layers_not_present", //28
00467   "layer_dependency_change", //29
00468   "scalable_nesting", //30
00469   "base_layer_temporal_hrd", //31
00470   "quality_layer_integrity_check", //32
00471   "redundant_pic_property", //33
00472   "tl0_dep_rep_index", //34
00473   "tl_switching_point", //35
00474   "parallel_decoding_info", //36
00475   "mvc_scalable_nesting", //37
00476   "view_scalability_info", //38
00477   "multiview_scene_info", //39
00478   "multiview_acquisition_info", //40
00479   "non_required_view_component", //41
00480   "view_dependency_change", //42
00481   "operation_points_not_present", //43
00482   "base_view_temporal_hrd", //44
00483   "frame_packing_arrangement", //45
00484   "reserved_sei_message" // 46 or higher
00485 };
00486 #endif
00487 
00488 void H264VideoStreamParser::analyze_sei_data() {
00489   // Begin by making a copy of the NAL unit data, removing any 'emulation prevention' bytes:
00490   u_int8_t sei[SEI_MAX_SIZE];
00491   unsigned seiSize;
00492   removeEmulationBytes(sei, sizeof sei, seiSize);
00493 
00494   unsigned j = 1; // skip the initial byte (forbidden_zero_bit; nal_ref_idc; nal_unit_type); we've already seen it 
00495   while (j < seiSize) {
00496     unsigned payloadType = 0;
00497     do {
00498       payloadType += sei[j];
00499     } while (sei[j++] == 255 && j < seiSize);
00500     if (j >= seiSize) break;
00501 
00502     unsigned payloadSize = 0;
00503     do {
00504       payloadSize += sei[j];
00505     } while (sei[j++] == 255 && j < seiSize);
00506     if (j >= seiSize) break;
00507 
00508 #ifdef DEBUG
00509     unsigned descriptionNum = payloadType <= MAX_SEI_PAYLOAD_TYPE_DESCRIPTION ? payloadType : MAX_SEI_PAYLOAD_TYPE_DESCRIPTION;
00510     fprintf(stderr, "\tpayloadType %d (\"%s\"); payloadSize %d\n", payloadType, sei_payloadType_description[descriptionNum], payloadSize);
00511 #endif
00512     j += payloadSize;
00513   }
00514 }
00515 
00516 void H264VideoStreamParser
00517 ::analyze_slice_header(u_int8_t* start, u_int8_t* end, u_int8_t nal_unit_type,
00518                        unsigned &frame_num, unsigned &pic_parameter_set_id, unsigned& idr_pic_id,
00519                        Boolean& field_pic_flag, Boolean& bottom_field_flag) {
00520   BitVector bv(start, 0, 8*(end-start));
00521 
00522   // Some of the result parameters might not be present in the header; set them to default values:
00523   field_pic_flag = bottom_field_flag = 0;
00524 
00525   // Note: We assume that there aren't any 'emulation prevention' bytes here to worry about...
00526   bv.skipBits(8); // forbidden_zero_bit; nal_ref_idc; nal_unit_type
00527   unsigned first_mb_in_slice = bv.get_expGolomb();
00528   DEBUG_PRINT(first_mb_in_slice);
00529   unsigned slice_type = bv.get_expGolomb();
00530   DEBUG_PRINT(slice_type);
00531   pic_parameter_set_id = bv.get_expGolomb();
00532   DEBUG_PRINT(pic_parameter_set_id);
00533   if (separate_colour_plane_flag) {
00534     bv.skipBits(2); // colour_plane_id
00535   }
00536   frame_num = bv.getBits(log2_max_frame_num);
00537   DEBUG_PRINT(frame_num);
00538   if (!frame_mbs_only_flag) {
00539     DEBUG_TAB;
00540     field_pic_flag = bv.get1Bit();
00541     DEBUG_PRINT(field_pic_flag);
00542     if (field_pic_flag) {
00543       DEBUG_TAB;
00544       bottom_field_flag = bv.get1Bit();
00545       DEBUG_PRINT(bottom_field_flag);
00546     }
00547   }
00548   Boolean IdrPicFlag = nal_unit_type == 5;
00549   if (IdrPicFlag) {
00550     DEBUG_TAB;
00551     idr_pic_id = bv.get_expGolomb();
00552     DEBUG_PRINT(idr_pic_id);
00553   }
00554   // We don't parse any more of the "slice_header", because we don't need the remaining fields (for our purpose)
00555 }
00556 
00557 void H264VideoStreamParser::flushInput() {
00558   fHaveSeenFirstStartCode = False;
00559   fHaveSeenFirstByteOfNALUnit = False;
00560 
00561   StreamParser::flushInput();
00562 }
00563 
00564 #define NUM_NEXT_SLICE_HEADER_BYTES_TO_ANALYZE 12
00565 
00566 unsigned H264VideoStreamParser::parse() {
00567   try {
00568     // The stream must start with a 0x00000001:
00569     if (!fHaveSeenFirstStartCode) {
00570       // Skip over any input bytes that precede the first 0x00000001:
00571       u_int32_t first4Bytes;
00572       while ((first4Bytes = test4Bytes()) != 0x00000001) {
00573         get1Byte(); setParseState(); // ensures that we progress over bad data
00574       }
00575       skipBytes(4); // skip this initial code
00576       
00577       setParseState();
00578       fHaveSeenFirstStartCode = True; // from now on
00579     }
00580     
00581     if (fOutputStartCodeSize > 0) {
00582       // Include a start code in the output:
00583       save4Bytes(0x00000001);
00584     }
00585 
00586     // Then save everything up until the next 0x00000001 (4 bytes) or 0x000001 (3 bytes), or we hit EOF.
00587     // Also make note of the first byte, because it contains the "nal_unit_type": 
00588     if (haveSeenEOF()) {
00589       // We hit EOF the last time that we tried to parse this data, so we know that any remaining unparsed data
00590       // forms a complete NAL unit, and that there's no 'start code' at the end:
00591       unsigned remainingDataSize = totNumValidBytes() - curOffset();
00592       while (remainingDataSize > 0) {
00593         saveByte(get1Byte());
00594         --remainingDataSize;
00595       }
00596 
00597       if (!fHaveSeenFirstByteOfNALUnit) {
00598         // There's no remaining NAL unit.
00599         (void)get1Byte(); // forces another read, which will cause EOF to get handled for real this time
00600         return 0;
00601       }
00602 #ifdef DEBUG
00603       fprintf(stderr, "This NAL unit (%d bytes) ends with EOF\n", curFrameSize()-fOutputStartCodeSize);
00604 #endif
00605     } else {
00606       u_int32_t next4Bytes = test4Bytes();
00607       if (!fHaveSeenFirstByteOfNALUnit) {
00608         fFirstByteOfNALUnit = next4Bytes>>24;
00609         fHaveSeenFirstByteOfNALUnit = True;
00610       }
00611       while (next4Bytes != 0x00000001 && (next4Bytes&0xFFFFFF00) != 0x00000100) {
00612         // We save at least some of "next4Bytes".
00613         if ((unsigned)(next4Bytes&0xFF) > 1) {
00614           // Common case: 0x00000001 or 0x000001 definitely doesn't begin anywhere in "next4Bytes", so we save all of it:
00615           save4Bytes(next4Bytes);
00616           skipBytes(4);
00617         } else {
00618           // Save the first byte, and continue testing the rest:
00619           saveByte(next4Bytes>>24);
00620           skipBytes(1);
00621         }
00622         setParseState(); // ensures forward progress
00623         next4Bytes = test4Bytes();
00624       }
00625       // Assert: next4Bytes starts with 0x00000001 or 0x000001, and we've saved all previous bytes (forming a complete NAL unit).
00626       // Skip over these remaining bytes, up until the start of the next NAL unit:
00627       if (next4Bytes == 0x00000001) {
00628         skipBytes(4);
00629       } else {
00630         skipBytes(3);
00631       }
00632     }
00633 
00634     u_int8_t nal_ref_idc = (fFirstByteOfNALUnit&0x60)>>5;
00635     u_int8_t nal_unit_type = fFirstByteOfNALUnit&0x1F;
00636     fHaveSeenFirstByteOfNALUnit = False; // for the next NAL unit that we parse
00637 #ifdef DEBUG
00638     fprintf(stderr, "Parsed %d-byte NAL-unit (nal_ref_idc: %d, nal_unit_type: %d (\"%s\"))\n",
00639             curFrameSize()-fOutputStartCodeSize, nal_ref_idc, nal_unit_type, nal_unit_type_description[nal_unit_type]);
00640 #endif
00641 
00642     switch (nal_unit_type) {
00643       case 6: { // Supplemental enhancement information (SEI)
00644         analyze_sei_data();
00645         // Later, perhaps adjust "fPresentationTime" if we saw a "pic_timing" SEI payload??? #####
00646         break;
00647       }
00648       case 7: { // Sequence parameter set
00649         // First, save a copy of this NAL unit, in case the downstream object wants to see it:
00650         usingSource()->saveCopyOfSPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize);
00651 
00652         // Parse this NAL unit to check whether frame rate information is present:
00653         unsigned num_units_in_tick, time_scale, fixed_frame_rate_flag;
00654         analyze_seq_parameter_set_data(num_units_in_tick, time_scale, fixed_frame_rate_flag);
00655         if (time_scale > 0 && num_units_in_tick > 0) {
00656           usingSource()->fFrameRate = time_scale/(2.0*num_units_in_tick);
00657 #ifdef DEBUG
00658           fprintf(stderr, "Set frame rate to %f fps\n", usingSource()->fFrameRate);
00659           if (fixed_frame_rate_flag == 0) {
00660             fprintf(stderr, "\tWARNING: \"fixed_frame_rate_flag\" was not set\n");
00661           }
00662 #endif
00663         } else {
00664 #ifdef DEBUG
00665           fprintf(stderr, "\tThis \"Sequence Parameter Set\" NAL unit contained no frame rate information, so we use a default frame rate of %f fps\n", usingSource()->fFrameRate);
00666 #endif
00667         }
00668         break;
00669       }
00670       case 8: { // Picture parameter set
00671         // Save a copy of this NAL unit, in case the downstream object wants to see it:
00672         usingSource()->saveCopyOfPPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize);
00673       }
00674     }
00675 
00676     usingSource()->setPresentationTime();
00677 #ifdef DEBUG
00678     unsigned long secs = (unsigned long)usingSource()->fPresentationTime.tv_sec;
00679     unsigned uSecs = (unsigned)usingSource()->fPresentationTime.tv_usec;
00680     fprintf(stderr, "\tPresentation time: %lu.%06u\n", secs, uSecs);
00681 #endif
00682 
00683     // If this NAL unit is a VCL NAL unit, we also scan the start of the next NAL unit, to determine whether this NAL unit
00684     // ends the current 'access unit'.  We need this information to figure out when to increment "fPresentationTime".
00685     // (RTP streamers also need to know this in order to figure out whether or not to set the "M" bit.)
00686     Boolean thisNALUnitEndsAccessUnit = False; // until we learn otherwise 
00687     if (haveSeenEOF()) {
00688       // There is no next NAL unit, so we assume that this one ends the current 'access unit':
00689       thisNALUnitEndsAccessUnit = True;
00690     } else {
00691       Boolean const isVCL = nal_unit_type <= 5 && nal_unit_type > 0; // Would need to include type 20 for SVC and MVC #####
00692       if (isVCL) {
00693         u_int32_t first4BytesOfNextNALUnit = test4Bytes();
00694         u_int8_t firstByteOfNextNALUnit = first4BytesOfNextNALUnit>>24;
00695         u_int8_t next_nal_ref_idc = (firstByteOfNextNALUnit&0x60)>>5;
00696         u_int8_t next_nal_unit_type = firstByteOfNextNALUnit&0x1F;
00697         if (next_nal_unit_type >= 6) {
00698           // The next NAL unit is not a VCL; therefore, we assume that this NAL unit ends the current 'access unit':
00699 #ifdef DEBUG
00700           fprintf(stderr, "\t(The next NAL unit is not a VCL)\n");
00701 #endif
00702           thisNALUnitEndsAccessUnit = True;
00703         } else {
00704           // The next NAL unit is also a VCL.  We need to examine it a little to figure out if it's a different 'access unit'.
00705           // (We use many of the criteria described in section 7.4.1.2.4 of the H.264 specification.)
00706           Boolean IdrPicFlag = nal_unit_type == 5;
00707           Boolean next_IdrPicFlag = next_nal_unit_type == 5;
00708           if (next_IdrPicFlag != IdrPicFlag) {
00709             // IdrPicFlag differs in value
00710 #ifdef DEBUG
00711             fprintf(stderr, "\t(IdrPicFlag differs in value)\n");
00712 #endif
00713             thisNALUnitEndsAccessUnit = True;
00714           } else if (next_nal_ref_idc != nal_ref_idc && next_nal_ref_idc*nal_ref_idc == 0) {
00715             // nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0
00716 #ifdef DEBUG
00717             fprintf(stderr, "\t(nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0)\n");
00718 #endif
00719             thisNALUnitEndsAccessUnit = True;
00720           } else if ((nal_unit_type == 1 || nal_unit_type == 2 || nal_unit_type == 5)
00721                      && (next_nal_unit_type == 1 || next_nal_unit_type == 2 || next_nal_unit_type == 5)) {
00722             // Both this and the next NAL units begin with a "slice_header".
00723             // Parse this (for each), to get parameters that we can compare:
00724             
00725             // Current NAL unit's "slice_header":
00726             unsigned frame_num, pic_parameter_set_id, idr_pic_id;
00727             Boolean field_pic_flag, bottom_field_flag;
00728             analyze_slice_header(fStartOfFrame + fOutputStartCodeSize, fTo, nal_unit_type,
00729                                  frame_num, pic_parameter_set_id, idr_pic_id, field_pic_flag, bottom_field_flag);
00730             
00731             // Next NAL unit's "slice_header":
00732 #ifdef DEBUG
00733             fprintf(stderr, "    Next NAL unit's slice_header:\n");
00734 #endif
00735             u_int8_t next_slice_header[NUM_NEXT_SLICE_HEADER_BYTES_TO_ANALYZE];
00736             testBytes(next_slice_header, sizeof next_slice_header);
00737             unsigned next_frame_num, next_pic_parameter_set_id, next_idr_pic_id;
00738             Boolean next_field_pic_flag, next_bottom_field_flag;
00739             analyze_slice_header(next_slice_header, &next_slice_header[sizeof next_slice_header], next_nal_unit_type,
00740                                  next_frame_num, next_pic_parameter_set_id, next_idr_pic_id, next_field_pic_flag, next_bottom_field_flag);
00741             
00742             if (next_frame_num != frame_num) {
00743               // frame_num differs in value
00744 #ifdef DEBUG
00745               fprintf(stderr, "\t(frame_num differs in value)\n");
00746 #endif
00747               thisNALUnitEndsAccessUnit = True;
00748             } else if (next_pic_parameter_set_id != pic_parameter_set_id) {
00749               // pic_parameter_set_id differs in value
00750 #ifdef DEBUG
00751               fprintf(stderr, "\t(pic_parameter_set_id differs in value)\n");
00752 #endif
00753               thisNALUnitEndsAccessUnit = True;
00754             } else if (next_field_pic_flag != field_pic_flag) {
00755               // field_pic_flag differs in value
00756 #ifdef DEBUG
00757               fprintf(stderr, "\t(field_pic_flag differs in value)\n");
00758 #endif
00759               thisNALUnitEndsAccessUnit = True;
00760             } else if (next_bottom_field_flag != bottom_field_flag) {
00761               // bottom_field_flag differs in value
00762 #ifdef DEBUG
00763               fprintf(stderr, "\t(bottom_field_flag differs in value)\n");
00764 #endif
00765               thisNALUnitEndsAccessUnit = True;
00766             } else if (next_IdrPicFlag == 1 && next_idr_pic_id != idr_pic_id) {
00767               // IdrPicFlag is equal to 1 for both and idr_pic_id differs in value
00768               // Note: We already know that IdrPicFlag is the same for both.
00769 #ifdef DEBUG
00770               fprintf(stderr, "\t(IdrPicFlag is equal to 1 for both and idr_pic_id differs in value)\n");
00771 #endif
00772               thisNALUnitEndsAccessUnit = True;
00773             }
00774           }
00775         }
00776       }
00777     }
00778         
00779     if (thisNALUnitEndsAccessUnit) {
00780 #ifdef DEBUG
00781       fprintf(stderr, "*****This NAL unit ends the current access unit*****\n");
00782 #endif
00783       usingSource()->fPictureEndMarker = True;
00784       ++usingSource()->fPictureCount;
00785 
00786       // Note that the presentation time for the next NAL unit will be different:
00787       struct timeval& nextPT = usingSource()->fNextPresentationTime; // alias
00788       nextPT = usingSource()->fPresentationTime;
00789       double nextFraction = nextPT.tv_usec/1000000.0 + 1/usingSource()->fFrameRate;
00790       unsigned nextSecsIncrement = (long)nextFraction;
00791       nextPT.tv_sec += (long)nextSecsIncrement;
00792       nextPT.tv_usec = (long)((nextFraction - nextSecsIncrement)*1000000);
00793     }
00794     setParseState();
00795 
00796     return curFrameSize();
00797   } catch (int /*e*/) {
00798 #ifdef DEBUG
00799     fprintf(stderr, "H264VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
00800 #endif
00801     return 0;  // the parsing got interrupted
00802   }
00803 }

Generated on Thu May 10 20:25:11 2012 for live by  doxygen 1.5.2