| 103 | { |
| 104 | |
| 105 | decoder::decoder( |
| 106 | vk::raii::Device & device, |
| 107 | vk::raii::PhysicalDevice & physical_device, |
| 108 | const wivrn::to_headset::video_stream_description & description, |
| 109 | uint8_t stream_index, |
| 110 | std::weak_ptr<scenes::stream> weak_scene, |
| 111 | shard_accumulator * accumulator) : |
| 112 | stream_index(stream_index), device(device), weak_scene(weak_scene), accumulator(accumulator) |
| 113 | { |
| 114 | spdlog::info("hbm_mutex.native_handle() = {}", (void *)hbm_mutex.native_handle()); |
| 115 | |
| 116 | auto width = description.width; |
| 117 | auto height = description.height / (stream_index == 2 ? 2 : 1); |
| 118 | |
| 119 | AImageReader * ir; |
| 120 | check(AImageReader_newWithUsage( |
| 121 | width, |
| 122 | height, |
| 123 | AIMAGE_FORMAT_PRIVATE, |
| 124 | AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, |
| 125 | scenes::stream::image_buffer_size + 4 /* maxImages */, |
| 126 | &ir), |
| 127 | "AImageReader_newWithUsage"); |
| 128 | image_reader.reset(ir, AImageReader_deleter{}); |
| 129 | |
| 130 | AImageReader_ImageListener listener{this, on_image_available}; |
| 131 | check(AImageReader_setImageListener(ir, &listener), "AImageReader_setImageListener"); |
| 132 | |
| 133 | vkGetAndroidHardwareBufferPropertiesANDROID = |
| 134 | application::get_vulkan_proc<PFN_vkGetAndroidHardwareBufferPropertiesANDROID>( |
| 135 | "vkGetAndroidHardwareBufferPropertiesANDROID"); |
| 136 | { |
| 137 | AMediaFormat_ptr format(AMediaFormat_new()); |
| 138 | AMediaFormat_setString(format.get(), AMEDIAFORMAT_KEY_MIME, mime(description.codec[stream_index])); |
| 139 | // AMediaFormat_setInt32(format.get(), "vendor.qti-ext-dec-low-latency.enable", 1); // Qualcomm low |
| 140 | // latency mode |
| 141 | AMediaFormat_setInt32(format.get(), AMEDIAFORMAT_KEY_WIDTH, width); |
| 142 | AMediaFormat_setInt32(format.get(), AMEDIAFORMAT_KEY_HEIGHT, height); |
| 143 | AMediaFormat_setInt32(format.get(), AMEDIAFORMAT_KEY_OPERATING_RATE, std::ceil(description.frame_rate)); |
| 144 | AMediaFormat_setInt32(format.get(), AMEDIAFORMAT_KEY_PRIORITY, 0); |
| 145 | |
| 146 | media_codec.reset(AMediaCodec_createDecoderByType(mime(description.codec[stream_index]))); |
| 147 | |
| 148 | if (not media_codec) |
| 149 | throw std::runtime_error(std::string("Cannot create decoder for MIME type ") + mime(description.codec[stream_index])); |
| 150 | |
| 151 | char * codec_name; |
| 152 | check(AMediaCodec_getName(media_codec.get(), &codec_name), "AMediaCodec_getName"); |
| 153 | spdlog::info("Created MediaCodec decoder \"{}\"", codec_name); |
| 154 | AMediaCodec_releaseName(media_codec.get(), codec_name); |
| 155 | |
| 156 | ANativeWindow * window; |
| 157 | |
| 158 | check(AImageReader_getWindow(image_reader.get(), &window), "AImageReader_getWindow"); |
| 159 | |
| 160 | AMediaCodecOnAsyncNotifyCallback callback{ |
| 161 | .onAsyncInputAvailable = decoder::on_media_input_available, |
| 162 | .onAsyncOutputAvailable = decoder::on_media_output_available, |