1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 #include "extra_data_handler.h"
30
extra_data_handler()31 extra_data_handler::extra_data_handler()
32 {
33 rbsp_buf = (OMX_U8 *) calloc(1,100);
34 memset(&frame_packing_arrangement,0,sizeof(frame_packing_arrangement));
35 frame_packing_arrangement.cancel_flag = 1;
36 pack_sei = false;
37 sei_payload_type = -1;
38 }
39
~extra_data_handler()40 extra_data_handler::~extra_data_handler()
41 {
42 if (rbsp_buf) {
43 free(rbsp_buf);
44 rbsp_buf = NULL;
45 }
46 }
47
d_u(OMX_U32 num_bits)48 OMX_U32 extra_data_handler::d_u(OMX_U32 num_bits)
49 {
50 OMX_U32 rem_bits = num_bits, bins = 0, shift = 0;
51
52 while (rem_bits >= bit_ptr) {
53 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr,
54 byte_ptr, rbsp_buf[byte_ptr]);
55 bins <<= shift;
56 shift = (8-bit_ptr);
57 bins |= ((rbsp_buf[byte_ptr] << shift) & 0xFF) >> shift;
58 rem_bits -= bit_ptr;
59 bit_ptr = 8;
60 byte_ptr ++;
61 }
62
63 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr,
64 byte_ptr, rbsp_buf[byte_ptr]);
65
66 if (rem_bits) {
67 bins <<= rem_bits;
68 bins |= ((rbsp_buf[byte_ptr] << (8-bit_ptr)) & 0xFF) >> (8-rem_bits);
69 bit_ptr -= rem_bits;
70
71 if (bit_ptr == 0) {
72 bit_ptr = 8;
73 byte_ptr++;
74 }
75 }
76
77 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr,
78 byte_ptr, rbsp_buf[byte_ptr]);
79
80 DEBUG_PRINT_LOW("\nIn %s() bin/num_bits : %x/%d", __func__, bins, num_bits);
81 return bins;
82 }
83
d_ue()84 OMX_U32 extra_data_handler::d_ue()
85 {
86 OMX_S32 lead_zeros = -1;
87 OMX_U32 symbol, bit;
88
89 do {
90 bit = d_u(1);
91 lead_zeros++;
92 } while (!bit);
93
94 symbol = ((1 << lead_zeros) - 1) + d_u(lead_zeros);
95
96 DEBUG_PRINT_LOW("\nIn %s() symbol : %d", __func__,symbol);
97 return symbol;
98 }
99
parse_frame_pack(OMX_U32 payload_size)100 OMX_U32 extra_data_handler::parse_frame_pack(OMX_U32 payload_size)
101 {
102 frame_packing_arrangement.id = d_ue();
103 frame_packing_arrangement.cancel_flag = d_u(1);
104
105 if (!frame_packing_arrangement.cancel_flag) {
106 frame_packing_arrangement.type = d_u(7);
107 frame_packing_arrangement.quincunx_sampling_flag = d_u(1);
108 frame_packing_arrangement.content_interpretation_type = d_u(6);
109 frame_packing_arrangement.spatial_flipping_flag = d_u(1);
110 frame_packing_arrangement.frame0_flipped_flag = d_u(1);
111 frame_packing_arrangement.field_views_flag = d_u(1);
112 frame_packing_arrangement.current_frame_is_frame0_flag = d_u(1);
113 frame_packing_arrangement.frame0_self_contained_flag = d_u(1);
114 frame_packing_arrangement.frame1_self_contained_flag = d_u(1);
115
116 if (!frame_packing_arrangement.quincunx_sampling_flag &&
117 frame_packing_arrangement.type != 5) {
118 frame_packing_arrangement.frame0_grid_position_x = d_u(4);
119 frame_packing_arrangement.frame0_grid_position_y = d_u(4);
120 frame_packing_arrangement.frame1_grid_position_x = d_u(4);
121 frame_packing_arrangement.frame1_grid_position_y = d_u(4);
122 }
123
124 frame_packing_arrangement.reserved_byte = d_u(8);
125 frame_packing_arrangement.repetition_period = d_ue();
126 }
127
128 frame_packing_arrangement.extension_flag = d_u(1);
129
130 return 1;
131 }
132
parse_rbsp(OMX_U8 * buf,OMX_U32 len)133 OMX_S32 extra_data_handler::parse_rbsp(OMX_U8 *buf, OMX_U32 len)
134 {
135 OMX_U32 i = 3, j=0, startcode;
136 OMX_U32 nal_unit_type, nal_ref_idc, forbidden_zero_bit;
137
138 bit_ptr = 8;
139 byte_ptr = 0;
140
141 startcode = buf[0] << 16 | buf[1] <<8 | buf[2];
142
143 if (!startcode) {
144 startcode |= buf[i++];
145 }
146
147 if (startcode != H264_START_CODE) {
148 DEBUG_PRINT_ERROR("\nERROR: In %s() Start code not found", __func__);
149 return -1;
150 }
151
152 forbidden_zero_bit = (buf[i] & 0x80) >>7;
153
154 if (forbidden_zero_bit) {
155 DEBUG_PRINT_ERROR("\nERROR: In %s() Non-zero forbidden bit", __func__);
156 return -1;
157 }
158
159 nal_ref_idc = (buf[i] & 0x60) >>5;
160 DEBUG_PRINT_LOW("\nIn %s() nal_ref_idc ; %d", __func__, nal_ref_idc);
161
162 nal_unit_type = (buf[i++] & 0x1F);
163
164 while (i<len) {
165 if (!(buf[i] + buf[i+1]) && (buf[i+2] == H264_EMULATION_BYTE) &&
166 (i+2 < len)) {
167 rbsp_buf[j++] = buf[i++];
168 rbsp_buf[j++] = buf[i++];
169 i++;
170 } else
171 rbsp_buf[j++] = buf[i++];
172 }
173
174 return nal_unit_type;
175 }
parse_sei(OMX_U8 * buffer,OMX_U32 buffer_length)176 OMX_S32 extra_data_handler::parse_sei(OMX_U8 *buffer, OMX_U32 buffer_length)
177 {
178 OMX_U32 nal_unit_type, payload_type = 0, payload_size = 0;
179 OMX_U32 marker = 0, pad = 0xFF;
180
181 nal_unit_type = parse_rbsp(buffer, buffer_length);
182
183 if (nal_unit_type != NAL_TYPE_SEI) {
184 DEBUG_PRINT_ERROR("\nERROR: In %s() - Non SEI NAL ", __func__);
185 return -1;
186 } else {
187
188 while (rbsp_buf[byte_ptr] == 0xFF)
189 payload_type += rbsp_buf[byte_ptr++];
190
191 payload_type += rbsp_buf[byte_ptr++];
192
193 DEBUG_PRINT_LOW("\nIn %s() payload_type : %u", __func__, payload_type);
194
195 while (rbsp_buf[byte_ptr] == 0xFF)
196 payload_size += rbsp_buf[byte_ptr++];
197
198 payload_size += rbsp_buf[byte_ptr++];
199
200 DEBUG_PRINT_LOW("\nIn %s() payload_size : %u", __func__, payload_size);
201
202 switch (payload_type) {
203 case SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT:
204 DEBUG_PRINT_LOW("\nIn %s() Frame Packing SEI ", __func__);
205 parse_frame_pack(payload_size);
206 break;
207 default:
208 DEBUG_PRINT_LOW("\nINFO: In %s() Not Supported SEI NAL ", __func__);
209 break;
210 }
211 }
212
213 if (bit_ptr != 8) {
214 marker = d_u(1);
215
216 if (marker) {
217 if (bit_ptr != 8) {
218 pad = d_u(bit_ptr);
219
220 if (pad) {
221 DEBUG_PRINT_ERROR("\nERROR: In %s() padding Bits Error in SEI",
222 __func__);
223 return -1;
224 }
225 }
226 } else {
227 DEBUG_PRINT_ERROR("\nERROR: In %s() Marker Bit Error in SEI",
228 __func__);
229 return -1;
230 }
231 }
232
233 DEBUG_PRINT_LOW("\nIn %s() payload_size : %u/%u", __func__,
234 payload_size, byte_ptr);
235 return 1;
236 }
237
parse_ltrinfo(OMX_BUFFERHEADERTYPE * pBufHdr,OMX_OTHER_EXTRADATATYPE * pExtra)238 OMX_S32 extra_data_handler::parse_ltrinfo(
239 OMX_BUFFERHEADERTYPE *pBufHdr, OMX_OTHER_EXTRADATATYPE *pExtra)
240 {
241 OMX_U32 *pLTR;
242 pExtra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoLTRInfo;
243 pLTR = (OMX_U32* )pExtra + 5;
244 DEBUG_PRINT_HIGH("ExtraData LTR ID %d", *pLTR, 0, 0);
245 return 0;
246 }
247 /*======================================================================
248 Slice Information will be available as below (each line is of 4 bytes)
249 | number of slices |
250 | 1st slice offset |
251 | 1st slice size |
252 | .. |
253 | Nth slice offset |
254 | Nth slice size |
255 ======================================================================*/
parse_sliceinfo(OMX_BUFFERHEADERTYPE * pBufHdr,OMX_OTHER_EXTRADATATYPE * pExtra)256 OMX_S32 extra_data_handler::parse_sliceinfo(
257 OMX_BUFFERHEADERTYPE *pBufHdr, OMX_OTHER_EXTRADATATYPE *pExtra)
258 {
259 OMX_U32 slice_offset = 0, slice_size = 0, total_size = 0;
260 OMX_U8 *pBuffer = (OMX_U8 *)pBufHdr->pBuffer;
261 OMX_U32 *data = (OMX_U32 *)pExtra->data;
262 OMX_U32 num_slices = *data;
263 DEBUG_PRINT_LOW("number of slices = %d", num_slices);
264
265 if ((4 + num_slices * 8) != (OMX_U32)pExtra->nDataSize) {
266 DEBUG_PRINT_ERROR("unknown error in slice info extradata");
267 return -1;
268 }
269
270 for (int i = 0; i < num_slices; i++) {
271 slice_offset = (OMX_U32)(*(data + (i*2 + 1)));
272
273 if ((*(pBuffer + slice_offset + 0) != 0x00) ||
274 (*(pBuffer + slice_offset + 1) != 0x00) ||
275 (*(pBuffer + slice_offset + 2) != 0x00) ||
276 (*(pBuffer + slice_offset + 3) != H264_START_CODE)) {
277 DEBUG_PRINT_ERROR("found 0x%x instead of start code at offset[%d] "
278 "for slice[%d]", (OMX_U32)(*(OMX_U32 *)(pBuffer + slice_offset)),
279 slice_offset, i);
280 return -1;
281 }
282
283 if (slice_offset != total_size) {
284 DEBUG_PRINT_ERROR("offset of slice number %d is not correct "
285 "or previous slice size is not correct", i);
286 return -1;
287 }
288
289 slice_size = (OMX_U32)(*(data + (i*2 + 2)));
290 total_size += slice_size;
291 DEBUG_PRINT_LOW("slice number %d offset/size = %d/%d",
292 i, slice_offset, slice_size);
293 }
294
295 if (pBufHdr->nFilledLen != total_size) {
296 DEBUG_PRINT_ERROR("frame_size[%d] is not equal to "
297 "total slices size[%d]", pBufHdr->nFilledLen, total_size);
298 return -1;
299 }
300
301 return 0;
302 }
303
parse_extra_data(OMX_BUFFERHEADERTYPE * buf_hdr)304 OMX_U32 extra_data_handler::parse_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr)
305 {
306 DEBUG_PRINT_LOW("In %s() flags: 0x%x", __func__,buf_hdr->nFlags);
307
308 if (buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
309
310 OMX_OTHER_EXTRADATATYPE *extra_data = (OMX_OTHER_EXTRADATATYPE *)
311 ((unsigned)(buf_hdr->pBuffer + buf_hdr->nOffset +
312 buf_hdr->nFilledLen + 3)&(~3));
313
314 while (extra_data &&
315 ((OMX_U32)extra_data > (OMX_U32)buf_hdr->pBuffer) &&
316 ((OMX_U32)extra_data < (OMX_U32)buf_hdr->pBuffer + buf_hdr->nAllocLen)) {
317
318 DEBUG_PRINT_LOW("extradata(0x%x): nSize = 0x%x, eType = 0x%x,"
319 " nDataSize = 0x%x", (unsigned)extra_data, extra_data->nSize,
320 extra_data->eType, extra_data->nDataSize);
321
322 if ((extra_data->eType == VDEC_EXTRADATA_NONE) ||
323 (extra_data->eType == VEN_EXTRADATA_NONE)) {
324 DEBUG_PRINT_LOW("No more extradata available");
325 extra_data->eType = OMX_ExtraDataNone;
326 break;
327 } else if (extra_data->eType == VDEC_EXTRADATA_SEI) {
328 DEBUG_PRINT_LOW("Extradata SEI of size %d found, "
329 "parsing it", extra_data->nDataSize);
330 parse_sei(extra_data->data, extra_data->nDataSize);
331 } else if (extra_data->eType == VEN_EXTRADATA_QCOMFILLER) {
332 DEBUG_PRINT_LOW("Extradata Qcom Filler found, skip %d bytes",
333 extra_data->nSize);
334 } else if (extra_data->eType == VEN_EXTRADATA_SLICEINFO) {
335 DEBUG_PRINT_LOW("Extradata SliceInfo of size %d found, "
336 "parsing it", extra_data->nDataSize);
337 parse_sliceinfo(buf_hdr, extra_data);
338 }
339
340 #ifndef _MSM8974_
341 else if (extra_data->eType == VEN_EXTRADATA_LTRINFO) {
342 DEBUG_PRINT_LOW("Extradata LTRInfo of size %d found, "
343 "parsing it", extra_data->nDataSize);
344 parse_ltrinfo(buf_hdr, extra_data);
345 }
346
347 #endif
348 else {
349 DEBUG_PRINT_ERROR("Unknown extradata(0x%x) found, nSize = 0x%x, "
350 "eType = 0x%x, nDataSize = 0x%x", (unsigned)extra_data,
351 extra_data->nSize, extra_data->eType, extra_data->nDataSize);
352 buf_hdr->nFlags &= ~(OMX_BUFFERFLAG_EXTRADATA);
353 break;
354 }
355
356 extra_data = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) extra_data) +
357 extra_data->nSize);
358 }
359 }
360
361 return 1;
362 }
363
get_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT * frame_pack)364 OMX_U32 extra_data_handler::get_frame_pack_data(
365 OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack)
366 {
367 DEBUG_PRINT_LOW("\n%s:%d get frame data", __func__, __LINE__);
368 memcpy(&frame_pack->id,&frame_packing_arrangement.id,
369 FRAME_PACK_SIZE*sizeof(OMX_U32));
370 return 1;
371 }
372
set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT * frame_pack)373 OMX_U32 extra_data_handler::set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT
374 *frame_pack)
375 {
376 DEBUG_PRINT_LOW("\n%s:%d set frame data", __func__, __LINE__);
377 memcpy(&frame_packing_arrangement.id, &frame_pack->id,
378 FRAME_PACK_SIZE*sizeof(OMX_U32));
379 pack_sei = true;
380 sei_payload_type = SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT;
381 return 1;
382 }
383
e_u(OMX_U32 symbol,OMX_U32 num_bits)384 OMX_U32 extra_data_handler::e_u(OMX_U32 symbol, OMX_U32 num_bits)
385 {
386 OMX_U32 rem_bits = num_bits, shift;
387
388 DEBUG_PRINT_LOW("\n%s bin : %x/%d", __func__, symbol, num_bits);
389
390 while (rem_bits >= bit_ptr) {
391 shift = rem_bits - bit_ptr;
392 rbsp_buf[byte_ptr] |= (symbol >> shift);
393 symbol = (symbol << (32 - shift)) >> (32 - shift);
394 rem_bits -= bit_ptr;
395 DEBUG_PRINT_LOW("\n%sstream byte/rem_bits %x/%d", __func__,
396 rbsp_buf[byte_ptr], rem_bits);
397 byte_ptr ++;
398 bit_ptr = 8;
399 }
400
401 if (rem_bits) {
402 shift = bit_ptr - rem_bits;
403 rbsp_buf[byte_ptr] |= (symbol << shift);
404 bit_ptr -= rem_bits;
405 DEBUG_PRINT_LOW("\n%s 2 stream byte/rem_bits %x", __func__,
406 rbsp_buf[byte_ptr], rem_bits);
407
408 if (bit_ptr == 0) {
409 bit_ptr = 8;
410 byte_ptr++;
411 }
412 }
413
414 return 1;
415 }
416
e_ue(OMX_U32 symbol)417 OMX_U32 extra_data_handler::e_ue(OMX_U32 symbol)
418 {
419 OMX_U32 i, sym_len, sufix_len, info;
420 OMX_U32 nn =(symbol + 1) >> 1;
421
422 DEBUG_PRINT_LOW("\n%s bin : %x", __func__, symbol);
423
424 for (i=0; i < 33 && nn != 0; i++)
425 nn >>= 1;
426
427 sym_len = ((i << 1) + 1);
428 info = symbol + 1 - (1 << i);
429 sufix_len = (1 << (sym_len >>1));
430 info = sufix_len | (info & (sufix_len - 1));
431 e_u(info, sym_len);
432 return 1;
433 }
434
create_frame_pack()435 OMX_U32 extra_data_handler::create_frame_pack()
436 {
437 e_ue(frame_packing_arrangement.id);
438 e_u(frame_packing_arrangement.cancel_flag, 1);
439
440 if (!frame_packing_arrangement.cancel_flag) {
441 e_u(frame_packing_arrangement.type, 7);
442 e_u(frame_packing_arrangement.quincunx_sampling_flag, 1);
443 e_u(frame_packing_arrangement.content_interpretation_type, 6);
444 e_u(frame_packing_arrangement.spatial_flipping_flag, 1);
445 e_u(frame_packing_arrangement.frame0_flipped_flag, 1);
446 e_u(frame_packing_arrangement.field_views_flag, 1);
447 e_u(frame_packing_arrangement.current_frame_is_frame0_flag, 1);
448 e_u(frame_packing_arrangement.frame0_self_contained_flag, 1);
449 e_u(frame_packing_arrangement.frame1_self_contained_flag, 1);
450
451 if (!frame_packing_arrangement.quincunx_sampling_flag &&
452 frame_packing_arrangement.type != 5) {
453 e_u(frame_packing_arrangement.frame0_grid_position_x, 4);
454 e_u(frame_packing_arrangement.frame0_grid_position_y, 4);
455 e_u(frame_packing_arrangement.frame1_grid_position_x, 4);
456 e_u(frame_packing_arrangement.frame1_grid_position_y, 4);
457 }
458
459 e_u(frame_packing_arrangement.reserved_byte, 8);
460 e_ue(frame_packing_arrangement.repetition_period);
461 }
462
463 e_u(frame_packing_arrangement.extension_flag, 1);
464 return 1;
465 }
466
create_rbsp(OMX_U8 * buf,OMX_U32 nalu_type)467 OMX_S32 extra_data_handler::create_rbsp(OMX_U8 *buf, OMX_U32 nalu_type)
468 {
469 OMX_U32 i, j = 7;
470
471 for (i = 0; i < 3; i++)
472 *buf++ = 0x00;
473
474 *buf++ = H264_START_CODE;
475 *buf++ = nalu_type;
476 *buf++ = (sei_payload_type & 0x000000FF);
477 *buf++ = byte_ptr - 1; //payload will contain 1 byte of rbsp_trailing_bits
478 //that shouldn't be taken into account
479
480 for (i = 0; i < byte_ptr ; i += 2) {
481 *buf++ = rbsp_buf[i];
482 j++;
483
484 if (i+1 < byte_ptr) {
485 *buf++ = rbsp_buf[i+1];
486 j++;
487
488 if (!(rbsp_buf[i] + rbsp_buf[i+1])) {
489 *buf++ = H264_EMULATION_BYTE;
490 j++;
491 }
492 }
493 }
494
495 DEBUG_PRINT_LOW("\n%s rbsp length %d", __func__, j);
496 return j;
497 }
498
create_sei(OMX_U8 * buffer)499 OMX_U32 extra_data_handler::create_sei(OMX_U8 *buffer)
500 {
501 OMX_U32 i, ret_val = 0;
502
503 byte_ptr = 0;
504 bit_ptr = 8;
505
506 if (sei_payload_type == SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT) {
507 create_frame_pack();
508
509 if (bit_ptr != 8) {
510 e_u(1,1);
511
512 if (bit_ptr != 8)
513 e_u(0,bit_ptr);
514 }
515
516 //Payload will have been byte aligned by now,
517 //insert the rbsp trailing bits
518 e_u(1, 1);
519 e_u(0, 7);
520
521 ret_val = create_rbsp(buffer, NAL_TYPE_SEI);
522 }
523
524 pack_sei = false;
525 sei_payload_type = -1;
526
527 return ret_val;
528 }
529
create_extra_data(OMX_BUFFERHEADERTYPE * buf_hdr)530 OMX_U32 extra_data_handler::create_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr)
531 {
532 OMX_U8 *buffer = (OMX_U8 *) ((unsigned)(buf_hdr->pBuffer +
533 buf_hdr->nOffset + buf_hdr->nFilledLen));
534 OMX_U32 msg_size;
535
536 if (buf_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
537 DEBUG_PRINT_LOW("\n%s:%d create extra data with config", __func__,
538 __LINE__);
539
540 if (pack_sei) {
541 msg_size = create_sei(buffer);
542
543 if ( msg_size > 0)
544 buf_hdr->nFilledLen += msg_size;
545 }
546 }
547
548 return 1;
549 }
550
551