| 248 | } |
| 249 | |
| 250 | IDataStream* Transcoder::TranscodeAndWait( |
| 251 | Context& context, |
| 252 | IEncoder* encoder, |
| 253 | const std::string& uri, |
| 254 | size_t bitrate, |
| 255 | const std::string& format) |
| 256 | { |
| 257 | /* the caller can specify an encoder; if it is not specified, go ahead and |
| 258 | create one here */ |
| 259 | if (!encoder) { |
| 260 | encoder = getEncoder(context, format); |
| 261 | if (!encoder) { |
| 262 | return nullptr; |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | std::string expectedFilename, tempFilename; |
| 267 | getTempAndFinalFilename(context, uri, bitrate, format, tempFilename, expectedFilename); |
| 268 | |
| 269 | /* already exists? */ |
| 270 | if (fs::exists(fs::u8path(expectedFilename))) { |
| 271 | touch(expectedFilename); |
| 272 | return context.environment->GetDataStream(expectedFilename.c_str(), OpenFlags::Read); |
| 273 | } |
| 274 | |
| 275 | IStreamingEncoder* audioStreamEncoder = dynamic_cast<IStreamingEncoder*>(encoder); |
| 276 | if (audioStreamEncoder) { |
| 277 | TranscodingAudioDataStream* transcoderStream = new TranscodingAudioDataStream( |
| 278 | context, audioStreamEncoder, uri, tempFilename, expectedFilename, bitrate, format); |
| 279 | |
| 280 | /* transcoders with a negative length have an indeterminate duration, so |
| 281 | we disallow waiting for them because they may never finish */ |
| 282 | if (transcoderStream->Length() < 0) { |
| 283 | transcoderStream->Release(); |
| 284 | delete transcoderStream; |
| 285 | return nullptr; |
| 286 | } |
| 287 | |
| 288 | char buffer[8192]; |
| 289 | while (!transcoderStream->Eof()) { |
| 290 | transcoderStream->Read(buffer, sizeof(buffer)); |
| 291 | std::this_thread::yield(); |
| 292 | } |
| 293 | |
| 294 | transcoderStream->Release(); |
| 295 | PruneTranscodeCache(context); |
| 296 | return context.environment->GetDataStream(uri.c_str(), OpenFlags::Read); |
| 297 | } |
| 298 | else { |
| 299 | IBlockingEncoder* blockingEncoder = dynamic_cast<IBlockingEncoder*>(encoder); |
| 300 | if (blockingEncoder) { |
| 301 | bool alreadyTranscoding = false; |
| 302 | { |
| 303 | /* see if there's already a blocking transcoder running for the specified |
| 304 | uri. if there is, wait for it to complete. if there's not, add it to the |
| 305 | running set */ |
| 306 | std::unique_lock<std::mutex> lock(transcoderMutex); |
| 307 | alreadyTranscoding = runningBlockingTranscoders.find(uri) != runningBlockingTranscoders.end(); |
nothing calls this directly
no test coverage detected