| 114 | } |
| 115 | |
| 116 | bool CVideo::Start() |
| 117 | { |
| 118 | dbg_assert(!m_Started, "Already started"); |
| 119 | |
| 120 | // wait for the graphic thread to idle |
| 121 | m_pGraphics->WaitForIdle(); |
| 122 | |
| 123 | m_AudioStream = {}; |
| 124 | m_VideoStream = {}; |
| 125 | |
| 126 | char aWholePath[IO_MAX_PATH_LENGTH]; |
| 127 | IOHANDLE File = m_pStorage->OpenFile(m_aName, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); |
| 128 | if(File) |
| 129 | { |
| 130 | io_close(File); |
| 131 | } |
| 132 | else |
| 133 | { |
| 134 | log_error("videorecorder", "Could not open file '%s'", aWholePath); |
| 135 | return false; |
| 136 | } |
| 137 | |
| 138 | const int FormatAllocResult = avformat_alloc_output_context2(&m_pFormatContext, nullptr, "mp4", aWholePath); |
| 139 | if(FormatAllocResult < 0 || !m_pFormatContext) |
| 140 | { |
| 141 | char aError[AV_ERROR_MAX_STRING_SIZE]; |
| 142 | av_strerror(FormatAllocResult, aError, sizeof(aError)); |
| 143 | log_error("videorecorder", "Could not create format context: %s", aError); |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | m_pFormat = m_pFormatContext->oformat; |
| 148 | |
| 149 | #if defined(CONF_ARCH_IA32) || defined(CONF_ARCH_ARM) || defined(CONF_ARCH_WASM) |
| 150 | // use only the minimum of 2 threads on 32-bit to save memory |
| 151 | m_VideoThreads = 2; |
| 152 | m_AudioThreads = 2; |
| 153 | #else |
| 154 | m_VideoThreads = std::thread::hardware_concurrency() + 2; |
| 155 | // audio gets a bit less |
| 156 | m_AudioThreads = (std::thread::hardware_concurrency() / 2) + 2; |
| 157 | #endif |
| 158 | |
| 159 | m_CurVideoThreadIndex = 0; |
| 160 | m_CurAudioThreadIndex = 0; |
| 161 | |
| 162 | const size_t VideoBufferSize = (size_t)4 * m_Width * m_Height * sizeof(uint8_t); |
| 163 | m_vVideoBuffers.resize(m_VideoThreads); |
| 164 | for(size_t i = 0; i < m_VideoThreads; ++i) |
| 165 | { |
| 166 | m_vVideoBuffers[i].m_vBuffer.resize(VideoBufferSize); |
| 167 | } |
| 168 | |
| 169 | m_vAudioBuffers.resize(m_AudioThreads); |
| 170 | |
| 171 | /* Add the audio and video streams using the default format codecs |
| 172 | * and initialize the codecs. */ |
| 173 | if(m_pFormat->video_codec != AV_CODEC_ID_NONE) |