Changeset 290653 in webkit
- Timestamp:
- Mar 1, 2022, 9:56:49 AM (5 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp (modified) (26 diffs)
-
WebProcess/GPU/webrtc/LibWebRTCCodecs.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r290646 r290653 1 2022-03-01 Youenn Fablet <youenn@apple.com> 2 3 Annotate LibWebRTC with thread safety macros 4 https://bugs.webkit.org/show_bug.cgi?id=237321 5 6 Reviewed by Eric Carlson. 7 8 LibWebRTCCodecs works with 3 threads and we add macros to make it clear where each thread is used: 9 - the main thread to get its GPU process connection (isMainRunLoop()). 10 - the libwebrtc thread where it gets orders to decode/encode frames (!isMainRunLoop()) 11 - the work queue thread where it is receiving encode/decode results (assertIsCurrent(workQueue())). 12 13 Rename m_encodersLock to m_encodersConnectionLock to make it clear this is about locking the encoder connection and not the encoder map. 14 Both decoder and encoder maps should only be touched on the workQueue thread. 15 16 Introduce encoderConnection/setEncoderConnection and decoderConnection/setDecoderConnection routines. 17 These methods are guarded by corresponding locks. 18 This requires adding some additional locks when accessing connections in workQueue thread. 19 Fix a potential issue when creating the encoder: we lock the encoderConnection lock earlier when setting the connection. 20 21 Covered by existing tests. 22 23 * WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp: 24 (WebKit::LibWebRTCCodecs::gpuProcessConnectionMayNoLongerBeNeeded): 25 (WebKit::LibWebRTCCodecs::createDecoder): 26 (WebKit::LibWebRTCCodecs::releaseDecoder): 27 (WebKit::LibWebRTCCodecs::decodeFrame): 28 (WebKit::LibWebRTCCodecs::registerDecodeFrameCallback): 29 (WebKit::LibWebRTCCodecs::failedDecoding): 30 (WebKit::LibWebRTCCodecs::completedDecoding): 31 (WebKit::LibWebRTCCodecs::completedDecodingCV): 32 (WebKit::LibWebRTCCodecs::createEncoder): 33 (WebKit::LibWebRTCCodecs::releaseEncoder): 34 (WebKit::LibWebRTCCodecs::initializeEncoder): 35 (WebKit::LibWebRTCCodecs::copySharedVideoFrame): 36 (WebKit::LibWebRTCCodecs::encodeFrame): 37 (WebKit::LibWebRTCCodecs::registerEncodeFrameCallback): 38 (WebKit::LibWebRTCCodecs::setEncodeRates): 39 (WebKit::LibWebRTCCodecs::completedEncoding): 40 (WebKit::LibWebRTCCodecs::gpuProcessConnectionDidClose): 41 (WebKit::LibWebRTCCodecs::encoderConnection): 42 (WebKit::LibWebRTCCodecs::setEncoderConnection): 43 (WebKit::LibWebRTCCodecs::decoderConnection): 44 (WebKit::LibWebRTCCodecs::setDecoderConnection): 45 (WebKit::copySharedVideoFrame): Deleted. 46 * WebProcess/GPU/webrtc/LibWebRTCCodecs.h: 47 (WebKit::LibWebRTCCodecs::workQueue const): 48 1 49 2022-03-01 Wenson Hsieh <wenson_hsieh@apple.com> 2 50 -
trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp
r290558 r290653 222 222 void LibWebRTCCodecs::gpuProcessConnectionMayNoLongerBeNeeded() 223 223 { 224 ASSERT(!isMainRunLoop()); 224 assertIsCurrent(workQueue()); 225 225 226 if (m_encoders.isEmpty() && m_decoders.isEmpty()) 226 227 m_needsGPUProcessConnection = false; … … 255 256 LibWebRTCCodecs::Decoder* LibWebRTCCodecs::createDecoder(Type type) 256 257 { 258 ASSERT(!isMainRunLoop()); 259 257 260 auto decoder = makeUnique<Decoder>(); 258 261 auto* result = decoder.get(); … … 261 264 262 265 ensureGPUProcessConnectionAndDispatchToThread([this, decoder = WTFMove(decoder)]() mutable { 266 assertIsCurrent(workQueue()); 267 263 268 Locker locker { m_connectionLock }; 264 decoder->connection = m_connection;265 269 createRemoteDecoder(*decoder, *m_connection, m_useRemoteFrames); 270 setDecoderConnection(*decoder, m_connection.get()); 266 271 267 272 auto decoderIdentifier = decoder->identifier; … … 274 279 int32_t LibWebRTCCodecs::releaseDecoder(Decoder& decoder) 275 280 { 281 ASSERT(!isMainRunLoop()); 282 276 283 #if ASSERT_ENABLED 277 284 { … … 281 288 #endif 282 289 ensureGPUProcessConnectionAndDispatchToThread([this, decoderIdentifier = decoder.identifier] { 290 assertIsCurrent(workQueue()); 291 283 292 ASSERT(m_decoders.contains(decoderIdentifier)); 284 293 if (auto decoder = m_decoders.take(decoderIdentifier)) { 285 decoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0); 294 Locker locker { m_connectionLock }; 295 decoderConnection(*decoder)->send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0); 286 296 gpuProcessConnectionMayNoLongerBeNeeded(); 287 297 } … … 292 302 int32_t LibWebRTCCodecs::decodeFrame(Decoder& decoder, uint32_t timeStamp, const uint8_t* data, size_t size, uint16_t width, uint16_t height) 293 303 { 304 ASSERT(!isMainRunLoop()); 305 294 306 Locker locker { m_connectionLock }; 295 307 if (!decoder.connection || decoder.hasError) { … … 307 319 void LibWebRTCCodecs::registerDecodeFrameCallback(Decoder& decoder, void* decodedImageCallback) 308 320 { 321 ASSERT(!isMainRunLoop()); 322 309 323 Locker locker { decoder.decodedImageCallbackLock }; 310 324 decoder.decodedImageCallback = decodedImageCallback; … … 313 327 void LibWebRTCCodecs::failedDecoding(RTCDecoderIdentifier decoderIdentifier) 314 328 { 315 ASSERT(!isMainRunLoop());329 assertIsCurrent(workQueue()); 316 330 317 331 if (auto* decoder = m_decoders.get(decoderIdentifier)) … … 321 335 void LibWebRTCCodecs::completedDecoding(RTCDecoderIdentifier decoderIdentifier, uint32_t timeStamp, RemoteVideoFrameProxy::Properties&& properties) 322 336 { 323 ASSERT(!isMainRunLoop()); 337 assertIsCurrent(workQueue()); 338 324 339 // Adopt RemoteVideoFrameProxy::Properties to RemoteVideoFrameProxy instance before the early outs, so that the reference gets adopted. 325 340 // Typically RemoteVideoFrameProxy::Properties&& sent to destinations that are already removed need to be handled separately. … … 348 363 void LibWebRTCCodecs::completedDecodingCV(RTCDecoderIdentifier decoderIdentifier, uint32_t timeStamp, WebCore::RemoteVideoSample&& remoteSample) 349 364 { 350 ASSERT(!isMainRunLoop()); 365 assertIsCurrent(workQueue()); 366 351 367 // FIXME: Do error logging. 352 368 auto* decoder = m_decoders.get(decoderIdentifier); … … 394 410 LibWebRTCCodecs::Encoder* LibWebRTCCodecs::createEncoder(Type type, const std::map<std::string, std::string>& formatParameters) 395 411 { 412 ASSERT(!isMainRunLoop()); 413 396 414 auto encoder = makeUnique<Encoder>(); 397 415 auto* result = encoder.get(); … … 404 422 405 423 ensureGPUProcessConnectionAndDispatchToThread([this, encoder = WTFMove(encoder), type, parameters = WTFMove(parameters)]() mutable { 424 assertIsCurrent(workQueue()); 425 426 auto connection = [&]() -> Ref<IPC::Connection> { 427 Locker locker { m_connectionLock }; 428 return *m_connection; 429 }(); 430 406 431 { 407 Locker locker { m_connectionLock }; 408 encoder->connection = m_connection; 432 Locker locker { m_encodersConnectionLock }; 433 connection->send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromCodecType(type), parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0); 434 setEncoderConnection(*encoder, connection.ptr()); 409 435 } 410 436 411 encoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromCodecType(type), parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0);412 437 encoder->parameters = WTFMove(parameters); 413 414 Locker locker { m_encodersLock };415 438 auto encoderIdentifier = encoder->identifier; 416 439 ASSERT(!m_encoders.contains(encoderIdentifier)); … … 422 445 int32_t LibWebRTCCodecs::releaseEncoder(Encoder& encoder) 423 446 { 447 ASSERT(!isMainRunLoop()); 448 424 449 #if ASSERT_ENABLED 425 450 { … … 429 454 #endif 430 455 ensureGPUProcessConnectionAndDispatchToThread([this, encoderIdentifier = encoder.identifier] { 431 Locker locker { m_encodersLock }; 456 assertIsCurrent(workQueue()); 457 432 458 ASSERT(m_encoders.contains(encoderIdentifier)); 433 459 auto encoder = m_encoders.take(encoderIdentifier); 434 encoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0); 460 461 Locker locker { m_encodersConnectionLock }; 462 encoderConnection(*encoder)->send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0); 463 435 464 gpuProcessConnectionMayNoLongerBeNeeded(); 436 465 }); … … 440 469 int32_t LibWebRTCCodecs::initializeEncoder(Encoder& encoder, uint16_t width, uint16_t height, unsigned startBitRate, unsigned maxBitRate, unsigned minBitRate, uint32_t maxFrameRate) 441 470 { 471 ASSERT(!isMainRunLoop()); 472 442 473 ensureGPUProcessConnectionAndDispatchToThread([this, encoderIdentifier = encoder.identifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate]() mutable { 474 assertIsCurrent(workQueue()); 475 443 476 auto* encoder = m_encoders.get(encoderIdentifier); 444 477 encoder->initializationData = EncoderInitializationData { width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }; 445 encoder->connection->send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoderIdentifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }, 0); 478 479 Locker locker { m_encodersConnectionLock }; 480 encoderConnection(*encoder)->send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoderIdentifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }, 0); 446 481 }); 447 482 return 0; … … 449 484 450 485 template<typename Buffer> 451 bool copySharedVideoFrame(LibWebRTCCodecs::Encoder& encoder, Buffer&& frameBuffer)486 bool LibWebRTCCodecs::copySharedVideoFrame(LibWebRTCCodecs::Encoder& encoder, IPC::Connection& connection, Buffer&& frameBuffer) 452 487 { 453 488 return encoder.sharedVideoFrameWriter.write(frameBuffer, 454 [&](auto& semaphore) { encoder.connection->send(Messages::LibWebRTCCodecsProxy::SetSharedVideoFrameSemaphore { encoder.identifier, semaphore }, 0); },455 [&](auto& handle) { encoder.connection->send(Messages::LibWebRTCCodecsProxy::SetSharedVideoFrameMemory { encoder.identifier, handle }, 0); }489 [&](auto& semaphore) { connection.send(Messages::LibWebRTCCodecsProxy::SetSharedVideoFrameSemaphore { encoder.identifier, semaphore }, 0); }, 490 [&](auto& handle) { connection.send(Messages::LibWebRTCCodecsProxy::SetSharedVideoFrameMemory { encoder.identifier, handle }, 0); } 456 491 ); 457 492 } … … 459 494 int32_t LibWebRTCCodecs::encodeFrame(Encoder& encoder, const webrtc::VideoFrame& frame, bool shouldEncodeAsKeyFrame) 460 495 { 461 Locker locker { m_encodersLock }; 462 if (!encoder.connection) 496 ASSERT(!isMainRunLoop()); 497 498 Locker locker { m_encodersConnectionLock }; 499 auto* connection = encoderConnection(encoder); 500 if (!connection) 463 501 return WEBRTC_VIDEO_CODEC_ERROR; 464 502 … … 475 513 if (!buffer) { 476 514 // buffer is not native, we need to copy to shared video frame. 477 if (!copySharedVideoFrame(encoder, frame))515 if (!copySharedVideoFrame(encoder, *connection, frame)) 478 516 return WEBRTC_VIDEO_CODEC_ERROR; 479 517 } … … 483 521 if (buffer && !sample->surface()) { 484 522 // buffer is not IOSurface, we need to copy to shared video frame. 485 if (!copySharedVideoFrame(encoder, buffer.get()))523 if (!copySharedVideoFrame(encoder, *connection, buffer.get())) 486 524 return WEBRTC_VIDEO_CODEC_ERROR; 487 525 } 488 526 489 encoder.connection->send(Messages::LibWebRTCCodecsProxy::EncodeFrame { encoder.identifier, *sample, frame.timestamp(), shouldEncodeAsKeyFrame, remoteVideoFrameReadReference }, 0);527 connection->send(Messages::LibWebRTCCodecsProxy::EncodeFrame { encoder.identifier, *sample, frame.timestamp(), shouldEncodeAsKeyFrame, remoteVideoFrameReadReference }, 0); 490 528 return WEBRTC_VIDEO_CODEC_OK; 491 529 } … … 493 531 void LibWebRTCCodecs::registerEncodeFrameCallback(Encoder& encoder, void* encodedImageCallback) 494 532 { 533 ASSERT(!isMainRunLoop()); 534 495 535 Locker locker { encoder.encodedImageCallbackLock }; 496 536 … … 500 540 void LibWebRTCCodecs::setEncodeRates(Encoder& encoder, uint32_t bitRate, uint32_t frameRate) 501 541 { 502 Locker locker { m_encodersLock }; 503 504 if (!encoder.connection) { 542 ASSERT(!isMainRunLoop()); 543 544 Locker locker { m_encodersConnectionLock }; 545 546 auto* connection = encoderConnection(encoder); 547 if (!connection) { 505 548 callOnMainRunLoop([encoderIdentifier = encoder.identifier, bitRate, frameRate] { 506 549 WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoderIdentifier, bitRate, frameRate }, 0); … … 508 551 return; 509 552 } 510 encoder.connection->send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoder.identifier, bitRate, frameRate }, 0);553 connection->send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoder.identifier, bitRate, frameRate }, 0); 511 554 } 512 555 513 556 void LibWebRTCCodecs::completedEncoding(RTCEncoderIdentifier identifier, IPC::DataReference&& data, const webrtc::WebKitEncodedFrameInfo& info) 514 557 { 515 ASSERT(!isMainRunLoop());558 assertIsCurrent(workQueue()); 516 559 517 560 // FIXME: Do error logging. … … 554 597 { 555 598 ASSERT(isMainRunLoop()); 599 556 600 Locker locker { m_connectionLock }; 557 601 std::exchange(m_connection, nullptr)->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName()); … … 561 605 ensureGPUProcessConnectionOnMainThreadWithLock(); 562 606 dispatchToThread([this, connection = m_connection]() { 563 for (auto& decoder : m_decoders.values()) { 564 createRemoteDecoder(*decoder, *connection, m_useRemoteFrames); 565 decoder->connection = connection.get(); 607 assertIsCurrent(workQueue()); 608 { 609 Locker locker { m_connectionLock }; 610 for (auto& decoder : m_decoders.values()) { 611 createRemoteDecoder(*decoder, *connection, m_useRemoteFrames); 612 setDecoderConnection(*decoder, connection.get()); 613 } 566 614 } 567 615 … … 570 618 encoder->sharedVideoFrameWriter.disable(); 571 619 572 Locker locker { m_encoders Lock };620 Locker locker { m_encodersConnectionLock }; 573 621 for (auto& encoder : m_encoders.values()) { 574 622 connection->send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromWebRTCCodecType(encoder->codecType), encoder->parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0); 575 623 if (encoder->initializationData) 576 624 connection->send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoder->identifier, encoder->initializationData->width, encoder->initializationData->height, encoder->initializationData->startBitRate, encoder->initializationData->maxBitRate, encoder->initializationData->minBitRate, encoder->initializationData->maxFrameRate }, 0); 577 encoder->connection = connection.get();625 setEncoderConnection(*encoder, connection.get()); 578 626 encoder->sharedVideoFrameWriter = { }; 579 627 } … … 590 638 } 591 639 640 IPC::Connection* LibWebRTCCodecs::encoderConnection(Encoder& encoder) 641 { 642 return encoder.connection.get(); 643 } 644 645 void LibWebRTCCodecs::setEncoderConnection(Encoder& encoder, RefPtr<IPC::Connection>&& connection) 646 { 647 encoder.connection = WTFMove(connection); 648 } 649 650 IPC::Connection* LibWebRTCCodecs::decoderConnection(Decoder& decoder) 651 { 652 return decoder.connection.get(); 653 } 654 655 void LibWebRTCCodecs::setDecoderConnection(Decoder& decoder, RefPtr<IPC::Connection>&& connection) 656 { 657 decoder.connection = WTFMove(connection); 658 } 659 592 660 } 593 661 -
trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h
r290555 r290653 145 145 void gpuProcessConnectionDidClose(GPUProcessConnection&); 146 146 147 IPC::Connection* encoderConnection(Encoder&) WTF_REQUIRES_LOCK(m_encodersConnectionLock); 148 void setEncoderConnection(Encoder&, RefPtr<IPC::Connection>&&) WTF_REQUIRES_LOCK(m_encodersConnectionLock); 149 IPC::Connection* decoderConnection(Decoder&) WTF_REQUIRES_LOCK(m_connectionLock); 150 void setDecoderConnection(Decoder&, RefPtr<IPC::Connection>&&) WTF_REQUIRES_LOCK(m_connectionLock); 151 152 template<typename Buffer> bool copySharedVideoFrame(LibWebRTCCodecs::Encoder&, IPC::Connection&, Buffer&&); 153 WorkQueue& workQueue() const { return m_queue; } 154 147 155 private: 148 HashMap<RTCDecoderIdentifier, std::unique_ptr<Decoder>> m_decoders; 149 HashSet<RTCDecoderIdentifier> m_decodingErrors; 156 HashMap<RTCDecoderIdentifier, std::unique_ptr<Decoder>> m_decoders WTF_GUARDED_BY_CAPABILITY(workQueue()); 150 157 151 Lock m_encoders Lock;152 HashMap<RTCEncoderIdentifier, std::unique_ptr<Encoder>> m_encoders ;158 Lock m_encodersConnectionLock; 159 HashMap<RTCEncoderIdentifier, std::unique_ptr<Encoder>> m_encoders WTF_GUARDED_BY_CAPABILITY(workQueue()); 153 160 154 161 std::atomic<bool> m_needsGPUProcessConnection;
Note:
See TracChangeset
for help on using the changeset viewer.