diff options
Diffstat (limited to 'mfx_stub')
| -rw-r--r-- | mfx_stub/bitstream.c | 89 | ||||
| -rw-r--r-- | mfx_stub/bitstream.h | 46 | ||||
| -rw-r--r-- | mfx_stub/include/mfxcommon.h | 46 | ||||
| -rw-r--r-- | mfx_stub/include/mfxdefs.h | 49 | ||||
| -rw-r--r-- | mfx_stub/include/mfxsession.h | 27 | ||||
| -rw-r--r-- | mfx_stub/include/mfxstructures.h | 90 | ||||
| -rw-r--r-- | mfx_stub/include/mfxvideo.h | 48 | ||||
| -rw-r--r-- | mfx_stub/mfxsession.c | 35 | ||||
| -rw-r--r-- | mfx_stub/mfxsession_impl.h | 41 | ||||
| -rw-r--r-- | mfx_stub/mfxvideo.c | 401 | 
10 files changed, 872 insertions, 0 deletions
| diff --git a/mfx_stub/bitstream.c b/mfx_stub/bitstream.c new file mode 100644 index 0000000..058cd75 --- /dev/null +++ b/mfx_stub/bitstream.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#include "bitstream.h" + +#include <string.h> + +static uint64_t BitstreamReadBit(struct Bitstream* bitstream) { +  size_t shift = 7 - (bitstream->offset & 0x7); +  if (shift == 7) { +    size_t byte; +  repeat: +    byte = bitstream->offset >> 3; +    if (byte >= bitstream->size) longjmp(bitstream->trap, 1); +    bitstream->cache = (bitstream->cache << 8) | bitstream->data[byte]; +    if (bitstream->offset >= 24 && (bitstream->cache & 0xffffff) == 3) { +      bitstream->offset += 8; +      bitstream->epb_count++; +      goto repeat; +    } +  } +  bitstream->offset++; +  return bitstream->cache >> shift & 0x1; +} + +uint64_t BitstreamReadU(struct Bitstream* bitstream, size_t size) { +  uint64_t result = 0; +  for (; size; size--) { +    result = (result << 1) | BitstreamReadBit(bitstream); +  } +  return result; +} + +uint64_t BitstreamReadUE(struct Bitstream* bitstream) { +  size_t size = 0; +  while (!BitstreamReadBit(bitstream)) size++; +  return (BitstreamReadU(bitstream, size) | (1 << size)) - 1; +} + +int64_t BitstreamReadSE(struct Bitstream* bitstream) { +  uint64_t result = BitstreamReadUE(bitstream); +  int64_t sign = (int64_t)((result & 1) << 1) - 1; +  return sign * (int64_t)((result + 1) >> 1); +} + +void BitstreamByteAlign(struct Bitstream* bitstream) { +  bitstream->offset = (bitstream->offset + 7) & ~(size_t)7; +} + +bool BitstreamReadNalu(struct Bitstream* bitstream, struct Bitstream* output) { +  if (bitstream->offset & 0x7) return false; +  size_t byte_offset = bitstream->offset >> 3; +  static const uint8_t kStartCodePrefix[] = {0, 0, 0, 1}; +  if (bitstream->size - byte_offset < sizeof(kStartCodePrefix)) { +    return false; +  } +  const uint8_t* data = bitstream->data + byte_offset; +  if (memcmp(bitstream->data + byte_offset, kStartCodePrefix, +             sizeof(kStartCodePrefix))) { +    return false; +  } +  data += sizeof(kStartCodePrefix); +  byte_offset += sizeof(kStartCodePrefix); +  size_t max_size = bitstream->size - byte_offset; +  uint8_t* next = +      memmem(data, max_size, kStartCodePrefix, sizeof(kStartCodePrefix)); +  size_t size = next ? (size_t)(next - data) : max_size; +  bitstream->offset = (byte_offset + size) << 3; +  *output = BitstreamCreate(data, size); +  return true; +} + +bool BitstreamAvail(const struct Bitstream* bitstream) { +  return bitstream->offset < (bitstream->size << 3); +} diff --git a/mfx_stub/bitstream.h b/mfx_stub/bitstream.h new file mode 100644 index 0000000..4a1faa2 --- /dev/null +++ b/mfx_stub/bitstream.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_BITSTREAM_H_ +#define MFX_STUB_BITSTREAM_H_ + +#include <setjmp.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define BitstreamCreate(a, b) \ +  (struct Bitstream) { .data = a, .size = b } +#define BitstreamReadFailed(x) setjmp((x)->trap) + +struct Bitstream { +  const uint8_t* data; +  size_t size; +  size_t offset; +  size_t epb_count; +  uint32_t cache; +  jmp_buf trap; +}; + +uint64_t BitstreamReadU(struct Bitstream* bitstream, size_t size); +uint64_t BitstreamReadUE(struct Bitstream* bitstream); +int64_t BitstreamReadSE(struct Bitstream* bitstream); +void BitstreamByteAlign(struct Bitstream* bitstream); +bool BitstreamReadNalu(struct Bitstream* bitstream, struct Bitstream* output); +bool BitstreamAvail(const struct Bitstream* bitstream); + +#endif  // MFX_STUB_BITSTREAM_H_ diff --git a/mfx_stub/include/mfxcommon.h b/mfx_stub/include/mfxcommon.h new file mode 100644 index 0000000..f4b1e26 --- /dev/null +++ b/mfx_stub/include/mfxcommon.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_INCLUDE_MFXCOMMON_H_ +#define MFX_STUB_INCLUDE_MFXCOMMON_H_ + +#include "mfxdefs.h" + +#define MFX_MAKEFOURCC(a, b, c, d)                       \ +  (((a) << 24 & 0xff000000) | ((b) << 16 & 0x00ff0000) | \ +   ((c) << 8 & 0x0000ff00) | ((d) << 0 & 0x000000ff)) + +typedef mfxI32 mfxIMPL; + +enum { +  MFX_IMPL_HARDWARE = 0x0002, +}; + +typedef union mfxVersion mfxVersion; + +typedef struct { +  mfxI64 DecodeTimeStamp; +  mfxU64 TimeStamp; +  mfxU8* Data; +  mfxU32 DataLength; +  mfxU32 MaxLength; +  mfxU16 DataFlag; +} mfxBitstream; + +typedef struct _mfxSyncPoint* mfxSyncPoint; + +#endif  // MFX_STUB_INCLUDE_MFXCOMMON_H_ diff --git a/mfx_stub/include/mfxdefs.h b/mfx_stub/include/mfxdefs.h new file mode 100644 index 0000000..4589513 --- /dev/null +++ b/mfx_stub/include/mfxdefs.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_INCLUDE_MFXDEFS_H_ +#define MFX_STUB_INCLUDE_MFXDEFS_H_ + +#include <stdint.h> + +#define MFX_INFINITE 0xffffffff + +typedef uint8_t mfxU8; +typedef int8_t mfxI8; +typedef int16_t mfxI16; +typedef uint16_t mfxU16; +typedef uint32_t mfxU32; +typedef int32_t mfxI32; +typedef uint64_t mfxU64; +typedef int64_t mfxI64; +typedef void* mfxHDL; +typedef mfxHDL mfxMemId; + +typedef enum { +  MFX_ERR_NONE = 0, +  MFX_ERR_UNSUPPORTED = -3, +  MFX_ERR_MEMORY_ALLOC = -4, +  MFX_ERR_MORE_DATA = -10, +  MFX_ERR_MORE_SURFACE = -11, +  MFX_ERR_DEVICE_FAILED = -17, +  MFX_ERR_REALLOC_SURFACE = -22, +  MFX_WRN_DEVICE_BUSY = 2, +  MFX_WRN_VIDEO_PARAM_CHANGED = 3, +  MFX_ERR_NONE_PARTIAL_OUTPUT = 12, +} mfxStatus; + +#endif  // MFX_STUB_INCLUDE_MFXDEFS_H_ diff --git a/mfx_stub/include/mfxsession.h b/mfx_stub/include/mfxsession.h new file mode 100644 index 0000000..d39a6ac --- /dev/null +++ b/mfx_stub/include/mfxsession.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_INCLUDE_MFXSESSION_H_ +#define MFX_STUB_INCLUDE_MFXSESSION_H_ + +#include "mfxcommon.h" + +typedef struct _mfxSession* mfxSession; +mfxStatus MFXInit(mfxIMPL impl, mfxVersion* ver, mfxSession* session); +mfxStatus MFXClose(mfxSession session); + +#endif  // MFX_STUB_INCLUDE_MFXSESSION_H_ diff --git a/mfx_stub/include/mfxstructures.h b/mfx_stub/include/mfxstructures.h new file mode 100644 index 0000000..64353c4 --- /dev/null +++ b/mfx_stub/include/mfxstructures.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_INCLUDE_MFXSTRUCTURES_H_ +#define MFX_STUB_INCLUDE_MFXSTRUCTURES_H_ + +#include "mfxcommon.h" + +typedef struct { +  mfxU32 FourCC; +  mfxU16 Width; +  mfxU16 Height; +  mfxU16 CropX; +  mfxU16 CropY; +  mfxU16 CropW; +  mfxU16 CropH; +  mfxU16 ChromaFormat; +} mfxFrameInfo; + +enum { +  MFX_FOURCC_NV12 = MFX_MAKEFOURCC('N', 'V', '1', '2'), +}; + +enum { +  MFX_CHROMAFORMAT_YUV420 = 1, +}; + +enum { +  MFX_TIMESTAMP_UNKNOWN = -1, +}; + +typedef struct { +  mfxFrameInfo Info; +  struct { +    mfxMemId MemId; +  } Data; +} mfxFrameSurface1; + +typedef struct { +  mfxU16 AsyncDepth; +  struct { +    mfxU32 CodecId; +    mfxU16 DecodedOrder; +  } mfx; +  mfxU16 IOPattern; +} mfxVideoParam; + +enum { +  MFX_IOPATTERN_OUT_VIDEO_MEMORY = 0x10, +}; + +enum { +  MFX_CODEC_HEVC = MFX_MAKEFOURCC('H', 'E', 'V', 'C'), +}; + +enum { +  MFX_BITSTREAM_COMPLETE_FRAME = 0x0001, +}; + +typedef struct { +  mfxU32 AllocId; +  mfxU16 NumFrameSuggested; +  mfxFrameInfo Info; +} mfxFrameAllocRequest; + +typedef struct { +  mfxU32 AllocId; +  mfxMemId* mids; +  mfxU16 NumFrameActual; +} mfxFrameAllocResponse; + +typedef enum { +  MFX_HANDLE_VA_DISPLAY = 4, +} mfxHandleType; + +#endif  // MFX_STUB_INCLUDE_MFXSTRUCTURES_H_ diff --git a/mfx_stub/include/mfxvideo.h b/mfx_stub/include/mfxvideo.h new file mode 100644 index 0000000..dec1789 --- /dev/null +++ b/mfx_stub/include/mfxvideo.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_INCLUDE_MFXVIDEO_H_ +#define MFX_STUB_INCLUDE_MFXVIDEO_H_ + +#include "mfxsession.h" +#include "mfxstructures.h" + +typedef struct { +  mfxHDL pthis; +  mfxStatus (*Alloc)(mfxHDL, mfxFrameAllocRequest*, mfxFrameAllocResponse*); +  mfxStatus (*GetHDL)(mfxHDL, mfxMemId, mfxHDL*); +  mfxStatus (*Free)(mfxHDL, mfxFrameAllocResponse*); +} mfxFrameAllocator; + +mfxStatus MFXVideoCORE_SetFrameAllocator(mfxSession session, +                                         mfxFrameAllocator* allocator); +mfxStatus MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, +                                 mfxHDL hdl); +mfxStatus MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, +                                     mfxU32 wait); + +mfxStatus MFXVideoDECODE_Query(mfxSession session, mfxVideoParam* in, +                               mfxVideoParam* out); +mfxStatus MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream* bs, +                                      mfxVideoParam* par); +mfxStatus MFXVideoDECODE_Init(mfxSession session, mfxVideoParam* par); +mfxStatus MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream* bs, +                                          mfxFrameSurface1* surface_work, +                                          mfxFrameSurface1** surface_out, +                                          mfxSyncPoint* syncp); + +#endif  // MFX_STUB_INCLUDE_MFXVIDEO_H_ diff --git a/mfx_stub/mfxsession.c b/mfx_stub/mfxsession.c new file mode 100644 index 0000000..13bf8fc --- /dev/null +++ b/mfx_stub/mfxsession.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#include <mfxsession.h> +#include <stdlib.h> + +#include "mfxsession_impl.h" + +mfxStatus MFXInit(mfxIMPL impl, mfxVersion* ver, mfxSession* session) { +  (void)impl; +  (void)ver; +  mfxSession result = malloc(sizeof(struct _mfxSession)); +  if (!result) return MFX_ERR_MEMORY_ALLOC; +  *session = result; +  return MFX_ERR_NONE; +} + +mfxStatus MFXClose(mfxSession session) { +  free(session); +  return MFX_ERR_NONE; +} diff --git a/mfx_stub/mfxsession_impl.h b/mfx_stub/mfxsession_impl.h new file mode 100644 index 0000000..5b359e1 --- /dev/null +++ b/mfx_stub/mfxsession_impl.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef MFX_STUB_MFXSESSION_IMPL_H_ +#define MFX_STUB_MFXSESSION_IMPL_H_ + +#include <stddef.h> +#include <va/va.h> + +#include "mfxvideo.h" + +struct _mfxSession { +  mfxFrameAllocator allocator; +  VADisplay display; + +  VAConfigID config_id; +  VAContextID context_id; +  mfxMemId* mids; +  size_t mids_count; + +  VAPictureParameterBufferHEVC ppb; +  VASliceParameterBufferHEVC spb; +  size_t global_frame_counter; +  size_t local_frame_counter; +}; + +#endif  // MFX_STUB_MFXSESSION_IMPL_H_ diff --git a/mfx_stub/mfxvideo.c b/mfx_stub/mfxvideo.c new file mode 100644 index 0000000..d070755 --- /dev/null +++ b/mfx_stub/mfxvideo.c @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2024 Mikhail Burakov. This file is part of receiver. + * + * receiver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * receiver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with receiver.  If not, see <https://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <mfxvideo.h> +#include <stdlib.h> +#include <string.h> + +#include "bitstream.h" +#include "mfxsession_impl.h" + +// Table 7-1 – NAL unit type codes and NAL unit type classes +enum NalUnitType { +  TRAIL_R = 1, +  BLA_W_LP = 16, +  IDR_W_RADL = 19, +  IDR_N_LP = 20, +  CRA_NUT = 21, +  RSV_IRAP_VCL23 = 23, +  VPS_NUT = 32, +  SPS_NUT = 33, +  PPS_NUT = 34, +  AUD_NUT = 35, +}; + +// 7.3.1.2 NAL unit header syntax +static uint8_t ParseNaluHeader(struct Bitstream* nalu) { +  assert(BitstreamReadU(nalu, 1) == 0);  // forbidden_zero_bit +  uint64_t nal_unit_type = BitstreamReadU(nalu, 6); +  assert(BitstreamReadU(nalu, 6) == 0);  // nuh_layer_id +  assert(BitstreamReadU(nalu, 3) == 1);  // nuh_temporal_id_plus1 +  return (uint8_t)nal_unit_type; +} + +// 7.3.3 Profile, tier and level syntax +static void ParseProfileTierLevel(struct Bitstream* nalu) { +  assert(BitstreamReadU(nalu, 2) == 0);  // general_profile_space +  assert(BitstreamReadU(nalu, 1) == 0);  // general_tier_flag +  assert(BitstreamReadU(nalu, 5) == 1);  // general_profile_idc +  assert(BitstreamReadU(nalu, 32) == +         3 << 29);                       // general_profile_compatibility_flag +  assert(BitstreamReadU(nalu, 1) == 1);  // general_progressive_source_flag +  assert(BitstreamReadU(nalu, 1) == 0);  // general_interlaced_source_flag +  assert(BitstreamReadU(nalu, 1) == 1);  // general_non_packed_constraint_flag +  assert(BitstreamReadU(nalu, 1) == 1);  // general_frame_only_constraint_flag +  assert(BitstreamReadU(nalu, 7) == 0);  // general_reserved_zero_7bits +  assert(BitstreamReadU(nalu, 1) == +         0);  // general_one_picture_only_constraint_flag +  assert(BitstreamReadU(nalu, 35) == 0);   // general_reserved_zero_35bits +  assert(BitstreamReadU(nalu, 1) == 0);    // general_reserved_zero_bit +  assert(BitstreamReadU(nalu, 8) == 120);  // general_level_idc +} + +// 7.3.7 Short-term reference picture set syntax +static void ParseStRefPicSet(struct Bitstream* nalu, uint64_t stRpsIdx) { +  if (stRpsIdx != 0) { +    assert(BitstreamReadU(nalu, 1) == 0);  // inter_ref_pic_set_prediction_flag +  } +  assert(BitstreamReadUE(nalu) == 1);    // num_negative_pics +  assert(BitstreamReadUE(nalu) == 0);    // num_positive_pics +  assert(BitstreamReadUE(nalu) == 0);    // delta_poc_s0_minus1 +  assert(BitstreamReadU(nalu, 1) == 1);  // used_by_curr_pic_s0_flag +} + +// E.2.1 VUI parameters syntax +static void ParseVuiParameters(struct Bitstream* nalu) { +  assert(BitstreamReadU(nalu, 1) == 0);  // aspect_ratio_info_present_flag +  assert(BitstreamReadU(nalu, 1) == 0);  // overscan_info_present_flag +  assert(BitstreamReadU(nalu, 1) == 1);  // video_signal_type_present_flag + +  // Table E.2 – Meaning of video_format +  assert(BitstreamReadU(nalu, 3) == 5);  // video_format +  assert(BitstreamReadU(nalu, 1) == 0);  // video_full_range_flag +  assert(BitstreamReadU(nalu, 1) == 1);  //  colour_description_present_flag + +  assert(BitstreamReadU(nalu, 8) == 2);  // colour_primaries +  assert(BitstreamReadU(nalu, 8) == 2);  // transfer_characteristics +  assert(BitstreamReadU(nalu, 8) == 6);  // matrix_coeffs + +  assert(BitstreamReadU(nalu, 1) == 0);  // chroma_loc_info_present_flag +  assert(BitstreamReadU(nalu, 1) == 0);  // neutral_chroma_indication_flag +  assert(BitstreamReadU(nalu, 1) == 0);  // field_seq_flag +  assert(BitstreamReadU(nalu, 1) == 0);  // vui_timing_info_present_flag + +  bool bitstream_restriction_flag = !!BitstreamReadU(nalu, 1); +  if (bitstream_restriction_flag) { +    assert(BitstreamReadU(nalu, 1) == 0);  // tiles_fixed_structure_flag +    assert(BitstreamReadU(nalu, 1) == +           1);  // motion_vectors_over_pic_boundaries_flag +    assert(BitstreamReadU(nalu, 1) == 1);  // restricted_ref_pic_lists_flag +    assert(BitstreamReadUE(nalu) == 0);    // min_spatial_segmentation_idc +    assert(BitstreamReadUE(nalu) == 0);    // max_bytes_per_pic_denom +    assert(BitstreamReadUE(nalu) == 0);    // max_bits_per_min_cu_denom +    assert(BitstreamReadUE(nalu) == 15);   // log2_max_mv_length_horizontal +    assert(BitstreamReadUE(nalu) == 15);   // log2_max_mv_length_vertical +  } +} + +// 7.3.2.2.1 General sequence parameter set RBSP syntax +static void ParseSps(struct Bitstream* nalu, mfxSession session) { +  assert(BitstreamReadU(nalu, 4) == 0);  // sps_video_parameter_set_id +  assert(BitstreamReadU(nalu, 3) == 0);  // sps_max_sub_layers_minus1 +  assert(BitstreamReadU(nalu, 1) == 1);  // sps_temporal_id_nesting_flag +  ParseProfileTierLevel(nalu); +  assert(BitstreamReadUE(nalu) == 0);  // sps_seq_parameter_set_id +                                       // +  session->ppb.pic_fields.bits.chroma_format_idc = +      (uint32_t)BitstreamReadUE(nalu); +  assert(session->ppb.pic_fields.bits.chroma_format_idc == 1); +  session->ppb.pic_width_in_luma_samples = (uint16_t)BitstreamReadUE(nalu); +  session->ppb.pic_height_in_luma_samples = (uint16_t)BitstreamReadUE(nalu); +  assert(BitstreamReadU(nalu, 1) == 0);  // conformance_window_flag + +  session->ppb.bit_depth_luma_minus8 = (uint8_t)BitstreamReadUE(nalu); +  session->ppb.bit_depth_chroma_minus8 = (uint8_t)BitstreamReadUE(nalu); +  session->ppb.log2_max_pic_order_cnt_lsb_minus4 = +      (uint8_t)BitstreamReadUE(nalu); +  assert(BitstreamReadU(nalu, 1) == +         0);  // sps_sub_layer_ordering_info_present_flag + +  session->ppb.sps_max_dec_pic_buffering_minus1 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.pic_fields.bits.NoPicReorderingFlag = +      !!BitstreamReadUE(nalu);         // sps_max_num_reorder_pics +  assert(BitstreamReadUE(nalu) == 0);  // sps_max_latency_increase_plus1 + +  session->ppb.log2_min_luma_coding_block_size_minus3 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.log2_diff_max_min_luma_coding_block_size = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.log2_min_transform_block_size_minus2 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.log2_diff_max_min_transform_block_size = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.max_transform_hierarchy_depth_inter = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.max_transform_hierarchy_depth_intra = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.pic_fields.bits.scaling_list_enabled_flag = +      (uint8_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.scaling_list_enabled_flag == 0); + +  session->ppb.pic_fields.bits.amp_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.slice_parsing_fields.bits.sample_adaptive_offset_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.pic_fields.bits.pcm_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.pcm_enabled_flag == 0); + +  // vvv weird vvv +  session->ppb.pcm_sample_bit_depth_luma_minus1 = +      (uint8_t)((1 << (session->ppb.bit_depth_luma_minus8 + 8)) - 1); +  session->ppb.pcm_sample_bit_depth_chroma_minus1 = +      (uint8_t)((1 << (session->ppb.bit_depth_chroma_minus8 + 8)) - 1); +  session->ppb.log2_min_pcm_luma_coding_block_size_minus3 = 253; +  // ^^^ weird ^^^ + +  session->ppb.num_short_term_ref_pic_sets = (uint8_t)BitstreamReadUE(nalu); +  for (uint8_t i = 0; i < session->ppb.num_short_term_ref_pic_sets; i++) { +    ParseStRefPicSet(nalu, i); +  } +  assert(BitstreamReadU(nalu, 1) == 0);  // long_term_ref_pics_present_flag + +  session->ppb.slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.pic_fields.bits.strong_intra_smoothing_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(BitstreamReadU(nalu, 1) == 1);  // vui_parameters_present_flag + +  ParseVuiParameters(nalu); +  assert(BitstreamReadU(nalu, 1) == 0);  // sps_extension_present_flag +} + +// 7.3.2.3.1 General picture parameter set RBSP syntax +static void ParsePps(struct Bitstream* nalu, mfxSession session) { +  assert(BitstreamReadUE(nalu) == 0);  // pps_pic_parameter_set_id +  assert(BitstreamReadUE(nalu) == 0);  // pps_seq_parameter_set_id + +  session->ppb.slice_parsing_fields.bits.dependent_slice_segments_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.slice_parsing_fields.bits.output_flag_present_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.num_extra_slice_header_bits = (uint8_t)BitstreamReadU(nalu, 3); +  assert(session->ppb.num_extra_slice_header_bits == 0); + +  session->ppb.pic_fields.bits.sign_data_hiding_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.slice_parsing_fields.bits.cabac_init_present_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.num_ref_idx_l0_default_active_minus1 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.num_ref_idx_l1_default_active_minus1 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.init_qp_minus26 = (int8_t)BitstreamReadSE(nalu); +  session->ppb.pic_fields.bits.constrained_intra_pred_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.pic_fields.bits.transform_skip_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.pic_fields.bits.cu_qp_delta_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.cu_qp_delta_enabled_flag == 0); + +  session->ppb.pps_cb_qp_offset = (int8_t)BitstreamReadSE(nalu); +  session->ppb.pps_cr_qp_offset = (int8_t)BitstreamReadSE(nalu); +  session->ppb.slice_parsing_fields.bits +      .pps_slice_chroma_qp_offsets_present_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.slice_parsing_fields.bits +             .pps_slice_chroma_qp_offsets_present_flag == 0); + +  session->ppb.pic_fields.bits.weighted_pred_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.weighted_pred_flag == 0); +  session->ppb.pic_fields.bits.weighted_bipred_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.weighted_bipred_flag == 0); + +  session->ppb.pic_fields.bits.transquant_bypass_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  session->ppb.pic_fields.bits.tiles_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.tiles_enabled_flag == 0); + +  // vvv weird vvv +  session->ppb.pic_fields.bits.loop_filter_across_tiles_enabled_flag = 1; +  // ^^^ weird ^^^ + +  session->ppb.pic_fields.bits.entropy_coding_sync_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.pic_fields.bits.entropy_coding_sync_enabled_flag == 0); + +  session->ppb.pic_fields.bits.pps_loop_filter_across_slices_enabled_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  bool deblocking_filter_control_present_flag = !!BitstreamReadU(nalu, 1); +  if (deblocking_filter_control_present_flag) { +    session->ppb.slice_parsing_fields.bits +        .deblocking_filter_override_enabled_flag = +        (uint32_t)BitstreamReadU(nalu, 1); +    assert(session->ppb.slice_parsing_fields.bits +               .deblocking_filter_override_enabled_flag == 0); +    session->ppb.slice_parsing_fields.bits.pps_disable_deblocking_filter_flag = +        (uint32_t)BitstreamReadU(nalu, 1); +    assert(session->ppb.slice_parsing_fields.bits +               .pps_disable_deblocking_filter_flag == 0); +    session->ppb.pps_beta_offset_div2 = (int8_t)BitstreamReadSE(nalu); +    session->ppb.pps_tc_offset_div2 = (int8_t)BitstreamReadSE(nalu); +  } + +  assert(BitstreamReadU(nalu, 1) == 0);  // scaling_list_data_present_flag +  session->ppb.slice_parsing_fields.bits.lists_modification_present_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert( +      session->ppb.slice_parsing_fields.bits.lists_modification_present_flag == +      0); +  session->ppb.log2_parallel_merge_level_minus2 = +      (uint8_t)BitstreamReadUE(nalu); +  session->ppb.slice_parsing_fields.bits +      .slice_segment_header_extension_present_flag = +      (uint32_t)BitstreamReadU(nalu, 1); +  assert(session->ppb.slice_parsing_fields.bits +             .slice_segment_header_extension_present_flag == 0); +  assert(BitstreamReadU(nalu, 1) == 0);  // pps_extension_present_flag +} + +mfxStatus MFXVideoCORE_SetFrameAllocator(mfxSession session, +                                         mfxFrameAllocator* allocator) { +  session->allocator = *allocator; +  return MFX_ERR_NONE; +} + +mfxStatus MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, +                                 mfxHDL hdl) { +  (void)type; +  session->display = hdl; +  return MFX_ERR_NONE; +} + +mfxStatus MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, +                                     mfxU32 wait) { +  (void)session; +  (void)syncp; +  (void)wait; +  return MFX_ERR_NONE; +} + +mfxStatus MFXVideoDECODE_Query(mfxSession session, mfxVideoParam* in, +                               mfxVideoParam* out) { +  (void)session; +  (void)in; +  (void)out; +  return MFX_ERR_NONE; +} + +mfxStatus MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream* bs, +                                      mfxVideoParam* par) { +  (void)par; +  struct Bitstream bitstream = BitstreamCreate(bs->Data, bs->DataLength); +  for (struct Bitstream nalu; BitstreamAvail(&bitstream);) { +    if (!BitstreamReadNalu(&bitstream, &nalu)) { +      assert(0); +      return MFX_ERR_UNSUPPORTED; +    } +    if (BitstreamReadFailed(&nalu)) { +      assert(0); +      return MFX_ERR_UNSUPPORTED; +    } +    uint8_t nal_unit_type = ParseNaluHeader(&nalu); +    switch (nal_unit_type) { +      case SPS_NUT: +        ParseSps(&nalu, session); +        break; +      case PPS_NUT: +        ParsePps(&nalu, session); +        bs->Data += bitstream.offset >> 3; +        bs->DataLength -= bitstream.offset >> 3; +        return MFX_ERR_NONE; +      default: +        break; +    } +  } +  return MFX_ERR_NONE; +} + +mfxStatus MFXVideoDECODE_Init(mfxSession session, mfxVideoParam* par) { +  (void)par; +  VAConfigID config_id; +  VAStatus status = vaCreateConfig(session->display, VAProfileHEVCMain, +                                   VAEntrypointVLD, NULL, 0, &config_id); +  if (status != VA_STATUS_SUCCESS) { +    return MFX_ERR_DEVICE_FAILED; +  } + +  VAContextID context_id; +  mfxStatus result = MFX_ERR_DEVICE_FAILED; +  status = vaCreateContext(session->display, config_id, +                           session->ppb.pic_width_in_luma_samples, +                           session->ppb.pic_height_in_luma_samples, +                           VA_PROGRESSIVE, NULL, 0, &context_id); +  if (status != VA_STATUS_SUCCESS) { +    goto rollback_config_id; +  } + +  mfxFrameAllocRequest request = { +      .Info.FourCC = MFX_FOURCC_NV12, +      .Info.Width = session->ppb.pic_width_in_luma_samples, +      .Info.Height = session->ppb.pic_height_in_luma_samples, +      .Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420, +      .NumFrameSuggested = 3, +  }; +  mfxFrameAllocResponse response; +  result = +      session->allocator.Alloc(session->allocator.pthis, &request, &response); +  if (result != MFX_ERR_NONE) { +    goto rollback_context_id; +  } + +  mfxMemId* mids = calloc(response.NumFrameActual, sizeof(mfxMemId)); +  if (!mids) { +    result = MFX_ERR_MEMORY_ALLOC; +    goto rollback_response; +  } + +  session->config_id = config_id; +  session->context_id = context_id; +  session->mids = mids; +  session->mids_count = response.NumFrameActual; +  memcpy(mids, response.mids, response.NumFrameActual * sizeof(mfxMemId)); +  return MFX_ERR_NONE; + +rollback_response: +  assert(session->allocator.Free(session->allocator.pthis, &response) == +         MFX_ERR_NONE); +rollback_context_id: +  assert(vaDestroyContext(session->display, context_id) == VA_STATUS_SUCCESS); +rollback_config_id: +  assert(vaDestroyConfig(session->display, config_id) == VA_STATUS_SUCCESS); +  return result; +} + +mfxStatus MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream* bs, +                                          mfxFrameSurface1* surface_work, +                                          mfxFrameSurface1** surface_out, +                                          mfxSyncPoint* syncp) { +  assert(0); +  return MFX_ERR_NONE; +} | 
