enhanced avc decode, parse the sps get width+height. 2.0.156.
正在显示
9 个修改的文件
包含
351 行增加
和
8 行删除
| @@ -562,7 +562,8 @@ Supported operating systems and hardware: | @@ -562,7 +562,8 @@ Supported operating systems and hardware: | ||
| 562 | 562 | ||
| 563 | ### SRS 2.0 history | 563 | ### SRS 2.0 history |
| 564 | 564 | ||
| 565 | -* v2.0, 2015-03-30, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155. | 565 | +* v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156. |
| 566 | +* v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155. | ||
| 566 | * v2.0, 2015-03-30, for [#366](https://github.com/winlinvip/simple-rtmp-server/issues/366), config hls to disable cleanup of ts. 2.0.154. | 567 | * v2.0, 2015-03-30, for [#366](https://github.com/winlinvip/simple-rtmp-server/issues/366), config hls to disable cleanup of ts. 2.0.154. |
| 567 | * v2.0, 2015-03-31, support server cycle handler. 2.0.153. | 568 | * v2.0, 2015-03-31, support server cycle handler. 2.0.153. |
| 568 | * v2.0, 2015-03-31, support on_hls for http hooks. 2.0.152. | 569 | * v2.0, 2015-03-31, support on_hls for http hooks. 2.0.152. |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 155 | 34 | +#define VERSION_REVISION 156 |
| 35 | 35 | ||
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
| @@ -31,6 +31,7 @@ using namespace std; | @@ -31,6 +31,7 @@ using namespace std; | ||
| 31 | #include <srs_kernel_log.hpp> | 31 | #include <srs_kernel_log.hpp> |
| 32 | #include <srs_kernel_stream.hpp> | 32 | #include <srs_kernel_stream.hpp> |
| 33 | #include <srs_kernel_utility.hpp> | 33 | #include <srs_kernel_utility.hpp> |
| 34 | +#include <srs_core_autofree.hpp> | ||
| 34 | 35 | ||
| 35 | string srs_codec_video2str(SrsCodecVideo codec) | 36 | string srs_codec_video2str(SrsCodecVideo codec) |
| 36 | { | 37 | { |
| @@ -713,7 +714,8 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -713,7 +714,8 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 713 | return ret; | 714 | return ret; |
| 714 | } | 715 | } |
| 715 | 716 | ||
| 716 | - // 1 sps | 717 | + // 1 sps, 7.3.2.1 Sequence parameter set RBSP syntax |
| 718 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 45. | ||
| 717 | if (!stream->require(1)) { | 719 | if (!stream->require(1)) { |
| 718 | ret = ERROR_HLS_DECODE_ERROR; | 720 | ret = ERROR_HLS_DECODE_ERROR; |
| 719 | srs_error("avc decode sequenc header sps failed. ret=%d", ret); | 721 | srs_error("avc decode sequenc header sps failed. ret=%d", ret); |
| @@ -740,8 +742,7 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -740,8 +742,7 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 740 | if (sequenceParameterSetLength > 0) { | 742 | if (sequenceParameterSetLength > 0) { |
| 741 | srs_freep(sequenceParameterSetNALUnit); | 743 | srs_freep(sequenceParameterSetNALUnit); |
| 742 | sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; | 744 | sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; |
| 743 | - memcpy(sequenceParameterSetNALUnit, stream->data() + stream->pos(), sequenceParameterSetLength); | ||
| 744 | - stream->skip(sequenceParameterSetLength); | 745 | + stream->read_bytes(sequenceParameterSetNALUnit, sequenceParameterSetLength); |
| 745 | } | 746 | } |
| 746 | // 1 pps | 747 | // 1 pps |
| 747 | if (!stream->require(1)) { | 748 | if (!stream->require(1)) { |
| @@ -770,10 +771,242 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | @@ -770,10 +771,242 @@ int SrsAvcAacCodec::avc_demux_sps_pps(SrsStream* stream) | ||
| 770 | if (pictureParameterSetLength > 0) { | 771 | if (pictureParameterSetLength > 0) { |
| 771 | srs_freep(pictureParameterSetNALUnit); | 772 | srs_freep(pictureParameterSetNALUnit); |
| 772 | pictureParameterSetNALUnit = new char[pictureParameterSetLength]; | 773 | pictureParameterSetNALUnit = new char[pictureParameterSetLength]; |
| 773 | - memcpy(pictureParameterSetNALUnit, stream->data() + stream->pos(), pictureParameterSetLength); | ||
| 774 | - stream->skip(pictureParameterSetLength); | 774 | + stream->read_bytes(pictureParameterSetNALUnit, pictureParameterSetLength); |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | + return avc_demux_sps(); | ||
| 778 | +} | ||
| 779 | + | ||
| 780 | +int SrsAvcAacCodec::avc_demux_sps() | ||
| 781 | +{ | ||
| 782 | + int ret = ERROR_SUCCESS; | ||
| 783 | + | ||
| 784 | + if (!sequenceParameterSetLength) { | ||
| 785 | + return ret; | ||
| 786 | + } | ||
| 787 | + | ||
| 788 | + SrsStream stream; | ||
| 789 | + if ((ret = stream.initialize(sequenceParameterSetNALUnit, sequenceParameterSetLength)) != ERROR_SUCCESS) { | ||
| 790 | + return ret; | ||
| 791 | + } | ||
| 792 | + | ||
| 793 | + // for NALU, 7.3.1 NAL unit syntax | ||
| 794 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
| 795 | + if (!stream.require(1)) { | ||
| 796 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 797 | + srs_error("avc decode sps failed. ret=%d", ret); | ||
| 798 | + return ret; | ||
| 799 | + } | ||
| 800 | + int8_t nutv = stream.read_1bytes(); | ||
| 801 | + | ||
| 802 | + // forbidden_zero_bit shall be equal to 0. | ||
| 803 | + int8_t forbidden_zero_bit = (nutv >> 7) & 0x01; | ||
| 804 | + if (forbidden_zero_bit) { | ||
| 805 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 806 | + srs_error("forbidden_zero_bit shall be equal to 0. ret=%d", ret); | ||
| 807 | + return ret; | ||
| 808 | + } | ||
| 809 | + | ||
| 810 | + // nal_ref_idc not equal to 0 specifies that the content of the NAL unit contains a sequence parameter set or a picture | ||
| 811 | + // parameter set or a slice of a reference picture or a slice data partition of a reference picture. | ||
| 812 | + int8_t nal_ref_idc = (nutv >> 5) & 0x03; | ||
| 813 | + if (!nal_ref_idc) { | ||
| 814 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 815 | + srs_error("for sps, nal_ref_idc shall be not be equal to 0. ret=%d", ret); | ||
| 816 | + return ret; | ||
| 817 | + } | ||
| 818 | + | ||
| 819 | + // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1. | ||
| 820 | + // VCL NAL units are specified as those NAL units having nal_unit_type equal to 1, 2, 3, 4, 5, or 12. | ||
| 821 | + // All remaining NAL units are called non-VCL NAL units. | ||
| 822 | + int8_t nal_unit_type = nutv & 0x1f; | ||
| 823 | + if (nal_unit_type != 7) { | ||
| 824 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 825 | + srs_error("for sps, nal_unit_type shall be equal to 7. ret=%d", ret); | ||
| 826 | + return ret; | ||
| 827 | + } | ||
| 828 | + | ||
| 829 | + // decode the rbsp from sps. | ||
| 830 | + // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes. | ||
| 831 | + int8_t* rbsp = new int8_t[sequenceParameterSetLength]; | ||
| 832 | + SrsAutoFree(int8_t, rbsp); | ||
| 833 | + | ||
| 834 | + int nb_rbsp = 0; | ||
| 835 | + while (!stream.empty()) { | ||
| 836 | + rbsp[nb_rbsp] = stream.read_1bytes(); | ||
| 837 | + | ||
| 838 | + // XX 00 00 03 XX, the 03 byte should be drop. | ||
| 839 | + if (nb_rbsp > 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) { | ||
| 840 | + continue; | ||
| 841 | + } | ||
| 842 | + | ||
| 843 | + nb_rbsp++; | ||
| 844 | + } | ||
| 845 | + | ||
| 846 | + return avc_demux_sps_rbsp((char*)rbsp, nb_rbsp); | ||
| 847 | +} | ||
| 848 | + | ||
| 849 | + | ||
| 850 | +int SrsAvcAacCodec::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp) | ||
| 851 | +{ | ||
| 852 | + int ret = ERROR_SUCCESS; | ||
| 853 | + | ||
| 854 | + // reparse the rbsp. | ||
| 855 | + SrsStream stream; | ||
| 856 | + if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) { | ||
| 857 | + return ret; | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + // for SPS, 7.3.2.1.1 Sequence parameter set data syntax | ||
| 861 | + // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62. | ||
| 862 | + if (!stream.require(3)) { | ||
| 863 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 864 | + srs_error("sps shall atleast 3bytes. ret=%d", ret); | ||
| 865 | + return ret; | ||
| 866 | + } | ||
| 867 | + u_int8_t profile_idc = stream.read_1bytes(); | ||
| 868 | + if (!profile_idc) { | ||
| 869 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 870 | + srs_error("sps the profile_idc invalid. ret=%d", ret); | ||
| 871 | + return ret; | ||
| 872 | + } | ||
| 873 | + | ||
| 874 | + int8_t flags = stream.read_1bytes(); | ||
| 875 | + if (flags & 0x03) { | ||
| 876 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 877 | + srs_error("sps the flags invalid. ret=%d", ret); | ||
| 878 | + return ret; | ||
| 879 | + } | ||
| 880 | + | ||
| 881 | + u_int8_t level_idc = stream.read_1bytes(); | ||
| 882 | + if (!level_idc) { | ||
| 883 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 884 | + srs_error("sps the level_idc invalid. ret=%d", ret); | ||
| 885 | + return ret; | ||
| 886 | + } | ||
| 887 | + | ||
| 888 | + SrsBitStream bs; | ||
| 889 | + if ((ret = bs.initialize(&stream)) != ERROR_SUCCESS) { | ||
| 890 | + return ret; | ||
| 891 | + } | ||
| 892 | + | ||
| 893 | + int64_t seq_parameter_set_id = -1; | ||
| 894 | + if ((ret = srs_avc_nalu_read_uev(&bs, seq_parameter_set_id)) != ERROR_SUCCESS) { | ||
| 895 | + return ret; | ||
| 896 | + } | ||
| 897 | + if (seq_parameter_set_id < 0) { | ||
| 898 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 899 | + srs_error("sps the seq_parameter_set_id invalid. ret=%d", ret); | ||
| 900 | + return ret; | ||
| 901 | + } | ||
| 902 | + srs_info("sps parse profile=%d, level=%d, sps_id=%d", profile_idc, level_idc, seq_parameter_set_id); | ||
| 903 | + | ||
| 904 | + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 | ||
| 905 | + || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 | ||
| 906 | + || profile_idc == 128 | ||
| 907 | + ) { | ||
| 908 | + int64_t chroma_format_idc = -1; | ||
| 909 | + if ((ret = srs_avc_nalu_read_uev(&bs, chroma_format_idc)) != ERROR_SUCCESS) { | ||
| 910 | + return ret; | ||
| 911 | + } | ||
| 912 | + if (chroma_format_idc == 3) { | ||
| 913 | + int8_t separate_colour_plane_flag = -1; | ||
| 914 | + if ((ret = srs_avc_nalu_read_bit(&bs, separate_colour_plane_flag)) != ERROR_SUCCESS) { | ||
| 915 | + return ret; | ||
| 916 | + } | ||
| 917 | + } | ||
| 918 | + | ||
| 919 | + int64_t bit_depth_luma_minus8 = -1; | ||
| 920 | + if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_luma_minus8)) != ERROR_SUCCESS) { | ||
| 921 | + return ret; | ||
| 922 | + } | ||
| 923 | + | ||
| 924 | + int64_t bit_depth_chroma_minus8 = -1; | ||
| 925 | + if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_chroma_minus8)) != ERROR_SUCCESS) { | ||
| 926 | + return ret; | ||
| 927 | + } | ||
| 928 | + | ||
| 929 | + int8_t qpprime_y_zero_transform_bypass_flag = -1; | ||
| 930 | + if ((ret = srs_avc_nalu_read_bit(&bs, qpprime_y_zero_transform_bypass_flag)) != ERROR_SUCCESS) { | ||
| 931 | + return ret; | ||
| 932 | + } | ||
| 933 | + | ||
| 934 | + int8_t seq_scaling_matrix_present_flag = -1; | ||
| 935 | + if ((ret = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag)) != ERROR_SUCCESS) { | ||
| 936 | + return ret; | ||
| 937 | + } | ||
| 938 | + if (seq_scaling_matrix_present_flag) { | ||
| 939 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 940 | + srs_error("sps the seq_scaling_matrix_present_flag invalid. ret=%d", ret); | ||
| 941 | + return ret; | ||
| 942 | + } | ||
| 943 | + } | ||
| 944 | + | ||
| 945 | + int64_t log2_max_frame_num_minus4 = -1; | ||
| 946 | + if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_frame_num_minus4)) != ERROR_SUCCESS) { | ||
| 947 | + return ret; | ||
| 948 | + } | ||
| 949 | + | ||
| 950 | + int64_t pic_order_cnt_type = -1; | ||
| 951 | + if ((ret = srs_avc_nalu_read_uev(&bs, pic_order_cnt_type)) != ERROR_SUCCESS) { | ||
| 952 | + return ret; | ||
| 953 | + } | ||
| 954 | + | ||
| 955 | + if (pic_order_cnt_type == 0) { | ||
| 956 | + int64_t log2_max_pic_order_cnt_lsb_minus4 = -1; | ||
| 957 | + if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_pic_order_cnt_lsb_minus4)) != ERROR_SUCCESS) { | ||
| 958 | + return ret; | ||
| 959 | + } | ||
| 960 | + } else if (pic_order_cnt_type == 1) { | ||
| 961 | + int8_t delta_pic_order_always_zero_flag = -1; | ||
| 962 | + if ((ret = srs_avc_nalu_read_bit(&bs, delta_pic_order_always_zero_flag)) != ERROR_SUCCESS) { | ||
| 963 | + return ret; | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + int64_t offset_for_non_ref_pic = -1; | ||
| 967 | + if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_non_ref_pic)) != ERROR_SUCCESS) { | ||
| 968 | + return ret; | ||
| 969 | + } | ||
| 970 | + | ||
| 971 | + int64_t offset_for_top_to_bottom_field = -1; | ||
| 972 | + if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_top_to_bottom_field)) != ERROR_SUCCESS) { | ||
| 973 | + return ret; | ||
| 974 | + } | ||
| 975 | + | ||
| 976 | + int64_t num_ref_frames_in_pic_order_cnt_cycle = -1; | ||
| 977 | + if ((ret = srs_avc_nalu_read_uev(&bs, num_ref_frames_in_pic_order_cnt_cycle)) != ERROR_SUCCESS) { | ||
| 978 | + return ret; | ||
| 979 | + } | ||
| 980 | + if (num_ref_frames_in_pic_order_cnt_cycle) { | ||
| 981 | + ret = ERROR_HLS_DECODE_ERROR; | ||
| 982 | + srs_error("sps the num_ref_frames_in_pic_order_cnt_cycle invalid. ret=%d", ret); | ||
| 983 | + return ret; | ||
| 984 | + } | ||
| 985 | + } | ||
| 986 | + | ||
| 987 | + int64_t max_num_ref_frames = -1; | ||
| 988 | + if ((ret = srs_avc_nalu_read_uev(&bs, max_num_ref_frames)) != ERROR_SUCCESS) { | ||
| 989 | + return ret; | ||
| 990 | + } | ||
| 991 | + | ||
| 992 | + int8_t gaps_in_frame_num_value_allowed_flag = -1; | ||
| 993 | + if ((ret = srs_avc_nalu_read_bit(&bs, gaps_in_frame_num_value_allowed_flag)) != ERROR_SUCCESS) { | ||
| 994 | + return ret; | ||
| 995 | + } | ||
| 996 | + | ||
| 997 | + int64_t pic_width_in_mbs_minus1 = -1; | ||
| 998 | + if ((ret = srs_avc_nalu_read_uev(&bs, pic_width_in_mbs_minus1)) != ERROR_SUCCESS) { | ||
| 999 | + return ret; | ||
| 1000 | + } | ||
| 1001 | + | ||
| 1002 | + int64_t pic_height_in_map_units_minus1 = -1; | ||
| 1003 | + if ((ret = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != ERROR_SUCCESS) { | ||
| 1004 | + return ret; | ||
| 1005 | + } | ||
| 1006 | + | ||
| 1007 | + width = (int)(pic_width_in_mbs_minus1 + 1) * 16; | ||
| 1008 | + height = (int)(pic_height_in_map_units_minus1 + 1) * 16; | ||
| 1009 | + | ||
| 777 | return ret; | 1010 | return ret; |
| 778 | } | 1011 | } |
| 779 | 1012 |
| @@ -581,6 +581,11 @@ private: | @@ -581,6 +581,11 @@ private: | ||
| 581 | */ | 581 | */ |
| 582 | virtual int avc_demux_sps_pps(SrsStream* stream); | 582 | virtual int avc_demux_sps_pps(SrsStream* stream); |
| 583 | /** | 583 | /** |
| 584 | + * decode the sps rbsp stream. | ||
| 585 | + */ | ||
| 586 | + virtual int avc_demux_sps(); | ||
| 587 | + virtual int avc_demux_sps_rbsp(char* rbsp, int nb_rbsp); | ||
| 588 | + /** | ||
| 584 | * demux the avc NALU in "AnnexB" | 589 | * demux the avc NALU in "AnnexB" |
| 585 | * from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. | 590 | * from H.264-AVC-ISO_IEC_14496-10.pdf, page 211. |
| 586 | */ | 591 | */ |
| @@ -215,7 +215,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -215,7 +215,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 | 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 |
| 216 | #define ERROR_HTTP_DVR_NO_TAEGET 3054 | 216 | #define ERROR_HTTP_DVR_NO_TAEGET 3054 |
| 217 | #define ERROR_ADTS_ID_NOT_AAC 3055 | 217 | #define ERROR_ADTS_ID_NOT_AAC 3055 |
| 218 | - | ||
| 219 | // HDS error code | 218 | // HDS error code |
| 220 | #define ERROR_HDS_OPEN_F4M_FAILED 3056 | 219 | #define ERROR_HDS_OPEN_F4M_FAILED 3056 |
| 221 | #define ERROR_HDS_WRITE_F4M_FAILED 3057 | 220 | #define ERROR_HDS_WRITE_F4M_FAILED 3057 |
| @@ -254,6 +253,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -254,6 +253,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 254 | #define ERROR_STREAM_CASTER_FLV_TAG 4024 | 253 | #define ERROR_STREAM_CASTER_FLV_TAG 4024 |
| 255 | #define ERROR_HTTP_RESPONSE_EOF 4025 | 254 | #define ERROR_HTTP_RESPONSE_EOF 4025 |
| 256 | #define ERROR_HTTP_INVALID_CHUNK_HEADER 4026 | 255 | #define ERROR_HTTP_INVALID_CHUNK_HEADER 4026 |
| 256 | +#define ERROR_AVC_NALU_UEV 4027 | ||
| 257 | 257 | ||
| 258 | /////////////////////////////////////////////////////// | 258 | /////////////////////////////////////////////////////// |
| 259 | // user-define error. | 259 | // user-define error. |
| @@ -252,4 +252,38 @@ void SrsStream::write_bytes(char* data, int size) | @@ -252,4 +252,38 @@ void SrsStream::write_bytes(char* data, int size) | ||
| 252 | p += size; | 252 | p += size; |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | +SrsBitStream::SrsBitStream() | ||
| 256 | +{ | ||
| 257 | + cb = 0; | ||
| 258 | + cb_left = 0; | ||
| 259 | + stream = NULL; | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +SrsBitStream::~SrsBitStream() | ||
| 263 | +{ | ||
| 264 | +} | ||
| 265 | + | ||
| 266 | +int SrsBitStream::initialize(SrsStream* s) { | ||
| 267 | + stream = s; | ||
| 268 | + return ERROR_SUCCESS; | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +bool SrsBitStream::empty() { | ||
| 272 | + if (cb_left) { | ||
| 273 | + return false; | ||
| 274 | + } | ||
| 275 | + return stream->empty(); | ||
| 276 | +} | ||
| 277 | + | ||
| 278 | +int8_t SrsBitStream::read_bit() { | ||
| 279 | + if (!cb_left) { | ||
| 280 | + srs_assert(!stream->empty()); | ||
| 281 | + cb = stream->read_1bytes(); | ||
| 282 | + cb_left = 8; | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + int8_t v = (cb >> (cb_left - 1)) & 0x01; | ||
| 286 | + cb_left--; | ||
| 287 | + return v; | ||
| 288 | +} | ||
| 255 | 289 |
| @@ -154,4 +154,22 @@ public: | @@ -154,4 +154,22 @@ public: | ||
| 154 | virtual void write_bytes(char* data, int size); | 154 | virtual void write_bytes(char* data, int size); |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | +/** | ||
| 158 | + * the bit stream. | ||
| 159 | + */ | ||
| 160 | +class SrsBitStream | ||
| 161 | +{ | ||
| 162 | +private: | ||
| 163 | + int8_t cb; | ||
| 164 | + u_int8_t cb_left; | ||
| 165 | + SrsStream* stream; | ||
| 166 | +public: | ||
| 167 | + SrsBitStream(); | ||
| 168 | + virtual ~SrsBitStream(); | ||
| 169 | +public: | ||
| 170 | + virtual int initialize(SrsStream* s); | ||
| 171 | + virtual bool empty(); | ||
| 172 | + virtual int8_t read_bit(); | ||
| 173 | +}; | ||
| 174 | + | ||
| 157 | #endif | 175 | #endif |
| @@ -46,6 +46,53 @@ using namespace std; | @@ -46,6 +46,53 @@ using namespace std; | ||
| 46 | // @see SRS_SYS_TIME_RESOLUTION_MS_TIMES | 46 | // @see SRS_SYS_TIME_RESOLUTION_MS_TIMES |
| 47 | #define SYS_TIME_RESOLUTION_US 300*1000 | 47 | #define SYS_TIME_RESOLUTION_US 300*1000 |
| 48 | 48 | ||
| 49 | +int srs_avc_nalu_read_uev(SrsBitStream* stream, int64_t& v) | ||
| 50 | +{ | ||
| 51 | + int ret = ERROR_SUCCESS; | ||
| 52 | + | ||
| 53 | + if (stream->empty()) { | ||
| 54 | + return ERROR_AVC_NALU_UEV; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + // ue(v) in 9.1 Parsing process for Exp-Golomb codes | ||
| 58 | + // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 227. | ||
| 59 | + // Syntax elements coded as ue(v), me(v), or se(v) are Exp-Golomb-coded. | ||
| 60 | + // leadingZeroBits = -1; | ||
| 61 | + // for( b = 0; !b; leadingZeroBits++ ) | ||
| 62 | + // b = read_bits( 1 ) | ||
| 63 | + // The variable codeNum is then assigned as follows: | ||
| 64 | + // codeNum = (2<<leadingZeroBits) – 1 + read_bits( leadingZeroBits ) | ||
| 65 | + int leadingZeroBits = -1; | ||
| 66 | + for (int8_t b = 0; !b && !stream->empty(); leadingZeroBits++) { | ||
| 67 | + b = stream->read_bit(); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + if (leadingZeroBits >= 64) { | ||
| 71 | + return ERROR_AVC_NALU_UEV; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + v = (1 << leadingZeroBits) - 1; | ||
| 75 | + for (int i = 0; i < leadingZeroBits; i++) { | ||
| 76 | + int64_t b = stream->read_bit(); | ||
| 77 | + v += b << (leadingZeroBits - 1); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + return ret; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +int srs_avc_nalu_read_bit(SrsBitStream* stream, int8_t& v) | ||
| 84 | +{ | ||
| 85 | + int ret = ERROR_SUCCESS; | ||
| 86 | + | ||
| 87 | + if (stream->empty()) { | ||
| 88 | + return ERROR_AVC_NALU_UEV; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + v = stream->read_bit(); | ||
| 92 | + | ||
| 93 | + return ret; | ||
| 94 | +} | ||
| 95 | + | ||
| 49 | static int64_t _srs_system_time_us_cache = 0; | 96 | static int64_t _srs_system_time_us_cache = 0; |
| 50 | static int64_t _srs_system_time_startup_time = 0; | 97 | static int64_t _srs_system_time_startup_time = 0; |
| 51 | 98 |
| @@ -33,11 +33,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,11 +33,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | #include <string> | 33 | #include <string> |
| 34 | 34 | ||
| 35 | class SrsStream; | 35 | class SrsStream; |
| 36 | +class SrsBitStream; | ||
| 36 | 37 | ||
| 37 | // compare | 38 | // compare |
| 38 | #define srs_min(a, b) (((a) < (b))? (a) : (b)) | 39 | #define srs_min(a, b) (((a) < (b))? (a) : (b)) |
| 39 | #define srs_max(a, b) (((a) < (b))? (b) : (a)) | 40 | #define srs_max(a, b) (((a) < (b))? (b) : (a)) |
| 40 | 41 | ||
| 42 | +// read nalu uev. | ||
| 43 | +extern int srs_avc_nalu_read_uev(SrsBitStream* stream, int64_t& v); | ||
| 44 | +extern int srs_avc_nalu_read_bit(SrsBitStream* stream, int8_t& v); | ||
| 45 | + | ||
| 41 | // get current system time in ms, use cache to avoid performance problem | 46 | // get current system time in ms, use cache to avoid performance problem |
| 42 | extern int64_t srs_get_system_time_ms(); | 47 | extern int64_t srs_get_system_time_ms(); |
| 43 | extern int64_t srs_get_system_startup_time_ms(); | 48 | extern int64_t srs_get_system_startup_time_ms(); |
-
请 注册 或 登录 后发表评论