diff options
Diffstat (limited to 'xbmc/utils/BitstreamConverter.cpp')
| -rw-r--r-- | xbmc/utils/BitstreamConverter.cpp | 1219 |
1 files changed, 1219 insertions, 0 deletions
diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp new file mode 100644 index 0000000..011a1e4 --- /dev/null +++ b/xbmc/utils/BitstreamConverter.cpp | |||
| @@ -0,0 +1,1219 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010-2018 Team Kodi | ||
| 3 | * This file is part of Kodi - https://kodi.tv | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0-or-later | ||
| 6 | * See LICENSES/README.md for more information. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include "utils/log.h" | ||
| 10 | |||
| 11 | #include <assert.h> | ||
| 12 | |||
| 13 | #ifndef UINT16_MAX | ||
| 14 | #define UINT16_MAX (65535U) | ||
| 15 | #endif | ||
| 16 | |||
| 17 | #include "BitstreamConverter.h" | ||
| 18 | #include "BitstreamReader.h" | ||
| 19 | #include "BitstreamWriter.h" | ||
| 20 | |||
| 21 | #include <algorithm> | ||
| 22 | |||
| 23 | enum { | ||
| 24 | AVC_NAL_SLICE=1, | ||
| 25 | AVC_NAL_DPA, | ||
| 26 | AVC_NAL_DPB, | ||
| 27 | AVC_NAL_DPC, | ||
| 28 | AVC_NAL_IDR_SLICE, | ||
| 29 | AVC_NAL_SEI, | ||
| 30 | AVC_NAL_SPS, | ||
| 31 | AVC_NAL_PPS, | ||
| 32 | AVC_NAL_AUD, | ||
| 33 | AVC_NAL_END_SEQUENCE, | ||
| 34 | AVC_NAL_END_STREAM, | ||
| 35 | AVC_NAL_FILLER_DATA, | ||
| 36 | AVC_NAL_SPS_EXT, | ||
| 37 | AVC_NAL_AUXILIARY_SLICE=19 | ||
| 38 | }; | ||
| 39 | |||
| 40 | enum { | ||
| 41 | HEVC_NAL_TRAIL_N = 0, | ||
| 42 | HEVC_NAL_TRAIL_R = 1, | ||
| 43 | HEVC_NAL_TSA_N = 2, | ||
| 44 | HEVC_NAL_TSA_R = 3, | ||
| 45 | HEVC_NAL_STSA_N = 4, | ||
| 46 | HEVC_NAL_STSA_R = 5, | ||
| 47 | HEVC_NAL_RADL_N = 6, | ||
| 48 | HEVC_NAL_RADL_R = 7, | ||
| 49 | HEVC_NAL_RASL_N = 8, | ||
| 50 | HEVC_NAL_RASL_R = 9, | ||
| 51 | HEVC_NAL_BLA_W_LP = 16, | ||
| 52 | HEVC_NAL_BLA_W_RADL = 17, | ||
| 53 | HEVC_NAL_BLA_N_LP = 18, | ||
| 54 | HEVC_NAL_IDR_W_RADL = 19, | ||
| 55 | HEVC_NAL_IDR_N_LP = 20, | ||
| 56 | HEVC_NAL_CRA_NUT = 21, | ||
| 57 | HEVC_NAL_VPS = 32, | ||
| 58 | HEVC_NAL_SPS = 33, | ||
| 59 | HEVC_NAL_PPS = 34, | ||
| 60 | HEVC_NAL_AUD = 35, | ||
| 61 | HEVC_NAL_EOS_NUT = 36, | ||
| 62 | HEVC_NAL_EOB_NUT = 37, | ||
| 63 | HEVC_NAL_FD_NUT = 38, | ||
| 64 | HEVC_NAL_SEI_PREFIX = 39, | ||
| 65 | HEVC_NAL_SEI_SUFFIX = 40 | ||
| 66 | }; | ||
| 67 | |||
| 68 | enum { | ||
| 69 | SEI_BUFFERING_PERIOD = 0, | ||
| 70 | SEI_PIC_TIMING, | ||
| 71 | SEI_PAN_SCAN_RECT, | ||
| 72 | SEI_FILLER_PAYLOAD, | ||
| 73 | SEI_USER_DATA_REGISTERED_ITU_T_T35, | ||
| 74 | SEI_USER_DATA_UNREGISTERED, | ||
| 75 | SEI_RECOVERY_POINT, | ||
| 76 | SEI_DEC_REF_PIC_MARKING_REPETITION, | ||
| 77 | SEI_SPARE_PIC, | ||
| 78 | SEI_SCENE_INFO, | ||
| 79 | SEI_SUB_SEQ_INFO, | ||
| 80 | SEI_SUB_SEQ_LAYER_CHARACTERISTICS, | ||
| 81 | SEI_SUB_SEQ_CHARACTERISTICS, | ||
| 82 | SEI_FULL_FRAME_FREEZE, | ||
| 83 | SEI_FULL_FRAME_FREEZE_RELEASE, | ||
| 84 | SEI_FULL_FRAME_SNAPSHOT, | ||
| 85 | SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START, | ||
| 86 | SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END, | ||
| 87 | SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET, | ||
| 88 | SEI_FILM_GRAIN_CHARACTERISTICS, | ||
| 89 | SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE, | ||
| 90 | SEI_STEREO_VIDEO_INFO, | ||
| 91 | SEI_POST_FILTER_HINTS, | ||
| 92 | SEI_TONE_MAPPING | ||
| 93 | }; | ||
| 94 | |||
| 95 | /* | ||
| 96 | * GStreamer h264 parser | ||
| 97 | * Copyright (C) 2005 Michal Benes <michal.benes@itonis.tv> | ||
| 98 | * (C) 2008 Wim Taymans <wim.taymans@gmail.com> | ||
| 99 | * gsth264parse.c | ||
| 100 | * | ||
| 101 | * SPDX-License-Identifier: LGPL-2.1-or-later | ||
| 102 | * See LICENSES/README.md for more information. | ||
| 103 | */ | ||
| 104 | static void nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size) | ||
| 105 | { | ||
| 106 | bs->data = data; | ||
| 107 | bs->end = data + size; | ||
| 108 | bs->head = 0; | ||
| 109 | // fill with something other than 0 to detect | ||
| 110 | // emulation prevention bytes | ||
| 111 | bs->cache = 0xffffffff; | ||
| 112 | } | ||
| 113 | |||
| 114 | static uint32_t nal_bs_read(nal_bitstream *bs, int n) | ||
| 115 | { | ||
| 116 | uint32_t res = 0; | ||
| 117 | int shift; | ||
| 118 | |||
| 119 | if (n == 0) | ||
| 120 | return res; | ||
| 121 | |||
| 122 | // fill up the cache if we need to | ||
| 123 | while (bs->head < n) | ||
| 124 | { | ||
| 125 | uint8_t a_byte; | ||
| 126 | bool check_three_byte; | ||
| 127 | |||
| 128 | check_three_byte = true; | ||
| 129 | next_byte: | ||
| 130 | if (bs->data >= bs->end) | ||
| 131 | { | ||
| 132 | // we're at the end, can't produce more than head number of bits | ||
| 133 | n = bs->head; | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | // get the byte, this can be an emulation_prevention_three_byte that we need | ||
| 137 | // to ignore. | ||
| 138 | a_byte = *bs->data++; | ||
| 139 | if (check_three_byte && a_byte == 0x03 && ((bs->cache & 0xffff) == 0)) | ||
| 140 | { | ||
| 141 | // next byte goes unconditionally to the cache, even if it's 0x03 | ||
| 142 | check_three_byte = false; | ||
| 143 | goto next_byte; | ||
| 144 | } | ||
| 145 | // shift bytes in cache, moving the head bits of the cache left | ||
| 146 | bs->cache = (bs->cache << 8) | a_byte; | ||
| 147 | bs->head += 8; | ||
| 148 | } | ||
| 149 | |||
| 150 | // bring the required bits down and truncate | ||
| 151 | if ((shift = bs->head - n) > 0) | ||
| 152 | res = static_cast<uint32_t>(bs->cache >> shift); | ||
| 153 | else | ||
| 154 | res = static_cast<uint32_t>(bs->cache); | ||
| 155 | |||
| 156 | // mask out required bits | ||
| 157 | if (n < 32) | ||
| 158 | res &= (1 << n) - 1; | ||
| 159 | bs->head = shift; | ||
| 160 | |||
| 161 | return res; | ||
| 162 | } | ||
| 163 | |||
| 164 | static bool nal_bs_eos(nal_bitstream *bs) | ||
| 165 | { | ||
| 166 | return (bs->data >= bs->end) && (bs->head == 0); | ||
| 167 | } | ||
| 168 | |||
| 169 | // read unsigned Exp-Golomb code | ||
| 170 | static int nal_bs_read_ue(nal_bitstream *bs) | ||
| 171 | { | ||
| 172 | int i = 0; | ||
| 173 | |||
| 174 | while (nal_bs_read(bs, 1) == 0 && !nal_bs_eos(bs) && i < 31) | ||
| 175 | i++; | ||
| 176 | |||
| 177 | return ((1 << i) - 1 + nal_bs_read(bs, i)); | ||
| 178 | } | ||
| 179 | |||
| 180 | static const uint8_t* avc_find_startcode_internal(const uint8_t *p, const uint8_t *end) | ||
| 181 | { | ||
| 182 | const uint8_t *a = p + 4 - ((intptr_t)p & 3); | ||
| 183 | |||
| 184 | for (end -= 3; p < a && p < end; p++) | ||
| 185 | { | ||
| 186 | if (p[0] == 0 && p[1] == 0 && p[2] == 1) | ||
| 187 | return p; | ||
| 188 | } | ||
| 189 | |||
| 190 | for (end -= 3; p < end; p += 4) | ||
| 191 | { | ||
| 192 | uint32_t x = *(const uint32_t*)p; | ||
| 193 | if ((x - 0x01010101) & (~x) & 0x80808080) // generic | ||
| 194 | { | ||
| 195 | if (p[1] == 0) | ||
| 196 | { | ||
| 197 | if (p[0] == 0 && p[2] == 1) | ||
| 198 | return p; | ||
| 199 | if (p[2] == 0 && p[3] == 1) | ||
| 200 | return p+1; | ||
| 201 | } | ||
| 202 | if (p[3] == 0) | ||
| 203 | { | ||
| 204 | if (p[2] == 0 && p[4] == 1) | ||
| 205 | return p+2; | ||
| 206 | if (p[4] == 0 && p[5] == 1) | ||
| 207 | return p+3; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | for (end += 3; p < end; p++) | ||
| 213 | { | ||
| 214 | if (p[0] == 0 && p[1] == 0 && p[2] == 1) | ||
| 215 | return p; | ||
| 216 | } | ||
| 217 | |||
| 218 | return end + 3; | ||
| 219 | } | ||
| 220 | |||
| 221 | static const uint8_t* avc_find_startcode(const uint8_t *p, const uint8_t *end) | ||
| 222 | { | ||
| 223 | const uint8_t *out = avc_find_startcode_internal(p, end); | ||
| 224 | if (p<out && out<end && !out[-1]) | ||
| 225 | out--; | ||
| 226 | return out; | ||
| 227 | } | ||
| 228 | |||
| 229 | static bool has_sei_recovery_point(const uint8_t *p, const uint8_t *end) | ||
| 230 | { | ||
| 231 | int pt(0), ps(0), offset(1); | ||
| 232 | |||
| 233 | do | ||
| 234 | { | ||
| 235 | pt = 0; | ||
| 236 | do { | ||
| 237 | pt += p[offset]; | ||
| 238 | } while (p[offset++] == 0xFF); | ||
| 239 | |||
| 240 | ps = 0; | ||
| 241 | do { | ||
| 242 | ps += p[offset]; | ||
| 243 | } while (p[offset++] == 0xFF); | ||
| 244 | |||
| 245 | if (pt == SEI_RECOVERY_POINT) | ||
| 246 | { | ||
| 247 | nal_bitstream bs; | ||
| 248 | nal_bs_init(&bs, p + offset, ps); | ||
| 249 | return nal_bs_read_ue(&bs) >= 0; | ||
| 250 | } | ||
| 251 | offset += ps; | ||
| 252 | } while (p + offset < end && p[offset] != 0x80); | ||
| 253 | |||
| 254 | return false; | ||
| 255 | } | ||
| 256 | |||
| 257 | //////////////////////////////////////////////////////////////////////////////////////////// | ||
| 258 | ///////////////////////////////////////////////////////////////////////////////////////////// | ||
| 259 | CBitstreamParser::CBitstreamParser() = default; | ||
| 260 | |||
| 261 | CBitstreamParser::~CBitstreamParser() = default; | ||
| 262 | |||
| 263 | void CBitstreamParser::Close() | ||
| 264 | { | ||
| 265 | } | ||
| 266 | |||
| 267 | bool CBitstreamParser::CanStartDecode(const uint8_t *buf, int buf_size) | ||
| 268 | { | ||
| 269 | if (!buf) | ||
| 270 | return false; | ||
| 271 | |||
| 272 | bool rtn = false; | ||
| 273 | uint32_t state = -1; | ||
| 274 | const uint8_t *buf_begin, *buf_end = buf + buf_size; | ||
| 275 | |||
| 276 | for (; rtn == false;) | ||
| 277 | { | ||
| 278 | buf = find_start_code(buf, buf_end, &state); | ||
| 279 | if (buf >= buf_end) | ||
| 280 | { | ||
| 281 | break; | ||
| 282 | } | ||
| 283 | |||
| 284 | switch (state & 0x1f) | ||
| 285 | { | ||
| 286 | case AVC_NAL_SLICE: | ||
| 287 | break; | ||
| 288 | case AVC_NAL_IDR_SLICE: | ||
| 289 | rtn = true; | ||
| 290 | break; | ||
| 291 | case AVC_NAL_SEI: | ||
| 292 | buf_begin = buf - 1; | ||
| 293 | buf = find_start_code(buf, buf_end, &state) - 4; | ||
| 294 | if (has_sei_recovery_point(buf_begin, buf)) | ||
| 295 | rtn = true; | ||
| 296 | break; | ||
| 297 | case AVC_NAL_SPS: | ||
| 298 | rtn = true; | ||
| 299 | break; | ||
| 300 | case AVC_NAL_PPS: | ||
| 301 | break; | ||
| 302 | default: | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | return rtn; | ||
| 308 | } | ||
| 309 | |||
| 310 | //////////////////////////////////////////////////////////////////////////////////////////// | ||
| 311 | ///////////////////////////////////////////////////////////////////////////////////////////// | ||
| 312 | CBitstreamConverter::CBitstreamConverter() | ||
| 313 | { | ||
| 314 | m_convert_bitstream = false; | ||
| 315 | m_convertBuffer = NULL; | ||
| 316 | m_convertSize = 0; | ||
| 317 | m_inputBuffer = NULL; | ||
| 318 | m_inputSize = 0; | ||
| 319 | m_to_annexb = false; | ||
| 320 | m_extradata = NULL; | ||
| 321 | m_extrasize = 0; | ||
| 322 | m_convert_3byteTo4byteNALSize = false; | ||
| 323 | m_convert_bytestream = false; | ||
| 324 | m_sps_pps_context.sps_pps_data = NULL; | ||
| 325 | m_start_decode = true; | ||
| 326 | } | ||
| 327 | |||
| 328 | CBitstreamConverter::~CBitstreamConverter() | ||
| 329 | { | ||
| 330 | Close(); | ||
| 331 | } | ||
| 332 | |||
| 333 | bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int in_extrasize, bool to_annexb) | ||
| 334 | { | ||
| 335 | m_to_annexb = to_annexb; | ||
| 336 | |||
| 337 | m_codec = codec; | ||
| 338 | switch(m_codec) | ||
| 339 | { | ||
| 340 | case AV_CODEC_ID_H264: | ||
| 341 | if (in_extrasize < 7 || in_extradata == NULL) | ||
| 342 | { | ||
| 343 | CLog::Log(LOGERROR, "CBitstreamConverter::Open avcC data too small or missing"); | ||
| 344 | return false; | ||
| 345 | } | ||
| 346 | // valid avcC data (bitstream) always starts with the value 1 (version) | ||
| 347 | if(m_to_annexb) | ||
| 348 | { | ||
| 349 | if ( in_extradata[0] == 1 ) | ||
| 350 | { | ||
| 351 | CLog::Log(LOGINFO, "CBitstreamConverter::Open bitstream to annexb init"); | ||
| 352 | m_extrasize = in_extrasize; | ||
| 353 | m_extradata = (uint8_t*)av_malloc(in_extrasize); | ||
| 354 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 355 | m_convert_bitstream = BitstreamConvertInitAVC(m_extradata, m_extrasize); | ||
| 356 | return true; | ||
| 357 | } | ||
| 358 | else | ||
| 359 | CLog::Log(LOGINFO, "CBitstreamConverter::Open Invalid avcC"); | ||
| 360 | } | ||
| 361 | else | ||
| 362 | { | ||
| 363 | // valid avcC atom data always starts with the value 1 (version) | ||
| 364 | if ( in_extradata[0] != 1 ) | ||
| 365 | { | ||
| 366 | if ( (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 0 && in_extradata[3] == 1) || | ||
| 367 | (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 1) ) | ||
| 368 | { | ||
| 369 | CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init"); | ||
| 370 | // video content is from x264 or from bytestream h264 (AnnexB format) | ||
| 371 | // NAL reformating to bitstream format needed | ||
| 372 | AVIOContext *pb; | ||
| 373 | if (avio_open_dyn_buf(&pb) < 0) | ||
| 374 | return false; | ||
| 375 | m_convert_bytestream = true; | ||
| 376 | // create a valid avcC atom data from ffmpeg's extradata | ||
| 377 | isom_write_avcc(pb, in_extradata, in_extrasize); | ||
| 378 | // unhook from ffmpeg's extradata | ||
| 379 | in_extradata = NULL; | ||
| 380 | // extract the avcC atom data into extradata then write it into avcCData for VDADecoder | ||
| 381 | in_extrasize = avio_close_dyn_buf(pb, &in_extradata); | ||
| 382 | // make a copy of extradata contents | ||
| 383 | m_extradata = (uint8_t *)av_malloc(in_extrasize); | ||
| 384 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 385 | m_extrasize = in_extrasize; | ||
| 386 | // done with the converted extradata, we MUST free using av_free | ||
| 387 | av_free(in_extradata); | ||
| 388 | return true; | ||
| 389 | } | ||
| 390 | else | ||
| 391 | { | ||
| 392 | CLog::Log(LOGINFO, "CBitstreamConverter::Open invalid avcC atom data"); | ||
| 393 | return false; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | else | ||
| 397 | { | ||
| 398 | if (in_extradata[4] == 0xFE) | ||
| 399 | { | ||
| 400 | CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init 3 byte to 4 byte nal"); | ||
| 401 | // video content is from so silly encoder that think 3 byte NAL sizes | ||
| 402 | // are valid, setup to convert 3 byte NAL sizes to 4 byte. | ||
| 403 | in_extradata[4] = 0xFF; | ||
| 404 | m_convert_3byteTo4byteNALSize = true; | ||
| 405 | |||
| 406 | m_extradata = (uint8_t *)av_malloc(in_extrasize); | ||
| 407 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 408 | m_extrasize = in_extrasize; | ||
| 409 | return true; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | // valid avcC atom | ||
| 413 | m_extradata = (uint8_t*)av_malloc(in_extrasize); | ||
| 414 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 415 | m_extrasize = in_extrasize; | ||
| 416 | return true; | ||
| 417 | } | ||
| 418 | return false; | ||
| 419 | break; | ||
| 420 | case AV_CODEC_ID_HEVC: | ||
| 421 | if (in_extrasize < 23 || in_extradata == NULL) | ||
| 422 | { | ||
| 423 | CLog::Log(LOGERROR, "CBitstreamConverter::Open hvcC data too small or missing"); | ||
| 424 | return false; | ||
| 425 | } | ||
| 426 | // valid hvcC data (bitstream) always starts with the value 1 (version) | ||
| 427 | if(m_to_annexb) | ||
| 428 | { | ||
| 429 | /** | ||
| 430 | * It seems the extradata is encoded as hvcC format. | ||
| 431 | * Temporarily, we support configurationVersion==0 until 14496-15 3rd | ||
| 432 | * is finalized. When finalized, configurationVersion will be 1 and we | ||
| 433 | * can recognize hvcC by checking if extradata[0]==1 or not. | ||
| 434 | */ | ||
| 435 | |||
| 436 | if (in_extradata[0] || in_extradata[1] || in_extradata[2] > 1) | ||
| 437 | { | ||
| 438 | CLog::Log(LOGINFO, "CBitstreamConverter::Open bitstream to annexb init"); | ||
| 439 | m_extrasize = in_extrasize; | ||
| 440 | m_extradata = (uint8_t*)av_malloc(in_extrasize); | ||
| 441 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 442 | m_convert_bitstream = BitstreamConvertInitHEVC(m_extradata, m_extrasize); | ||
| 443 | return true; | ||
| 444 | } | ||
| 445 | else | ||
| 446 | CLog::Log(LOGINFO, "CBitstreamConverter::Open Invalid hvcC"); | ||
| 447 | } | ||
| 448 | else | ||
| 449 | { | ||
| 450 | // valid hvcC atom data always starts with the value 1 (version) | ||
| 451 | if ( in_extradata[0] != 1 ) | ||
| 452 | { | ||
| 453 | if ( (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 0 && in_extradata[3] == 1) || | ||
| 454 | (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 1) ) | ||
| 455 | { | ||
| 456 | CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init"); | ||
| 457 | //! @todo convert annexb to bitstream format | ||
| 458 | return false; | ||
| 459 | } | ||
| 460 | else | ||
| 461 | { | ||
| 462 | CLog::Log(LOGINFO, "CBitstreamConverter::Open invalid hvcC atom data"); | ||
| 463 | return false; | ||
| 464 | } | ||
| 465 | } | ||
| 466 | else | ||
| 467 | { | ||
| 468 | if ((in_extradata[4] & 0x3) == 2) | ||
| 469 | { | ||
| 470 | CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init 3 byte to 4 byte nal"); | ||
| 471 | // video content is from so silly encoder that think 3 byte NAL sizes | ||
| 472 | // are valid, setup to convert 3 byte NAL sizes to 4 byte. | ||
| 473 | in_extradata[4] |= 0x03; | ||
| 474 | m_convert_3byteTo4byteNALSize = true; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | // valid hvcC atom | ||
| 478 | m_extradata = (uint8_t*)av_malloc(in_extrasize); | ||
| 479 | memcpy(m_extradata, in_extradata, in_extrasize); | ||
| 480 | m_extrasize = in_extrasize; | ||
| 481 | return true; | ||
| 482 | } | ||
| 483 | return false; | ||
| 484 | break; | ||
| 485 | default: | ||
| 486 | return false; | ||
| 487 | break; | ||
| 488 | } | ||
| 489 | return false; | ||
| 490 | } | ||
| 491 | |||
| 492 | void CBitstreamConverter::Close(void) | ||
| 493 | { | ||
| 494 | if (m_sps_pps_context.sps_pps_data) | ||
| 495 | av_free(m_sps_pps_context.sps_pps_data), m_sps_pps_context.sps_pps_data = NULL; | ||
| 496 | |||
| 497 | if (m_convertBuffer) | ||
| 498 | av_free(m_convertBuffer), m_convertBuffer = NULL; | ||
| 499 | m_convertSize = 0; | ||
| 500 | |||
| 501 | if (m_extradata) | ||
| 502 | av_free(m_extradata), m_extradata = NULL; | ||
| 503 | m_extrasize = 0; | ||
| 504 | |||
| 505 | m_inputSize = 0; | ||
| 506 | m_inputBuffer = NULL; | ||
| 507 | |||
| 508 | m_convert_bitstream = false; | ||
| 509 | m_convert_bytestream = false; | ||
| 510 | m_convert_3byteTo4byteNALSize = false; | ||
| 511 | } | ||
| 512 | |||
| 513 | bool CBitstreamConverter::Convert(uint8_t *pData, int iSize) | ||
| 514 | { | ||
| 515 | if (m_convertBuffer) | ||
| 516 | { | ||
| 517 | av_free(m_convertBuffer); | ||
| 518 | m_convertBuffer = NULL; | ||
| 519 | } | ||
| 520 | m_inputSize = 0; | ||
| 521 | m_convertSize = 0; | ||
| 522 | m_inputBuffer = NULL; | ||
| 523 | |||
| 524 | if (pData) | ||
| 525 | { | ||
| 526 | if (m_codec == AV_CODEC_ID_H264 || | ||
| 527 | m_codec == AV_CODEC_ID_HEVC) | ||
| 528 | { | ||
| 529 | if (m_to_annexb) | ||
| 530 | { | ||
| 531 | int demuxer_bytes = iSize; | ||
| 532 | uint8_t *demuxer_content = pData; | ||
| 533 | |||
| 534 | if (m_convert_bitstream) | ||
| 535 | { | ||
| 536 | // convert demuxer packet from bitstream to bytestream (AnnexB) | ||
| 537 | int bytestream_size = 0; | ||
| 538 | uint8_t *bytestream_buff = NULL; | ||
| 539 | |||
| 540 | BitstreamConvert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size); | ||
| 541 | if (bytestream_buff && (bytestream_size > 0)) | ||
| 542 | { | ||
| 543 | m_convertSize = bytestream_size; | ||
| 544 | m_convertBuffer = bytestream_buff; | ||
| 545 | return true; | ||
| 546 | } | ||
| 547 | else | ||
| 548 | { | ||
| 549 | m_convertSize = 0; | ||
| 550 | m_convertBuffer = NULL; | ||
| 551 | CLog::Log(LOGERROR, "CBitstreamConverter::Convert: error converting."); | ||
| 552 | return false; | ||
| 553 | } | ||
| 554 | } | ||
| 555 | else | ||
| 556 | { | ||
| 557 | m_inputSize = iSize; | ||
| 558 | m_inputBuffer = pData; | ||
| 559 | return true; | ||
| 560 | } | ||
| 561 | } | ||
| 562 | else | ||
| 563 | { | ||
| 564 | m_inputSize = iSize; | ||
| 565 | m_inputBuffer = pData; | ||
| 566 | |||
| 567 | if (m_convert_bytestream) | ||
| 568 | { | ||
| 569 | if(m_convertBuffer) | ||
| 570 | { | ||
| 571 | av_free(m_convertBuffer); | ||
| 572 | m_convertBuffer = NULL; | ||
| 573 | } | ||
| 574 | m_convertSize = 0; | ||
| 575 | |||
| 576 | // convert demuxer packet from bytestream (AnnexB) to bitstream | ||
| 577 | AVIOContext *pb; | ||
| 578 | |||
| 579 | if(avio_open_dyn_buf(&pb) < 0) | ||
| 580 | { | ||
| 581 | return false; | ||
| 582 | } | ||
| 583 | m_convertSize = avc_parse_nal_units(pb, pData, iSize); | ||
| 584 | m_convertSize = avio_close_dyn_buf(pb, &m_convertBuffer); | ||
| 585 | } | ||
| 586 | else if (m_convert_3byteTo4byteNALSize) | ||
| 587 | { | ||
| 588 | if(m_convertBuffer) | ||
| 589 | { | ||
| 590 | av_free(m_convertBuffer); | ||
| 591 | m_convertBuffer = NULL; | ||
| 592 | } | ||
| 593 | m_convertSize = 0; | ||
| 594 | |||
| 595 | // convert demuxer packet from 3 byte NAL sizes to 4 byte | ||
| 596 | AVIOContext *pb; | ||
| 597 | if (avio_open_dyn_buf(&pb) < 0) | ||
| 598 | return false; | ||
| 599 | |||
| 600 | uint32_t nal_size; | ||
| 601 | uint8_t *end = pData + iSize; | ||
| 602 | uint8_t *nal_start = pData; | ||
| 603 | while (nal_start < end) | ||
| 604 | { | ||
| 605 | nal_size = BS_RB24(nal_start); | ||
| 606 | avio_wb32(pb, nal_size); | ||
| 607 | nal_start += 3; | ||
| 608 | avio_write(pb, nal_start, nal_size); | ||
| 609 | nal_start += nal_size; | ||
| 610 | } | ||
| 611 | |||
| 612 | m_convertSize = avio_close_dyn_buf(pb, &m_convertBuffer); | ||
| 613 | } | ||
| 614 | return true; | ||
| 615 | } | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | return false; | ||
| 620 | } | ||
| 621 | |||
| 622 | |||
| 623 | uint8_t *CBitstreamConverter::GetConvertBuffer() const | ||
| 624 | { | ||
| 625 | if((m_convert_bitstream || m_convert_bytestream || m_convert_3byteTo4byteNALSize) && m_convertBuffer != NULL) | ||
| 626 | return m_convertBuffer; | ||
| 627 | else | ||
| 628 | return m_inputBuffer; | ||
| 629 | } | ||
| 630 | |||
| 631 | int CBitstreamConverter::GetConvertSize() const | ||
| 632 | { | ||
| 633 | if((m_convert_bitstream || m_convert_bytestream || m_convert_3byteTo4byteNALSize) && m_convertBuffer != NULL) | ||
| 634 | return m_convertSize; | ||
| 635 | else | ||
| 636 | return m_inputSize; | ||
| 637 | } | ||
| 638 | |||
| 639 | uint8_t *CBitstreamConverter::GetExtraData() const | ||
| 640 | { | ||
| 641 | if(m_convert_bitstream) | ||
| 642 | return m_sps_pps_context.sps_pps_data; | ||
| 643 | else | ||
| 644 | return m_extradata; | ||
| 645 | } | ||
| 646 | int CBitstreamConverter::GetExtraSize() const | ||
| 647 | { | ||
| 648 | if(m_convert_bitstream) | ||
| 649 | return m_sps_pps_context.size; | ||
| 650 | else | ||
| 651 | return m_extrasize; | ||
| 652 | } | ||
| 653 | |||
| 654 | void CBitstreamConverter::ResetStartDecode(void) | ||
| 655 | { | ||
| 656 | m_start_decode = false; | ||
| 657 | } | ||
| 658 | |||
| 659 | bool CBitstreamConverter::CanStartDecode() const | ||
| 660 | { | ||
| 661 | return m_start_decode; | ||
| 662 | } | ||
| 663 | |||
| 664 | bool CBitstreamConverter::BitstreamConvertInitAVC(void *in_extradata, int in_extrasize) | ||
| 665 | { | ||
| 666 | // based on h264_mp4toannexb_bsf.c (ffmpeg) | ||
| 667 | // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> | ||
| 668 | // and Licensed GPL 2.1 or greater | ||
| 669 | |||
| 670 | m_sps_pps_size = 0; | ||
| 671 | m_sps_pps_context.sps_pps_data = NULL; | ||
| 672 | |||
| 673 | // nothing to filter | ||
| 674 | if (!in_extradata || in_extrasize < 6) | ||
| 675 | return false; | ||
| 676 | |||
| 677 | uint16_t unit_size; | ||
| 678 | uint32_t total_size = 0; | ||
| 679 | uint8_t *out = NULL, unit_nb, sps_done = 0, sps_seen = 0, pps_seen = 0; | ||
| 680 | const uint8_t *extradata = (uint8_t*)in_extradata + 4; | ||
| 681 | static const uint8_t nalu_header[4] = {0, 0, 0, 1}; | ||
| 682 | |||
| 683 | // retrieve length coded size | ||
| 684 | m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; | ||
| 685 | |||
| 686 | // retrieve sps and pps unit(s) | ||
| 687 | unit_nb = *extradata++ & 0x1f; // number of sps unit(s) | ||
| 688 | if (!unit_nb) | ||
| 689 | { | ||
| 690 | goto pps; | ||
| 691 | } | ||
| 692 | else | ||
| 693 | { | ||
| 694 | sps_seen = 1; | ||
| 695 | } | ||
| 696 | |||
| 697 | while (unit_nb--) | ||
| 698 | { | ||
| 699 | void *tmp; | ||
| 700 | |||
| 701 | unit_size = extradata[0] << 8 | extradata[1]; | ||
| 702 | total_size += unit_size + 4; | ||
| 703 | |||
| 704 | if (total_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || | ||
| 705 | (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize)) | ||
| 706 | { | ||
| 707 | av_free(out); | ||
| 708 | return false; | ||
| 709 | } | ||
| 710 | tmp = av_realloc(out, total_size + AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 711 | if (!tmp) | ||
| 712 | { | ||
| 713 | av_free(out); | ||
| 714 | return false; | ||
| 715 | } | ||
| 716 | out = (uint8_t*)tmp; | ||
| 717 | memcpy(out + total_size - unit_size - 4, nalu_header, 4); | ||
| 718 | memcpy(out + total_size - unit_size, extradata + 2, unit_size); | ||
| 719 | extradata += 2 + unit_size; | ||
| 720 | |||
| 721 | pps: | ||
| 722 | if (!unit_nb && !sps_done++) | ||
| 723 | { | ||
| 724 | unit_nb = *extradata++; // number of pps unit(s) | ||
| 725 | if (unit_nb) | ||
| 726 | pps_seen = 1; | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | if (out) | ||
| 731 | memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 732 | |||
| 733 | if (!sps_seen) | ||
| 734 | CLog::Log(LOGDEBUG, "SPS NALU missing or invalid. The resulting stream may not play"); | ||
| 735 | if (!pps_seen) | ||
| 736 | CLog::Log(LOGDEBUG, "PPS NALU missing or invalid. The resulting stream may not play"); | ||
| 737 | |||
| 738 | m_sps_pps_context.sps_pps_data = out; | ||
| 739 | m_sps_pps_context.size = total_size; | ||
| 740 | m_sps_pps_context.first_idr = 1; | ||
| 741 | m_sps_pps_context.idr_sps_pps_seen = 0; | ||
| 742 | |||
| 743 | return true; | ||
| 744 | } | ||
| 745 | |||
| 746 | bool CBitstreamConverter::BitstreamConvertInitHEVC(void *in_extradata, int in_extrasize) | ||
| 747 | { | ||
| 748 | m_sps_pps_size = 0; | ||
| 749 | m_sps_pps_context.sps_pps_data = NULL; | ||
| 750 | |||
| 751 | // nothing to filter | ||
| 752 | if (!in_extradata || in_extrasize < 23) | ||
| 753 | return false; | ||
| 754 | |||
| 755 | uint16_t unit_nb, unit_size; | ||
| 756 | uint32_t total_size = 0; | ||
| 757 | uint8_t *out = NULL, array_nb, nal_type, sps_seen = 0, pps_seen = 0; | ||
| 758 | const uint8_t *extradata = (uint8_t*)in_extradata + 21; | ||
| 759 | static const uint8_t nalu_header[4] = {0, 0, 0, 1}; | ||
| 760 | |||
| 761 | // retrieve length coded size | ||
| 762 | m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; | ||
| 763 | |||
| 764 | array_nb = *extradata++; | ||
| 765 | while (array_nb--) | ||
| 766 | { | ||
| 767 | nal_type = *extradata++ & 0x3f; | ||
| 768 | unit_nb = extradata[0] << 8 | extradata[1]; | ||
| 769 | extradata += 2; | ||
| 770 | |||
| 771 | if (nal_type == HEVC_NAL_SPS && unit_nb) | ||
| 772 | { | ||
| 773 | sps_seen = 1; | ||
| 774 | } | ||
| 775 | else if (nal_type == HEVC_NAL_PPS && unit_nb) | ||
| 776 | { | ||
| 777 | pps_seen = 1; | ||
| 778 | } | ||
| 779 | while (unit_nb--) | ||
| 780 | { | ||
| 781 | void *tmp; | ||
| 782 | |||
| 783 | unit_size = extradata[0] << 8 | extradata[1]; | ||
| 784 | extradata += 2; | ||
| 785 | if (nal_type != HEVC_NAL_SPS && | ||
| 786 | nal_type != HEVC_NAL_PPS && | ||
| 787 | nal_type != HEVC_NAL_VPS) | ||
| 788 | { | ||
| 789 | extradata += unit_size; | ||
| 790 | continue; | ||
| 791 | } | ||
| 792 | total_size += unit_size + 4; | ||
| 793 | |||
| 794 | if (total_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || | ||
| 795 | (extradata + unit_size) > ((uint8_t*)in_extradata + in_extrasize)) | ||
| 796 | { | ||
| 797 | av_free(out); | ||
| 798 | return false; | ||
| 799 | } | ||
| 800 | tmp = av_realloc(out, total_size + AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 801 | if (!tmp) | ||
| 802 | { | ||
| 803 | av_free(out); | ||
| 804 | return false; | ||
| 805 | } | ||
| 806 | out = (uint8_t*)tmp; | ||
| 807 | memcpy(out + total_size - unit_size - 4, nalu_header, 4); | ||
| 808 | memcpy(out + total_size - unit_size, extradata, unit_size); | ||
| 809 | extradata += unit_size; | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | if (out) | ||
| 814 | memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 815 | |||
| 816 | if (!sps_seen) | ||
| 817 | CLog::Log(LOGDEBUG, "SPS NALU missing or invalid. The resulting stream may not play"); | ||
| 818 | if (!pps_seen) | ||
| 819 | CLog::Log(LOGDEBUG, "PPS NALU missing or invalid. The resulting stream may not play"); | ||
| 820 | |||
| 821 | m_sps_pps_context.sps_pps_data = out; | ||
| 822 | m_sps_pps_context.size = total_size; | ||
| 823 | m_sps_pps_context.first_idr = 1; | ||
| 824 | m_sps_pps_context.idr_sps_pps_seen = 0; | ||
| 825 | |||
| 826 | return true; | ||
| 827 | } | ||
| 828 | |||
| 829 | bool CBitstreamConverter::IsIDR(uint8_t unit_type) | ||
| 830 | { | ||
| 831 | switch (m_codec) | ||
| 832 | { | ||
| 833 | case AV_CODEC_ID_H264: | ||
| 834 | return unit_type == AVC_NAL_IDR_SLICE; | ||
| 835 | case AV_CODEC_ID_HEVC: | ||
| 836 | return unit_type == HEVC_NAL_IDR_W_RADL || | ||
| 837 | unit_type == HEVC_NAL_IDR_N_LP || | ||
| 838 | unit_type == HEVC_NAL_CRA_NUT; | ||
| 839 | default: | ||
| 840 | return false; | ||
| 841 | } | ||
| 842 | } | ||
| 843 | |||
| 844 | bool CBitstreamConverter::IsSlice(uint8_t unit_type) | ||
| 845 | { | ||
| 846 | switch (m_codec) | ||
| 847 | { | ||
| 848 | case AV_CODEC_ID_H264: | ||
| 849 | return unit_type == AVC_NAL_SLICE; | ||
| 850 | case AV_CODEC_ID_HEVC: | ||
| 851 | return unit_type == HEVC_NAL_TRAIL_R || | ||
| 852 | unit_type == HEVC_NAL_TRAIL_N || | ||
| 853 | unit_type == HEVC_NAL_TSA_N || | ||
| 854 | unit_type == HEVC_NAL_TSA_R || | ||
| 855 | unit_type == HEVC_NAL_STSA_N || | ||
| 856 | unit_type == HEVC_NAL_STSA_R || | ||
| 857 | unit_type == HEVC_NAL_BLA_W_LP || | ||
| 858 | unit_type == HEVC_NAL_BLA_W_RADL || | ||
| 859 | unit_type == HEVC_NAL_BLA_N_LP || | ||
| 860 | unit_type == HEVC_NAL_CRA_NUT || | ||
| 861 | unit_type == HEVC_NAL_RADL_N || | ||
| 862 | unit_type == HEVC_NAL_RADL_R || | ||
| 863 | unit_type == HEVC_NAL_RASL_N || | ||
| 864 | unit_type == HEVC_NAL_RASL_R; | ||
| 865 | default: | ||
| 866 | return false; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) | ||
| 871 | { | ||
| 872 | // based on h264_mp4toannexb_bsf.c (ffmpeg) | ||
| 873 | // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> | ||
| 874 | // and Licensed GPL 2.1 or greater | ||
| 875 | |||
| 876 | int i; | ||
| 877 | uint8_t *buf = pData; | ||
| 878 | uint32_t buf_size = iSize; | ||
| 879 | uint8_t unit_type, nal_sps, nal_pps, nal_sei; | ||
| 880 | int32_t nal_size; | ||
| 881 | uint32_t cumul_size = 0; | ||
| 882 | const uint8_t *buf_end = buf + buf_size; | ||
| 883 | |||
| 884 | switch (m_codec) | ||
| 885 | { | ||
| 886 | case AV_CODEC_ID_H264: | ||
| 887 | nal_sps = AVC_NAL_SPS; | ||
| 888 | nal_pps = AVC_NAL_PPS; | ||
| 889 | nal_sei = AVC_NAL_SEI; | ||
| 890 | break; | ||
| 891 | case AV_CODEC_ID_HEVC: | ||
| 892 | nal_sps = HEVC_NAL_SPS; | ||
| 893 | nal_pps = HEVC_NAL_PPS; | ||
| 894 | nal_sei = HEVC_NAL_SEI_PREFIX; | ||
| 895 | break; | ||
| 896 | default: | ||
| 897 | return false; | ||
| 898 | } | ||
| 899 | |||
| 900 | do | ||
| 901 | { | ||
| 902 | if (buf + m_sps_pps_context.length_size > buf_end) | ||
| 903 | goto fail; | ||
| 904 | |||
| 905 | for (nal_size = 0, i = 0; i < m_sps_pps_context.length_size; i++) | ||
| 906 | nal_size = (nal_size << 8) | buf[i]; | ||
| 907 | |||
| 908 | buf += m_sps_pps_context.length_size; | ||
| 909 | if (m_codec == AV_CODEC_ID_H264) | ||
| 910 | { | ||
| 911 | unit_type = *buf & 0x1f; | ||
| 912 | } | ||
| 913 | else | ||
| 914 | { | ||
| 915 | unit_type = (*buf >> 1) & 0x3f; | ||
| 916 | } | ||
| 917 | |||
| 918 | if (buf + nal_size > buf_end || nal_size <= 0) | ||
| 919 | goto fail; | ||
| 920 | |||
| 921 | // Don't add sps/pps if the unit already contain them | ||
| 922 | if (m_sps_pps_context.first_idr && (unit_type == nal_sps || unit_type == nal_pps)) | ||
| 923 | m_sps_pps_context.idr_sps_pps_seen = 1; | ||
| 924 | |||
| 925 | if (!m_start_decode && (unit_type == nal_sps || IsIDR(unit_type) || (unit_type == nal_sei && has_sei_recovery_point(buf, buf + nal_size)))) | ||
| 926 | m_start_decode = true; | ||
| 927 | |||
| 928 | // prepend only to the first access unit of an IDR picture, if no sps/pps already present | ||
| 929 | if (m_sps_pps_context.first_idr && IsIDR(unit_type) && !m_sps_pps_context.idr_sps_pps_seen) | ||
| 930 | { | ||
| 931 | BitstreamAllocAndCopy(poutbuf, poutbuf_size, | ||
| 932 | m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); | ||
| 933 | m_sps_pps_context.first_idr = 0; | ||
| 934 | } | ||
| 935 | else | ||
| 936 | { | ||
| 937 | BitstreamAllocAndCopy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); | ||
| 938 | if (!m_sps_pps_context.first_idr && IsSlice(unit_type)) | ||
| 939 | { | ||
| 940 | m_sps_pps_context.first_idr = 1; | ||
| 941 | m_sps_pps_context.idr_sps_pps_seen = 0; | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | buf += nal_size; | ||
| 946 | cumul_size += nal_size + m_sps_pps_context.length_size; | ||
| 947 | } while (cumul_size < buf_size); | ||
| 948 | |||
| 949 | return true; | ||
| 950 | |||
| 951 | fail: | ||
| 952 | av_free(*poutbuf), *poutbuf = NULL; | ||
| 953 | *poutbuf_size = 0; | ||
| 954 | return false; | ||
| 955 | } | ||
| 956 | |||
| 957 | void CBitstreamConverter::BitstreamAllocAndCopy( uint8_t **poutbuf, int *poutbuf_size, | ||
| 958 | const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size) | ||
| 959 | { | ||
| 960 | // based on h264_mp4toannexb_bsf.c (ffmpeg) | ||
| 961 | // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> | ||
| 962 | // and Licensed GPL 2.1 or greater | ||
| 963 | |||
| 964 | uint32_t offset = *poutbuf_size; | ||
| 965 | uint8_t nal_header_size = offset ? 3 : 4; | ||
| 966 | void *tmp; | ||
| 967 | |||
| 968 | *poutbuf_size += sps_pps_size + in_size + nal_header_size; | ||
| 969 | tmp = av_realloc(*poutbuf, *poutbuf_size); | ||
| 970 | if (!tmp) | ||
| 971 | return; | ||
| 972 | *poutbuf = (uint8_t*)tmp; | ||
| 973 | if (sps_pps) | ||
| 974 | memcpy(*poutbuf + offset, sps_pps, sps_pps_size); | ||
| 975 | |||
| 976 | memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); | ||
| 977 | if (!offset) | ||
| 978 | { | ||
| 979 | BS_WB32(*poutbuf + sps_pps_size, 1); | ||
| 980 | } | ||
| 981 | else | ||
| 982 | { | ||
| 983 | (*poutbuf + offset + sps_pps_size)[0] = 0; | ||
| 984 | (*poutbuf + offset + sps_pps_size)[1] = 0; | ||
| 985 | (*poutbuf + offset + sps_pps_size)[2] = 1; | ||
| 986 | } | ||
| 987 | } | ||
| 988 | |||
| 989 | int CBitstreamConverter::avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size) | ||
| 990 | { | ||
| 991 | const uint8_t *p = buf_in; | ||
| 992 | const uint8_t *end = p + size; | ||
| 993 | const uint8_t *nal_start, *nal_end; | ||
| 994 | |||
| 995 | size = 0; | ||
| 996 | nal_start = avc_find_startcode(p, end); | ||
| 997 | |||
| 998 | for (;;) { | ||
| 999 | while (nal_start < end && !*(nal_start++)); | ||
| 1000 | if (nal_start == end) | ||
| 1001 | break; | ||
| 1002 | |||
| 1003 | nal_end = avc_find_startcode(nal_start, end); | ||
| 1004 | avio_wb32(pb, nal_end - nal_start); | ||
| 1005 | avio_write(pb, nal_start, nal_end - nal_start); | ||
| 1006 | size += 4 + nal_end - nal_start; | ||
| 1007 | nal_start = nal_end; | ||
| 1008 | } | ||
| 1009 | return size; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | int CBitstreamConverter::avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) | ||
| 1013 | { | ||
| 1014 | AVIOContext *pb; | ||
| 1015 | int ret = avio_open_dyn_buf(&pb); | ||
| 1016 | if (ret < 0) | ||
| 1017 | return ret; | ||
| 1018 | |||
| 1019 | avc_parse_nal_units(pb, buf_in, *size); | ||
| 1020 | |||
| 1021 | av_freep(buf); | ||
| 1022 | *size = avio_close_dyn_buf(pb, buf); | ||
| 1023 | return 0; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | int CBitstreamConverter::isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) | ||
| 1027 | { | ||
| 1028 | // extradata from bytestream h264, convert to avcC atom data for bitstream | ||
| 1029 | if (len > 6) | ||
| 1030 | { | ||
| 1031 | /* check for h264 start code */ | ||
| 1032 | if (BS_RB32(data) == 0x00000001 || BS_RB24(data) == 0x000001) | ||
| 1033 | { | ||
| 1034 | uint8_t *buf=NULL, *end, *start; | ||
| 1035 | uint32_t sps_size=0, pps_size=0; | ||
| 1036 | uint8_t *sps=0, *pps=0; | ||
| 1037 | |||
| 1038 | int ret = avc_parse_nal_units_buf(data, &buf, &len); | ||
| 1039 | if (ret < 0) | ||
| 1040 | return ret; | ||
| 1041 | start = buf; | ||
| 1042 | end = buf + len; | ||
| 1043 | |||
| 1044 | /* look for sps and pps */ | ||
| 1045 | while (end - buf > 4) | ||
| 1046 | { | ||
| 1047 | uint32_t size; | ||
| 1048 | uint8_t nal_type; | ||
| 1049 | size = std::min<uint32_t>(BS_RB32(buf), end - buf - 4); | ||
| 1050 | buf += 4; | ||
| 1051 | nal_type = buf[0] & 0x1f; | ||
| 1052 | if (nal_type == 7) /* SPS */ | ||
| 1053 | { | ||
| 1054 | sps = buf; | ||
| 1055 | sps_size = size; | ||
| 1056 | } | ||
| 1057 | else if (nal_type == 8) /* PPS */ | ||
| 1058 | { | ||
| 1059 | pps = buf; | ||
| 1060 | pps_size = size; | ||
| 1061 | } | ||
| 1062 | buf += size; | ||
| 1063 | } | ||
| 1064 | if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) | ||
| 1065 | assert(0); | ||
| 1066 | |||
| 1067 | avio_w8(pb, 1); /* version */ | ||
| 1068 | avio_w8(pb, sps[1]); /* profile */ | ||
| 1069 | avio_w8(pb, sps[2]); /* profile compat */ | ||
| 1070 | avio_w8(pb, sps[3]); /* level */ | ||
| 1071 | avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ | ||
| 1072 | avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ | ||
| 1073 | |||
| 1074 | avio_wb16(pb, sps_size); | ||
| 1075 | avio_write(pb, sps, sps_size); | ||
| 1076 | if (pps) | ||
| 1077 | { | ||
| 1078 | avio_w8(pb, 1); /* number of pps */ | ||
| 1079 | avio_wb16(pb, pps_size); | ||
| 1080 | avio_write(pb, pps, pps_size); | ||
| 1081 | } | ||
| 1082 | av_free(start); | ||
| 1083 | } | ||
| 1084 | else | ||
| 1085 | { | ||
| 1086 | avio_write(pb, data, len); | ||
| 1087 | } | ||
| 1088 | } | ||
| 1089 | return 0; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | //////////////////////////////////////////////////////////////////////////////////////////// | ||
| 1093 | ///////////////////////////////////////////////////////////////////////////////////////////// | ||
| 1094 | bool CBitstreamConverter::mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence) | ||
| 1095 | { | ||
| 1096 | // parse nal's until a sequence_header_code is found | ||
| 1097 | // and return the width, height, aspect ratio and frame rate if changed. | ||
| 1098 | bool changed = false; | ||
| 1099 | |||
| 1100 | if (!data) | ||
| 1101 | return changed; | ||
| 1102 | |||
| 1103 | const uint8_t *p = data; | ||
| 1104 | const uint8_t *end = p + size; | ||
| 1105 | const uint8_t *nal_start, *nal_end; | ||
| 1106 | |||
| 1107 | nal_start = avc_find_startcode(p, end); | ||
| 1108 | while (nal_start < end) | ||
| 1109 | { | ||
| 1110 | while (!*(nal_start++)); | ||
| 1111 | nal_end = avc_find_startcode(nal_start, end); | ||
| 1112 | if (*nal_start == 0xB3) | ||
| 1113 | { | ||
| 1114 | nal_bitstream bs; | ||
| 1115 | nal_bs_init(&bs, nal_start, end - nal_start); | ||
| 1116 | |||
| 1117 | // sequence_header_code | ||
| 1118 | nal_bs_read(&bs, 8); | ||
| 1119 | |||
| 1120 | // width | ||
| 1121 | // nal_start + 12 bits == horizontal_size_value | ||
| 1122 | uint32_t width = nal_bs_read(&bs, 12); | ||
| 1123 | if (width != sequence->width) | ||
| 1124 | { | ||
| 1125 | changed = true; | ||
| 1126 | sequence->width = width; | ||
| 1127 | } | ||
| 1128 | // height | ||
| 1129 | // nal_start + 24 bits == vertical_size_value | ||
| 1130 | uint32_t height = nal_bs_read(&bs, 12); | ||
| 1131 | if (height != sequence->height) | ||
| 1132 | { | ||
| 1133 | changed = true; | ||
| 1134 | sequence->height = height; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | // aspect ratio | ||
| 1138 | // nal_start + 28 bits == aspect_ratio_information | ||
| 1139 | float ratio = sequence->ratio; | ||
| 1140 | uint32_t ratio_info = nal_bs_read(&bs, 4); | ||
| 1141 | switch(ratio_info) | ||
| 1142 | { | ||
| 1143 | case 0x01: | ||
| 1144 | ratio = 1.0f; | ||
| 1145 | break; | ||
| 1146 | default: | ||
| 1147 | case 0x02: | ||
| 1148 | ratio = 4.0f/3; | ||
| 1149 | break; | ||
| 1150 | case 0x03: | ||
| 1151 | ratio = 16.0f/9; | ||
| 1152 | break; | ||
| 1153 | case 0x04: | ||
| 1154 | ratio = 2.21f; | ||
| 1155 | break; | ||
| 1156 | } | ||
| 1157 | if (ratio_info != sequence->ratio_info) | ||
| 1158 | { | ||
| 1159 | changed = true; | ||
| 1160 | sequence->ratio = ratio; | ||
| 1161 | sequence->ratio_info = ratio_info; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | // frame rate | ||
| 1165 | // nal_start + 32 bits == frame_rate_code | ||
| 1166 | uint32_t fpsrate = sequence->fps_rate; | ||
| 1167 | uint32_t fpsscale = sequence->fps_scale; | ||
| 1168 | uint32_t rate_info = nal_bs_read(&bs, 4); | ||
| 1169 | |||
| 1170 | switch(rate_info) | ||
| 1171 | { | ||
| 1172 | default: | ||
| 1173 | case 0x01: | ||
| 1174 | fpsrate = 24000; | ||
| 1175 | fpsscale = 1001; | ||
| 1176 | break; | ||
| 1177 | case 0x02: | ||
| 1178 | fpsrate = 24000; | ||
| 1179 | fpsscale = 1000; | ||
| 1180 | break; | ||
| 1181 | case 0x03: | ||
| 1182 | fpsrate = 25000; | ||
| 1183 | fpsscale = 1000; | ||
| 1184 | break; | ||
| 1185 | case 0x04: | ||
| 1186 | fpsrate = 30000; | ||
| 1187 | fpsscale = 1001; | ||
| 1188 | break; | ||
| 1189 | case 0x05: | ||
| 1190 | fpsrate = 30000; | ||
| 1191 | fpsscale = 1000; | ||
| 1192 | break; | ||
| 1193 | case 0x06: | ||
| 1194 | fpsrate = 50000; | ||
| 1195 | fpsscale = 1000; | ||
| 1196 | break; | ||
| 1197 | case 0x07: | ||
| 1198 | fpsrate = 60000; | ||
| 1199 | fpsscale = 1001; | ||
| 1200 | break; | ||
| 1201 | case 0x08: | ||
| 1202 | fpsrate = 60000; | ||
| 1203 | fpsscale = 1000; | ||
| 1204 | break; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | if (fpsscale != sequence->fps_scale || fpsrate != sequence->fps_rate) | ||
| 1208 | { | ||
| 1209 | changed = true; | ||
| 1210 | sequence->fps_rate = fpsrate; | ||
| 1211 | sequence->fps_scale = fpsscale; | ||
| 1212 | } | ||
| 1213 | } | ||
| 1214 | nal_start = nal_end; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | return changed; | ||
| 1218 | } | ||
| 1219 | |||
