Well, actually i do not decode h264 stream but just need width, height info...

For h264 stream, here is simple buggy parser which gets width height
from  fSpropParameterSets...
Maybe someone also need a starting point for parsing those data...


Best Wishes


How To Use:

So in desribe response if you get  those parmeters from
scs.subsession->fmtp_spropparametersets();

just use this simple buggy parser like

H264SPropParameterSetParser parser(scs.subsession->fmtp_spropparametersets());

int w = parse->GetWidth();
int h= parser->GetHeight();


Here is the codes: There is 2 class BitStreamReader, and
H264SPropParameterSetParser

// H264SPropParameterSetParser

#pragma once

#ifndef _H264_SPROP_PARAMETER_SET_PARSER_
#define       _H264_SPROP_PARAMETER_SET_PARSER_

#include <iostream>

#include "BitStreamReader.h"


using namespace std;

static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";



        class H264SPropParameterSetParser
        {
        public:
                H264SPropParameterSetParser(string spsFromSdp)
                {
                        this->spsFromSdp = spsFromSdp;
                        height = 0;
                        width = 0;

                        StartParsing();
                }

                int GetWidth()
                {
                        int width  = ( pic_width_in_mbs_minus1 +1)*16;
                        return width;
                }

                int GetHeight()
                {

                        int height =( pic_height_in_map_units_minus1+1)*16;
                        return  height;
                }

                ~H264SPropParameterSetParser(void)
                {

                        delete bitStreamReader;
                        bitStreamReader = NULL;
                        
                }


        private:

                void StartParsing()
                {
                        ConvertFromBase64IntoByteArray();
                        ParseSequenceParameterSet();

                }

                void ConvertFromBase64IntoByteArray()
                {
                        string decodedString = DecodeBase64( spsFromSdp);

                        binaryData = new unsigned char[decodedString.size()];
                        std::copy(decodedString.begin(), decodedString.end(), 
binaryData);
                }

                void ParseSequenceParameterSet()
                {

                        unsigned __int32 temp;

                        bitStreamReader = new BitStreamReader(binaryData);

                        bitStreamReader->U(8); // skip nal unit type

                        profile_idc  =  bitStreamReader->U(8);

                        constraint_set0_flag = bitStreamReader->U(1);
                        constraint_set1_flag = bitStreamReader->U(1);
                        constraint_set2_flag = bitStreamReader->U(1);
                        constraint_set3_flag = bitStreamReader->U(1);
                        reserved_zero_4bits = bitStreamReader->U(4);

                        level_idc = bitStreamReader->U(8);
                        seq_parameter_set_id = bitStreamReader->Uev();

                        if (profile_idc  == 100 || profile_idc  == 110 ||
                                profile_idc  == 122 || profile_idc  == 144)
                        {

                                chroma_format_idc = bitStreamReader->Uev();

                                if (chroma_format_idc == 3)
                                {
                                        separate_colour_plane_flag = 
bitStreamReader->U(1);
                                }

                                bit_depth_luma_minus8 = bitStreamReader->Uev();
                                bit_depth_chroma_minus8 = 
bitStreamReader->Uev();
                                qpprime_y_zero_transform_bypass_flag  = 
bitStreamReader->U(1);
                                seq_scaling_matrix_present_flag =  
bitStreamReader->U(1);

                                if( seq_scaling_matrix_present_flag )
                                {
                                        for(unsigned int ix = 0; ix < 8; ix++)
                                        {
                                                temp = bitStreamReader->U(1);

                                                if (temp)
                                                {
                                                        ScalingList(ix, ix < 6 
? 16 : 64);
                                                }
                                        }
                                }
                        }


                        log2_max_frame_num_minus4 = bitStreamReader->Uev();

                        pic_order_cnt_type =  bitStreamReader->Uev();

                        if (pic_order_cnt_type == 0)
                        {
                                log2_max_pic_order_cnt_lsb_minus4 = 
bitStreamReader->Uev();

                        }

                        else if (pic_order_cnt_type == 1)
                        {
                                delta_pic_order_always_zero_flag = 
bitStreamReader->U(1);
                                offset_for_non_ref_pic = bitStreamReader->Sev();
                                offset_for_top_to_bottom_field =  
bitStreamReader->Sev();

                                num_ref_frames_in_pic_order_cnt_cycle = 
bitStreamReader->Uev();

                                for( int i = 0; i < 
num_ref_frames_in_pic_order_cnt_cycle; i++ )
                                {

                                        int skippedParameter = 
bitStreamReader->Sev();
                                }

                        }



                        num_ref_frames = bitStreamReader->Uev();
                        gaps_in_frame_num_value_allowed_flag = 
bitStreamReader->U(1);

                        pic_width_in_mbs_minus1 = bitStreamReader->Uev();
                        pic_height_in_map_units_minus1 = bitStreamReader->Uev();

                        frame_mbs_only_flag =  bitStreamReader->U(1);


                        if( !frame_mbs_only_flag )
                        {
                                mb_adaptive_frame_field_flag = 
bitStreamReader->U(1);
                        }


                        direct_8x8_inference_flag =  bitStreamReader->U(1);
                        frame_cropping_flag = bitStreamReader->U(1);

                        if( frame_cropping_flag )
                        {

                                frame_crop_left_offset = bitStreamReader->Uev();
                                frame_crop_right_offset = 
bitStreamReader->Uev();
                                frame_crop_top_offset = bitStreamReader->Uev();
                                frame_crop_bottom_offset = 
bitStreamReader->Uev();


                        }

                        vui_parameters_present_flag = bitStreamReader->U(1);

                }



                // Utility to parse
                void ScalingList(unsigned int ix, unsigned int 
sizeOfScalingList)
                {

                        unsigned int lastScale = 8;
                        unsigned int nextScale = 8;
                        unsigned int jx;
                        int deltaScale;

                        for (jx = 0; jx < sizeOfScalingList; jx++)
                        {
                                if (nextScale != 0)
                                {
                                        deltaScale = bitStreamReader->Sev();
                                        nextScale = (lastScale + deltaScale + 
256) % 256;
                                }
                                if (nextScale == 0)
                                {
                                        lastScale = lastScale;
                                }
                                else
                                {
                                        lastScale = nextScale;
                                }
                        }

                }


                std::string DecodeBase64(std::string const& encodedString)
                {
                        int inlen = encodedString.size();
                        int i = 0;
                        int j = 0;
                        int in = 0;

                        unsigned char charArray4[4], charArray3[3];
                        std::string ret;

                        while (inlen-- && ( encodedString[in] != '=') &&
IsBase64(encodedString[in])) {
                                charArray4[i++] = encodedString[in]; in++;
                                if (i ==4) {
                                        for (i = 0; i <4; i++)
                                                charArray4[i] = 
base64_chars.find(charArray4[i]);

                                        charArray3[0] = (charArray4[0] << 2) + 
((charArray4[1] & 0x30) >> 4);
                                        charArray3[1] = ((charArray4[1] & 0xf) 
<< 4) + ((charArray4[2] &
0x3c) >> 2);
                                        charArray3[2] = ((charArray4[2] & 0x3) 
<< 6) + charArray4[3];

                                        for (i = 0; (i < 3); i++)
                                                ret += charArray3[i];
                                        i = 0;
                                }
                        }

                        if (i) {
                                for (j = i; j <4; j++)
                                        charArray4[j] = 0;

                                for (j = 0; j <4; j++)
                                        charArray4[j] = 
base64_chars.find(charArray4[j]);

                                charArray3[0] = (charArray4[0] << 2) + 
((charArray4[1] & 0x30) >> 4);
                                charArray3[1] = ((charArray4[1] & 0xf) << 4) + 
((charArray4[2] &
0x3c) >> 2);
                                charArray3[2] = ((charArray4[2] & 0x3) << 6) + 
charArray4[3];

                                for (j = 0; (j < i - 1); j++) ret += 
charArray3[j];
                        }

                        return ret;

                }



                bool IsBase64(unsigned char c)
                {
                        return (isalnum(c) || (c == '+') || (c == '/'));
                }

                // Data to Parse
                unsigned char* binaryData;
                // Parameter from Describe RtspReponse: Base64 string
                string spsFromSdp;

                // Utility to read bits esaily
                BitStreamReader* bitStreamReader;


                // Parameters

                int profile_idc ;
                int constraint_set0_flag;
                int constraint_set1_flag;
                int constraint_set2_flag;
                int constraint_set3_flag;
                int reserved_zero_4bits;
                int level_idc;
                int seq_parameter_set_id;
                int chroma_format_idc;
                int separate_colour_plane_flag;
                int bit_depth_luma_minus8;
                int bit_depth_chroma_minus8;
                int qpprime_y_zero_transform_bypass_flag;
                int seq_scaling_matrix_present_flag;
                int log2_max_frame_num_minus4;
                int pic_order_cnt_type;
                int log2_max_pic_order_cnt_lsb_minus4;
                int delta_pic_order_always_zero_flag;
                int offset_for_non_ref_pic;
                int offset_for_top_to_bottom_field;
                int  num_ref_frames_in_pic_order_cnt_cycle;
                int num_ref_frames;
                int gaps_in_frame_num_value_allowed_flag;
                unsigned __int32  pic_width_in_mbs_minus1;
                unsigned __int32  pic_height_in_map_units_minus1;
                int frame_mbs_only_flag;
                int mb_adaptive_frame_field_flag;
                int direct_8x8_inference_flag;
                int frame_cropping_flag;
                int frame_crop_left_offset;
                int frame_crop_right_offset;
                int frame_crop_top_offset;
                int frame_crop_bottom_offset;
                int vui_parameters_present_flag;

                int height;
                int width;

        };


#endif



Then

// BitStreamReader

#pragma once

#ifndef __BIT_STREAM_READER__
#define      __BIT_STREAM_READER__

#include <iostream>
#include <sstream>
#include <string>


        class BitStreamReader
        {
        public:
                BitStreamReader(unsigned char* dataToRead)
                {
                        position = 0;
                        binaryData =  dataToRead;
                }

                ~BitStreamReader(void)
                {
                        delete[]  binaryData;
                        binaryData = NULL;
                }

                void SkipBits(int n)
                {
                        for (int i = 0; i < n; i++)
                        {
                                SkipBit();
                        }

                }

                int GetBits(int n) // Same as U(int n)
                {

                        int result = 0;
                        for (int i = 0; i < n; i++) {
                                result = result * 2 +GetBit();
                        }

                        return result;
                }


                int U(int n)
                {
                        int result = 0;
                        for (int i = 0; i < n; i++)
                        {
                                result = result * 2 +GetBit();
                        }

                        return result;
                }

                int Uev() {
                        return Ev(false);
                }


                int Sev()
                {
                        return Ev(true);
                }

        private:

                int GetBit()
                {
                        int mask = 1 << (7 - (position & 7));
                        int index = position >> 3;
                        position++;
                        return ((binaryData[index] & mask) == 0) ? 0 : 1;
                }

                void SkipBit()
                {
                        position++;

                }

                int Ev(bool isItSigned)
                {

                        int bitCount = 0;

                        std::string expGolomb;

                        while (GetBit() == 0)
                        {
                                expGolomb += '0';
                                bitCount++;
                        }

                        expGolomb += "/1";

                        int result = 1;
                        for (int i = 0; i < bitCount; i++)
                        {
                                int b = GetBit();
                                expGolomb += b;
                                result = result * 2 + b;
                        }

                        result--;
                        if (isItSigned) {
                                result = (result + 1) / 2 * (result % 2 == 0 ? 
-1 : 1);

                        }
                        return result;

                }
                unsigned char* binaryData;
                int position;
        };



#endif




2012/1/10 Ross Finlayson <finlay...@live555.com>:
> I check video stream  width  height  from subsession
> scs.subsession->videoHeight(), scs.subsession->videoHeight()...
>
> They give me right dimesions for server which desribe response include
> "a=x-dimensions:%d,%d", &width, &height)"...
>
> But they give wrong value ( 0) for server which does NOT  include
> "a=x-dimensions:%d,%d", &width, &height)"
>
>
> Exactly.  The "MediaSubsession::videoHeight()" and
> "MediaSubsession::videoWidth()" member functions (and other "MediaSession"
> member functions) return the values that were obtained by parsing the
> stream's SDP description.  If, however, the corresponding fields are not in
> the stream's SDP description, then 'null' values will be returned instead.
>
>
> So i have to parse that subsession->fSpropParameterSets to get width..
>
>
> Yes.  Just as you have to parse this, and all of the other NAL units if you
> want to decode and play the H.264 video.
>
>
> Is there a parser for  fSpropParameterSets parameter s in Live555
> which i can extract video with height...
>
>
> No.
>
>
> Ross Finlayson
> Live Networks, Inc.
> http://www.live555.com/
>
>
> _______________________________________________
> live-devel mailing list
> live-devel@lists.live555.com
> http://lists.live555.com/mailman/listinfo/live-devel
>

_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to