java - 解析问题H.264序列参数集数据

标签 java parsing h.264

我需要从原始 H.264 数据解析图像大小。以下测试代码适用于我测试的案例,但现在如果在“Z0IAIOKQCgDLYC3AQEBpB4kRUA==”上失败。结果应该是 1280x800,但它给了我 640x1616:

public static void main(String[] args) {
    decode(StringUtils.fromBase64("Z0IAKeKQCgDLYC3AQEBpB4kRUA=="));
    decode(StringUtils.fromBase64("Z0IAIOKQCgDLYC3AQEBpB4kRUA=="));
    decode(StringUtils.fromBase64("Z0IAHuNQFAe2AtwEBAaQeJEV"));
}

static int pos;
static byte[] data;

private static void decode(byte[] data) {
    try {
        System.out.println();
        System.out.println(StringUtils.toHex(data));
        System.out.println(StringUtils.toBin(data, 0, data.length, true));
        System.out.println();
        pos = 0;
        T.data = data;
        int profile_idc = getU(8);
        int constraint_set0_flag = getU(1);
        int constraint_set1_flag = getU(1);
        int constraint_set2_flag = getU(1);
        int constraint_set3_flag = getU(1);
        int reserved_zero_4bits = getU(4);
        int level_idc = getU(8);
        int seq_parameter_set_id = uev();
        int log2_max_frame_num_minus4 = uev();
        int pict_order_cnt_type = uev();
        System.out.println("pict_order_cnt_type=" + pict_order_cnt_type);
        if (pict_order_cnt_type == 0) {
            uev();
        } else if (pict_order_cnt_type == 1) {
            getU(1);
            sev();
            sev();
            int n = uev();
            System.out.println("n*sev, n=" + n);
            for (int i = 0; i < n; i++)
                sev();
        }
        int num_ref_frames = uev();
        getU(1);
        int pic_width = (uev() + 1) * 16;
        int pic_height = (uev() + 1) * 16;
        int frame_mbs_only_flag = getU(1);
        System.out.println(pic_width + " x " + pic_height);
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

private static int ev(boolean signed) {
    int bitcount = 0;
    StringBuilder expGolomb = new StringBuilder();
    while (getBit() == 0) {
        expGolomb.append('0');
        bitcount++;
    }
    expGolomb.append("/1");
    int result = 1;
    for (int i = 0; i < bitcount; i++) {
        int b = getBit();
        expGolomb.append(b);
        result = result * 2 + b;
    }
    result--;
    if (signed) {
        result = (result + 1) / 2 * (result % 2 == 0 ? -1 : 1);
        System.out.println("getSe(v) = " + (result) + " " + expGolomb);
    } else {
        System.out.println("getUe(v) = " + (result) + " " + expGolomb);
    }
    return result;
}

private static int uev() {
    return ev(false);
}

private static int sev() {
    return ev(true);
}

private static int getU(int bits) {
    int result = 0;
    for (int i = 0; i < bits; i++) {
        result = result * 2 + getBit();
    }
    System.out.println("getU(" + bits + ") = " + result);
    return result;
}

private static int getBit() {
    int mask = 1 << (7 - (pos & 7));
    int idx = pos >> 3;
    pos++;
    return ((data[idx] & mask) == 0) ? 0 : 1;
}

失败案例的输出:

67420020E2900A00CB602DC040406907891150
01100111 01000010 00000000 00100000 11100010 10010000 00001010 00000000 11001011 01100000 00101101 11000000 01000000 01000000 01101001 00000111 10001001 00010001 01010000 

getU(8) = 103
getU(1) = 0
getU(1) = 1
getU(1) = 0
getU(1) = 0
getU(4) = 2   << shouldn't this be 0 ? is same with correct parsing!
getU(8) = 0
getUe(v) = 3 00/100
getUe(v) = 13 000/1110   << log2_max_frame_num_minus4 shall be 0-12, inclusive.
getUe(v) = 4 00/101    
pict_order_cnt_type=4    << pic_order_cnt_type shall be 0-2, inclusive.
getUe(v) = 3 00/100       
getU(1) = 0
getUe(v) = 39 00000/101000
getUe(v) = 100 000000/1100101
getU(1) = 1
640 x 1616

最佳答案

也许不是你要求的,但看看引用实现,看看他们是如何进行解析的......

  1. http://www.w6rz.net/h264_parse.zip 下载 h.264 解析器(来自这个线程@doom9 http://forum.doom9.org/archive/index.php/t-133070.html)

  2. http://iphome.hhi.de/suehring/tml/ 下载 H.264 引用软件

这应该可以帮助您入门。 BTW 比特流在附件中描述。 B. 在规范中。从国际电联下载http://www.itu.int/rec/T-REC-H.264-201003-I/en

关于java - 解析问题H.264序列参数集数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6189689/

相关文章:

java - 配置 WebLogic MDB 以监听外部 AMQ 服务器

java - 每秒检查一次时间

java - 如何从 Map<K, List<T>> 创建 Map<T, List<K>>?

c++ - 在 C++ 中通过定界符解析字符串

sql - 从大型 XML 数据创建 SQL 数据库表

parsing - 解析声音文件

c++ - 媒体基础 H264 解码器无法正常工作

java - 我不认为Long.java中的numberOfLeadingZeros(long i)是基于floor(log2(x)) = 63 - numberOfLeadingZeros(x)!

android - Chrome Android 未使用 SDP 提供的所有编解码器选项

ffmpeg - H.264 - 识别图像的访问单元