1 /*
2 * Copyright 2015 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "h264e_sei"
18
19 #include <string.h>
20
21 #include "mpp_common.h"
22
23 #include "mpp_bitwrite.h"
24 #include "mpp_packet_impl.h"
25 #include "h264e_debug.h"
26
27 #include "h264_syntax.h"
28 #include "h264e_sei.h"
29
write_recovery_point(MppWriteCtx * bit,RK_U32 recovery_frame_cnt)30 static MPP_RET write_recovery_point(MppWriteCtx *bit, RK_U32 recovery_frame_cnt)
31 {
32 mpp_writer_put_ue(bit, recovery_frame_cnt);
33 mpp_writer_put_bits(bit, 1, 1);
34 mpp_writer_put_bits(bit, 0, 1);
35 mpp_writer_put_bits(bit, 0, 2);
36 mpp_writer_trailing(bit);
37 return MPP_OK;
38 }
39
h264e_sei_recovery_point_to_packet(MppPacket packet,RK_S32 * len,RK_U32 recovery_frame_cnt)40 MPP_RET h264e_sei_recovery_point_to_packet(MppPacket packet, RK_S32 *len, RK_U32 recovery_frame_cnt)
41 {
42 MPP_RET ret = MPP_OK;
43 void *pos = mpp_packet_get_pos(packet);
44 void *pkt_base = mpp_packet_get_data(packet);
45 size_t pkt_size = mpp_packet_get_size(packet);
46 size_t length = mpp_packet_get_length(packet);
47 void *dst = pos + length;
48 RK_S32 buf_size = (pkt_base + pkt_size) - (pos + length);
49 MppWriteCtx bit_ctx;
50 MppWriteCtx *bit = &bit_ctx;
51 RK_S32 payload_size = 0;
52 RK_S32 type = H264_SEI_RECOVERY_POINT;
53 RK_U8 src[100] = {0};
54 RK_S32 sei_size = 0;
55 RK_S32 i;
56 mpp_writer_init(bit, src, 100);
57 write_recovery_point(bit, recovery_frame_cnt);
58 payload_size = mpp_writer_bytes(bit);
59
60 mpp_writer_init(bit, dst, buf_size);
61
62 /* start_code_prefix 00 00 00 01 */
63 mpp_writer_put_raw_bits(bit, 0, 24);
64 mpp_writer_put_raw_bits(bit, 1, 8);
65 /* forbidden_zero_bit */
66 mpp_writer_put_raw_bits(bit, 0, 1);
67 /* nal_ref_idc */
68 mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_DISPOSABLE, 2);
69 /* nal_unit_type */
70 mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_SEI, 5);
71
72 /* sei_payload_type_ff_byte */
73 for (i = 0; i <= type - 255; i += 255)
74 mpp_writer_put_bits(bit, 0xff, 8);
75
76 /* sei_last_payload_type_byte */
77 mpp_writer_put_bits(bit, type - i, 8);
78
79 /* sei_payload_size_ff_byte */
80 for (i = 0; i <= payload_size - 255; i += 255)
81 mpp_writer_put_bits(bit, 0xff, 8);
82
83 /* sei_last_payload_size_byte */
84 mpp_writer_put_bits(bit, payload_size - i, 8);
85
86 write_recovery_point(bit, recovery_frame_cnt);
87
88 sei_size = mpp_writer_bytes(bit);
89 if (len)
90 *len = sei_size;
91
92 mpp_packet_set_length(packet, length + sei_size);
93 mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SEI, length, sei_size);
94
95 h264e_dbg_sei("sei data length %d pkt len %d -> %d\n", sei_size,
96 length, length + sei_size);
97
98 return ret;
99
100 }
101
h264e_sei_to_packet(MppPacket packet,RK_S32 * len,RK_S32 type,RK_U8 uuid[16],const void * data,RK_S32 size)102 MPP_RET h264e_sei_to_packet(MppPacket packet, RK_S32 *len, RK_S32 type,
103 RK_U8 uuid[16], const void *data, RK_S32 size)
104 {
105 void *pos = mpp_packet_get_pos(packet);
106 void *pkt_base = mpp_packet_get_data(packet);
107 size_t pkt_size = mpp_packet_get_size(packet);
108 size_t length = mpp_packet_get_length(packet);
109 const RK_U8 *src = (RK_U8 *)data;
110 void *dst = pos + length;
111 RK_S32 buf_size = (pkt_base + pkt_size) - (pos + length);
112 MppWriteCtx bit_ctx;
113 MppWriteCtx *bit = &bit_ctx;
114 RK_S32 uuid_size = uuid ? 16 : 0;
115 RK_S32 payload_size = size + uuid_size;
116 RK_S32 sei_size = 0;
117 RK_S32 i;
118
119 h264e_dbg_sei("write sei to pkt [%p:%u] [%p:%u]\n", pkt_base, pkt_size,
120 pos, length);
121
122 mpp_writer_init(bit, dst, buf_size);
123
124 /* start_code_prefix 00 00 00 01 */
125 mpp_writer_put_raw_bits(bit, 0, 24);
126 mpp_writer_put_raw_bits(bit, 1, 8);
127 /* forbidden_zero_bit */
128 mpp_writer_put_raw_bits(bit, 0, 1);
129 /* nal_ref_idc */
130 mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_DISPOSABLE, 2);
131 /* nal_unit_type */
132 mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_SEI, 5);
133
134 /* sei_payload_type_ff_byte */
135 for (i = 0; i <= type - 255; i += 255)
136 mpp_writer_put_bits(bit, 0xff, 8);
137
138 /* sei_last_payload_type_byte */
139 mpp_writer_put_bits(bit, type - i, 8);
140
141 /* sei_payload_size_ff_byte */
142 for (i = 0; i <= payload_size - 255; i += 255)
143 mpp_writer_put_bits(bit, 0xff, 8);
144
145 /* sei_last_payload_size_byte */
146 mpp_writer_put_bits(bit, payload_size - i, 8);
147
148 /* uuid_iso_iec_11578 */
149 for (i = 0; i < uuid_size; i++)
150 mpp_writer_put_bits(bit, uuid[i], 8);
151
152 /* sei_payload_data */
153 for (i = 0; i < size; i++)
154 mpp_writer_put_bits(bit, src[i], 8);
155
156 mpp_writer_trailing(bit);
157
158 sei_size = mpp_writer_bytes(bit);
159 if (len)
160 *len = sei_size;
161
162 mpp_packet_set_length(packet, length + sei_size);
163 mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SEI, length, sei_size);
164
165 h264e_dbg_sei("sei data length %d pkt len %d -> %d\n", sei_size,
166 length, length + sei_size);
167
168 return MPP_OK;
169 }
170