HTMLVideoElement.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Bitmap.h>
  7. #include <LibWeb/Bindings/Intrinsics.h>
  8. #include <LibWeb/DOM/Document.h>
  9. #include <LibWeb/HTML/HTMLVideoElement.h>
  10. #include <LibWeb/HTML/VideoTrack.h>
  11. #include <LibWeb/Layout/VideoBox.h>
  12. #include <LibWeb/Platform/Timer.h>
  13. namespace Web::HTML {
  14. // FIXME: Determine a reasonable framerate somehow. For now, this is roughly 24fps.
  15. static constexpr int s_frame_delay_ms = 42;
  16. HTMLVideoElement::HTMLVideoElement(DOM::Document& document, DOM::QualifiedName qualified_name)
  17. : HTMLMediaElement(document, move(qualified_name))
  18. {
  19. }
  20. HTMLVideoElement::~HTMLVideoElement() = default;
  21. JS::ThrowCompletionOr<void> HTMLVideoElement::initialize(JS::Realm& realm)
  22. {
  23. MUST_OR_THROW_OOM(Base::initialize(realm));
  24. set_prototype(&Bindings::ensure_web_prototype<Bindings::HTMLVideoElementPrototype>(realm, "HTMLVideoElement"));
  25. return {};
  26. }
  27. void HTMLVideoElement::visit_edges(Cell::Visitor& visitor)
  28. {
  29. Base::visit_edges(visitor);
  30. visitor.visit(m_video_track);
  31. }
  32. JS::GCPtr<Layout::Node> HTMLVideoElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
  33. {
  34. return heap().allocate_without_realm<Layout::VideoBox>(document(), *this, move(style));
  35. }
  36. Layout::VideoBox* HTMLVideoElement::layout_node()
  37. {
  38. return static_cast<Layout::VideoBox*>(Node::layout_node());
  39. }
  40. Layout::VideoBox const* HTMLVideoElement::layout_node() const
  41. {
  42. return static_cast<Layout::VideoBox const*>(Node::layout_node());
  43. }
  44. // https://html.spec.whatwg.org/multipage/media.html#dom-video-videowidth
  45. u32 HTMLVideoElement::video_width() const
  46. {
  47. // The videoWidth IDL attribute must return the intrinsic width of the video in CSS pixels. The videoHeight IDL
  48. // attribute must return the intrinsic height of the video in CSS pixels. If the element's readyState attribute
  49. // is HAVE_NOTHING, then the attributes must return 0.
  50. if (ready_state() == ReadyState::HaveNothing)
  51. return 0;
  52. return m_video_width;
  53. }
  54. // https://html.spec.whatwg.org/multipage/media.html#dom-video-videoheight
  55. u32 HTMLVideoElement::video_height() const
  56. {
  57. // The videoWidth IDL attribute must return the intrinsic width of the video in CSS pixels. The videoHeight IDL
  58. // attribute must return the intrinsic height of the video in CSS pixels. If the element's readyState attribute
  59. // is HAVE_NOTHING, then the attributes must return 0.
  60. if (ready_state() == ReadyState::HaveNothing)
  61. return 0;
  62. return m_video_height;
  63. }
  64. void HTMLVideoElement::set_video_track(JS::GCPtr<HTML::VideoTrack> video_track)
  65. {
  66. set_needs_style_update(true);
  67. document().set_needs_layout();
  68. if (m_video_timer)
  69. m_video_timer->stop();
  70. m_video_track = video_track;
  71. if (!m_video_track)
  72. return;
  73. if (!m_video_timer) {
  74. m_video_timer = Platform::Timer::create_repeating(s_frame_delay_ms, [this]() {
  75. if (auto frame = m_video_track->next_frame())
  76. m_current_frame = move(frame);
  77. else
  78. m_video_timer->stop();
  79. layout_node()->set_needs_display();
  80. });
  81. }
  82. m_video_timer->start();
  83. }
  84. }