• 获得H.264视频分辨率的方法


    在使用ffmpeg解码播放TS流的时候(例如之前写过的UDP组播流),在连接时往往需要耗费大量时间。经过debug发现是av_find_stream_info(已抛弃,现在使用的是avformat_find_stream_info)这个方法十分耗时,而且是阻塞的。av_find_stream_info方法主要是获得相应的流信息,其中对我的应用最有用的就是视频的分辨率。在av_find_stream_info中是要不断的读取数据包,解码获得相应的信息,而其中除了分辨率信息以外的东西对我的应用中是无用的。所以,考虑自己手动从H.264码流中解析出视频的分辨率信息。

        以下内容主要参考了这篇文章:http://www.myexception.cn/internet/586390.html

           H.264码流的流信息都存储在了特殊的结构中,叫做SPS(Sequence Parameter Set)。要解析SPS就需要知道一些H.264码流的格式信息。

        在H.264码流中,都是以0x00 0x00 0x01 或者 0x00 0x00 0x00 0x01为开始码的(在我的应用中为后者),之后通过检测开始码后第一个字节的后五位是否为7(00111)来判断其是否为SPS。得到SPS之后,就可以解析出视频的分辨率。SPS中有两个成员,pic_width_in_mbs_minus1和pic_height_in_map_units_minus_1,分别表示图像的宽和高,但是要注意的是它们都是以16为单位(在面积上就是以16*16的块为单位)再减1,所以实际的宽是(pic_width_in_mbs_minus1 + 1)*16,高为(pic_height_in_map_units_minus_1+1)*16。

          欢迎转载,转载请注明出处:http://guoyb.com/Tech/34.html

        以下是解析宽高的代码:

    转载http://guoyb.com/Tech/34.html

    以下部分 转自 http://blog.csdn.net/pkueecser/article/details/7367641

    使用RTP传输H264的时候,需要用到sdp协议描述,其中有两项:Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS)需要用到,那么这两项从哪里获取呢?答案是从H264码流中获取.在H264码流中,都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"为开始码的,找到开始码之后,使用开始码之后的第一个字节的低5位判断是否为7(sps)或者8(pps), 及data[4] & 0x1f == 7 || data[4] & 0x1f == 8.然后对获取的nal去掉开始码之后进行base64编码,得到的信息就可以用于sdp.sps和pps需要用逗号分隔开来.

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    如何解析SDP中包含的H.264的SPS和PPS串

    http://www.pernet.tv.sixxs.org/thread-109-1-1.html

    SDP中的H.264的SPS和PPS串,包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高,deblock滤波器等。
    由于SDP中的SPS和PPS都是BASE64编码形式的,不容易理解,附件有一个工具软件可以对SDP中的SPS和PPS进行解析。
    用法是在命令行中输入:
    spsparser sps.txt pps.txt output.txt

    例如sps.txt中的内容为:
    Z0LgFNoFglE=
    pps.txt中的内容为:
    aM4wpIA=

    最终解析的到的结果为:

    Start dumping SPS:
      profile_idc = 66
      constrained_set0_flag = 1
      constrained_set1_flag = 1
      constrained_set2_flag = 1
      constrained_set3_flag = 0
      level_idc = 20
      seq_parameter_set_id = 0
      chroma_format_idc = 1
      bit_depth_luma_minus8 = 0
      bit_depth_chroma_minus8 = 0
      seq_scaling_matrix_present_flag = 0
      log2_max_frame_num_minus4 = 0
      pic_order_cnt_type = 2
      log2_max_pic_order_cnt_lsb_minus4 = 0
      delta_pic_order_always_zero_flag = 0
      offset_for_non_ref_pic = 0
      offset_for_top_to_bottom_field = 0
      num_ref_frames_in_pic_order_cnt_cycle = 0
      num_ref_frames = 1
      gaps_in_frame_num_value_allowed_flag = 0
      pic_width_in_mbs_minus1 = 21
      pic_height_in_mbs_minus1 = 17
      frame_mbs_only_flag = 1
      mb_adaptive_frame_field_flag = 0
      direct_8x8_interence_flag = 0
      frame_cropping_flag = 0
      frame_cropping_rect_left_offset = 0
      frame_cropping_rect_right_offset = 0
      frame_cropping_rect_top_offset = 0
      frame_cropping_rect_bottom_offset = 0
      vui_parameters_present_flag = 0

    Start dumping PPS:
      pic_parameter_set_id = 0
      seq_parameter_set_id = 0
      entropy_coding_mode_flag = 0
      pic_order_present_flag = 0
      num_slice_groups_minus1 = 0
      slice_group_map_type = 0
      num_ref_idx_l0_active_minus1 = 0
      num_ref_idx_l1_active_minus1 = 0
      weighted_pref_flag = 0
      weighted_bipred_idc = 0
      pic_init_qp_minus26 = 0
      pic_init_qs_minus26 = 0
      chroma_qp_index_offset = 10
      deblocking_filter_control_present_flag = 1
      constrained_intra_pred_flag = 0
      redundant_pic_cnt_present_flag = 0
      transform_8x8_mode_flag = 0
      pic_scaling_matrix_present_flag = 0
      second_chroma_qp_index_offset = 10

    /////////////////////////////////////////////////////////////////////////////////////////////////
    这里需要特别提一下这两个参数
    pic_width_in_mbs_minus1 = 21
      pic_height_in_mbs_minus1 = 17
    分别表示图像的宽和高,以宏块(16x16)为单位的值减1
    因此,实际的宽为 (21+1)*16 = 352
     spsparser.rar

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    http://krdai.info.sixxs.org/blog/mp4-sps-pps-data.html

    最近在做跟 h264 encode/decode 相關的研究,目標是希望可以從 Android 的 MediaRecorder 當中取出 h264 的資訊。目前問題是在於 SPS 以及 PPS 到底要怎樣得到。由於 MediaRecorder 是寫入 mp4 檔案中,所以不得已只好來去分析一下 mp4 的檔案格式,發現沒有想像中的困難. 主要是參照 ISO/IEC 14496-15 這部份. 在 mp4 的檔案之中, 找到 avcC 這個字串, 之後就是接上 AVCDecoderConfigurationRecord. AVCDecoderConfigurationRecord 的 format 如下:

    [cpp] view plaincopy
     
    1. aligned(8) class AVCDecoderConfigurationRecord {  
    2.    unsigned int(8) configurationVersion = 1;  
    3.    unsigned int(8) AVCProfileIndication;  
    4.    unsigned int(8) profile_compatibility;  
    5.    unsigned int(8) AVCLevelIndication;  
    6.   
    7. bit(6) reserved = '111111'b;  
    8.    unsigned int(2) lengthSizeMinusOne;  
    9.   
    10. bit(3) reserved = '111'b;  
    11.    unsigned int(5) numOfSequenceParameterSets;  
    12.   
    13. for (i=0; i< numOfSequenceParameterSets; i++) {  
    14.       unsigned int(16) sequenceParameterSetLength ;  
    15.       bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;  
    16.    }  
    17.    unsigned int(8) numOfPictureParameterSets;  
    18.    for (i=0; i< numOfPictureParameterSets; i++) {  
    19.       unsigned int(16) pictureParameterSetLength;  
    20.       bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;  
    21.    }  
    22. }  

    對照一下這樣就可以找到 SPS 和 PPS

    +++++++++++++++++++++++++++++++++++++++++++++
     
    vlc没有收到pps和sps
    2010-10-08 16:16
    问题 packetizer_h264 packetizer warning: waiting for SPS/PPS

    是因为解码器只是在第一次执行编码的时候,才编码出 SPS、PPS、和I_Frame; 
    h264 packetizer has set so, that it sends sps/pps only first keyframe,
     I'm trying to figure what breaks if that is changed so sps/pps is written in every keyframe. 
    [出自| http://trac.videolan.org/vlc/ticket/1384]

    解决办法:

    1、编码器编码出每个关键帧都加上SPS、PPS ,据说通常情况编码器编出的 SPS、PPS是一样的,所以这种方法耗费资源。

    2、在服务器接收到客户端请求时,发送第一个package 加上 SPS、PPS。

    具体如下:

    • 1、在 VideoOpenFileSource 添加一个变量 isFirstFrame;

    • 2、构造时初始化 isFirstFrame = true;
    • 3、在int VideoOpenFileSource::readFromBufferChain() 修改如下:

    •    1         if(isFirstFrame == true)
         2         {
         3                 memcpy(fTo, h264_header, sizeof(h264_header)); /* h264_header = pps +sps*/
         4                 offset = sizeof(h264_header);
         5                 framesize = BufferChain_get(fInput.video_bufs, fTo + offset);
         6                 offset += framesize;
         7                 isFirstFrame = false;
         8                 printf("this is the first fime
      ");
         9                 sleep(1);
        10         }
        11         else
        12         {
        13                 framesize = BufferChain_get(fInput.video_bufs, fTo + offset);
        14                 offset += framesize;
        15         }
        1
    [http://topic.csdn.net/u/20100801/17/ef35e664-92ff-4144-a35f-3984dcf11da3.html| 参考] 
    
    
    ========================================================================
    sdp 关于pps和sps的疑问:
    packetization-mode 主要是定义包的模式,单一 NALU单元模式(0);非交错(non-interleaved)封包模式(1);交错(interleaved)封包模式(2)
    sprop-parameter-sets 等于H.264 的序列参数集和图像参数 NAL单元,base64转换;(即= sps+pps)
    profile-level-id 这个参数用于指示 H.264 流的 profile 类型和级别。这知道这个是啥东东
    
    参考 黑暗长老 www.cppblog.com/czanyou/
    ffmpeg decode 关于pps sps问题:
    stackoverflow.com/questions/3493742/problem-to-decode-h264-video-over-rtp-with-ffmpeg-libavcodec/3500432#3500432

    如何用C语言取出H.264ES文件里的nal(sps,pps)信息。比如width, height, profile等等

    请高手指点指点。。。 http://www.oschina.net/question/225813_35707

    解析sps,pps的代码在ffmpeg里面就有, 抄出来就行了, 我以前也自己写过...
    ffmpeg的libavcodec/h264_parser.c,
    h264_ps.c
    函数
    ff_h264_decode_seq_parameter_set
    ff_h264_decode_picture_parameter_set
    自己可以看代码.

    H264参数语法文档: SPS、PPS、IDR http://blog.csdn.net/heanyu/article/details/6205390

    H.264码流第一个 NALU 是 SPS(序列参数集Sequence Parameter Set)
    对应H264标准文档 7.3.2.1 序列参数集的语法进行解析

     
  • 相关阅读:
    Sample XPS Documents Download
    触发器中的inserted表和deleted表
    Using freewheel.labs.autodesk.com to auto generate preview images of DWF files on your web site
    解除SQL对组件"Ad Hoc Distributed Queries"的"STATEMENT'OpenRowset OpenDatasource"的访问
    读写xps
    XPS文件,在Windows XP下的打开查看阅读和打印方法。
    Learning to Reference Inserted and Deleted Tables
    Get value from updated, inserted and deleted
    Reinstall Microsoft Helper Viewer
    如何查找文件的IFilter
  • 原文地址:https://www.cnblogs.com/likwo/p/3531241.html
Copyright © 2020-2023  润新知