| 182 | } |
| 183 | |
| 184 | void BaseEncoder::EncoderThread() { |
| 185 | |
| 186 | try { |
| 187 | |
| 188 | Logger::LogInfo("[BaseEncoder::EncoderThread] " + Logger::tr("Encoder thread started.")); |
| 189 | |
| 190 | // normal encoding |
| 191 | while(!m_should_stop) { |
| 192 | |
| 193 | // get a frame |
| 194 | std::unique_ptr<AVFrameWrapper> frame; |
| 195 | { |
| 196 | SharedLock lock(&m_shared_data); |
| 197 | if(!lock->m_frame_queue.empty()) { |
| 198 | frame = std::move(lock->m_frame_queue.front()); |
| 199 | lock->m_frame_queue.pop_front(); |
| 200 | } |
| 201 | } |
| 202 | if(frame == NULL) { |
| 203 | if(m_should_finish) { |
| 204 | break; |
| 205 | } |
| 206 | usleep(20000); |
| 207 | continue; |
| 208 | } |
| 209 | |
| 210 | // encode the frame |
| 211 | EncodeFrame(frame.get()); |
| 212 | |
| 213 | } |
| 214 | |
| 215 | // flush the encoder |
| 216 | if(!m_should_stop && (m_codec_context->codec->capabilities & AV_CODEC_CAP_DELAY)) { |
| 217 | Logger::LogInfo("[BaseEncoder::EncoderThread] " + Logger::tr("Flushing encoder ...")); |
| 218 | while(!m_should_stop) { |
| 219 | if(!EncodeFrame(NULL)) { |
| 220 | break; |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | // tell the others that we're done |
| 226 | m_is_done = true; |
| 227 | |
| 228 | Logger::LogInfo("[BaseEncoder::EncoderThread] " + Logger::tr("Encoder thread stopped.")); |
| 229 | |
| 230 | } catch(const std::exception& e) { |
| 231 | m_error_occurred = true; |
| 232 | Logger::LogError("[BaseEncoder::EncoderThread] " + Logger::tr("Exception '%1' in encoder thread.").arg(e.what())); |
| 233 | } catch(...) { |
| 234 | m_error_occurred = true; |
| 235 | Logger::LogError("[BaseEncoder::EncoderThread] " + Logger::tr("Unknown exception in encoder thread.")); |
| 236 | } |
| 237 | |
| 238 | // always end the stream, even if there was an error, otherwise the muxer will wait forever |
| 239 | m_muxer->EndStream(m_stream->index); |
| 240 | |
| 241 | } |