-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathsei_parser.c
More file actions
141 lines (124 loc) · 4.52 KB
/
sei_parser.c
File metadata and controls
141 lines (124 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* Extracts the SEI information of a raw H.264 video stream
* to check whether the frame_packing flag is set appropriately
* for 3D stereoscopic video to be detected correctly by players
* Compilable for Linux and Windows
*/
#define _CRT_SECURE_NO_WARNINGS // suppress windows compile warning for insecure fopen calls
#include <stdlib.h>
#include <stdio.h>
int mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
int readBit(unsigned char data[], int* bitpos) {
int bit = (data[*bitpos/8] & mask[*bitpos%8]) != 0 ? 1 : 0;
(*bitpos)++;
return bit;
}
long readUnsigned(unsigned char data[], int* bitpos, int length) {
long value = 0;
while (length-->0)
if (readBit(data, bitpos) == 1)
value += 1<<length;
return value;
}
long readUExpGolomb(unsigned char data[], int* bitpos) {
int zeros = 0;
while (readBit(data, bitpos) == 0)
zeros++;
return (1<<zeros)-1 + readUnsigned(data, bitpos, zeros);
}
void parse_sei_payload(unsigned char payload[], int payload_size) {
int bitpos = 0;
int frame_packing_arrangement_cancel_flag;
long frame_packing_arrangement_type;
int quincunx_sampling_flag;
printf("frame_packing_arrangement_id = %li\n", readUExpGolomb(payload, &bitpos));
frame_packing_arrangement_cancel_flag = readBit(payload, &bitpos);
printf("frame_packing_arrangement_cancel_flag = %i\n", frame_packing_arrangement_cancel_flag);
if (!frame_packing_arrangement_cancel_flag) {
frame_packing_arrangement_type = readUnsigned(payload, &bitpos, 7);
printf("frame_packing_arrangement_type = %li\n", frame_packing_arrangement_type);
quincunx_sampling_flag = readBit(payload, &bitpos);
printf("quincunx_sampling_flag = %i\n", quincunx_sampling_flag);
printf("content_interpretation_type = %li\n", readUnsigned(payload, &bitpos, 6));
printf("spatial_flipping_flag = %i\n", readBit(payload, &bitpos));
printf("frame0_flipped_flag = %i\n", readBit(payload, &bitpos));
printf("field_views_flag = %i\n", readBit(payload, &bitpos));
printf("current_frame_is_frame0_flag = %i\n", readBit(payload, &bitpos));
printf("frame0_self_contained_flag = %i\n", readBit(payload, &bitpos));
printf("frame1_self_contained_flag = %i\n", readBit(payload, &bitpos));
if (!quincunx_sampling_flag && frame_packing_arrangement_type != 5) {
printf("frame0_grid_position_x = %li\n", readUnsigned(payload, &bitpos, 4));
printf("frame0_grid_position_y = %li\n", readUnsigned(payload, &bitpos, 4));
printf("frame1_grid_position_x = %li\n", readUnsigned(payload, &bitpos, 4));
printf("frame1_grid_position_y = %li\n", readUnsigned(payload, &bitpos, 4));
}
printf("frame_packing_arrangement_reserved_byte = %li\n", readUnsigned(payload, &bitpos, 8));
printf("frame_packing_arrangement_repetition_period = %li\n", readUExpGolomb(payload, &bitpos));
}
printf("frame_packing_arrangement_extension_flag = %i\n", readBit(payload, &bitpos));
printf("rbsp trailer: ");
while (bitpos < payload_size*8) {
printf("%i", readBit(payload, &bitpos));
if (bitpos % 8 == 0)
printf(" ");
}
printf("\n");
}
void parse_sei_unit(FILE* f) {
int payload_type = 0;
int payload_size = 0;
unsigned char* payload;
int i, emu_count;
printf("found a SEI NAL unit!\n");
while (!feof(f) && payload_type % 0xFF == 0)
payload_type += fgetc(f);
printf("payload_type = %i\n", payload_type);
while (!feof(f) && payload_size % 0xFF == 0)
payload_size += fgetc(f);
printf("payload_size = %i\n", payload_size);
if (payload_type != 45)
return;
payload = (unsigned char*)malloc(payload_size*sizeof(unsigned char));
for (i=0, emu_count=0; i<payload_size && !feof(f); i++, emu_count++) {
payload[i] = fgetc(f);
// drop emulation prevention bytes
if (emu_count>=2 && payload[i] == 0x03 && payload[i-1] == 0x00 && payload[i-2] == 0x00) {
i--;
emu_count = 0;
}
}
if (i != payload_size) {
fprintf(stderr, "EOF reached while reading SEI payload");
free(payload);
return;
}
parse_sei_payload(payload, payload_size);
free(payload);
}
void seek_sei(char* filename) {
int offset = 0;
int checklen = 0;
FILE* f = fopen(filename, "r");
while (!feof(f)) {
if (checklen < 2 && fgetc(f) == 0x00)
checklen++;
else if (checklen == 2 && fgetc(f) == 0x01)
checklen++;
else if (checklen == 3 && fgetc(f) == 0x06) {
parse_sei_unit(f);
checklen = 0;
}
else
checklen = 0;
}
fclose(f);
}
int main(int argc, char** args) {
if (argc != 2)
printf("Usage: sei_parser <h264-file>\n or simply drag&drop a h264-file on this program\n2011-11-03-schiermike\n\n");
else
seek_sei(args[1]);
printf("Press any key to quit...\n");
getchar();
return 0;
}