<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::compartments::InCompartment;
use crate::document_loader::{LoadBlocker, LoadType};
use crate::dom::attr::Attr;
use crate::dom::audiotrack::AudioTrack;
use crate::dom::audiotracklist::AudioTrackList;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementConstants;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::{
    MediaStreamOrBlob, VideoTrackOrAudioTrackOrTextTrack,
};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob;
use crate::dom::document::Document;
use crate::dom::element::{
    cors_setting_for_element, reflect_cross_origin_attribute, set_cross_origin_attribute,
};
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
use crate::dom::mediastream::MediaStream;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::trackevent::TrackEvent;
use crate::dom::url::URL;
use crate::dom::videotrack::VideoTrack;
use crate::dom::videotracklist::VideoTrackList;
use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller;
use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use headers::{ContentLength, ContentRange, HeaderMapExt};
use html5ever::{LocalName, Prefix};
use http::header::{self, HeaderMap, HeaderValue};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::image::base::Image;
use net_traits::image_cache::ImageResponse;
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode};
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData;
use servo_config::pref;
use servo_media::player::frame::{Frame, FrameRenderer};
use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, StreamType};
use servo_media::{ServoMedia, SupportsMediaType};
use servo_url::ServoUrl;
use std::cell::Cell;
use std::collections::VecDeque;
use std::f64;
use std::mem;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use time::{self, Duration, Timespec};
use webrender_api::{ImageData, ImageDescriptor, ImageFormat, ImageKey, RenderApi};
use webrender_api::{RenderApiSender, Transaction};

pub struct MediaFrameRenderer {
    api: RenderApi,
    current_frame: Option<(ImageKey, i32, i32)>,
    old_frame: Option<ImageKey>,
    very_old_frame: Option<ImageKey>,
}

impl MediaFrameRenderer {
    fn new(render_api_sender: RenderApiSender) -> Self {
        Self {
            api: render_api_sender.create_api(),
            current_frame: None,
            old_frame: None,
            very_old_frame: None,
        }
    }

    fn render_poster_frame(&mut self, image: Arc<Image>) {
        if let Some(image_id) = image.id {
            self.current_frame = Some((image_id, image.width as i32, image.height as i32));
        }
    }
}

impl FrameRenderer for MediaFrameRenderer {
    fn render(&mut self, frame: Frame) {
        let descriptor = ImageDescriptor::new(
            frame.get_width(),
            frame.get_height(),
            ImageFormat::BGRA8,
            false,
            false,
        );

        let mut txn = Transaction::new();

        let image_data = ImageData::Raw(frame.get_data());

        if let Some(old_image_key) = mem::replace(&mut self.very_old_frame, self.old_frame.take()) {
            txn.delete_image(old_image_key);
        }

        match self.current_frame {
            Some((ref image_key, ref mut width, ref mut height))
                if *width == frame.get_width() && *height == frame.get_height() =>
            {
                txn.update_image(
                    *image_key,
                    descriptor,
                    image_data,
                    &webrender_api::DirtyRect::All,
                );

                if let Some(old_image_key) = self.old_frame.take() {
                    txn.delete_image(old_image_key);
                }
            }
            Some((ref mut image_key, ref mut width, ref mut height)) => {
                self.old_frame = Some(*image_key);

                let new_image_key = self.api.generate_image_key();
                txn.add_image(new_image_key, descriptor, image_data, None);
                *image_key = new_image_key;
                *width = frame.get_width();
                *height = frame.get_height();
            },
            None => {
                let image_key = self.api.generate_image_key();
                txn.add_image(image_key, descriptor, image_data, None);
                self.current_frame = Some((image_key, frame.get_width(), frame.get_height()));
            },
        }
        self.api.update_resources(txn.resource_updates);
    }
}

#[must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum SrcObject {
    MediaStream(Dom<MediaStream>),
    Blob(Dom<Blob>),
}

impl From<MediaStreamOrBlob> for SrcObject {
    #[allow(unrooted_must_root)]<commit_msg>Ignore frame if it is a GL texture<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::compartments::InCompartment;
use crate::document_loader::{LoadBlocker, LoadType};
use crate::dom::attr::Attr;
use crate::dom::audiotrack::AudioTrack;
use crate::dom::audiotracklist::AudioTrackList;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementConstants;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::{
    MediaStreamOrBlob, VideoTrackOrAudioTrackOrTextTrack,
};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob;
use crate::dom::document::Document;
use crate::dom::element::{
    cors_setting_for_element, reflect_cross_origin_attribute, set_cross_origin_attribute,
};
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
use crate::dom::mediastream::MediaStream;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::trackevent::TrackEvent;
use crate::dom::url::URL;
use crate::dom::videotrack::VideoTrack;
use crate::dom::videotracklist::VideoTrackList;
use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller;
use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use headers::{ContentLength, ContentRange, HeaderMapExt};
use html5ever::{LocalName, Prefix};
use http::header::{self, HeaderMap, HeaderValue};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::image::base::Image;
use net_traits::image_cache::ImageResponse;
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode};
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData;
use servo_config::pref;
use servo_media::player::frame::{Frame, FrameRenderer};
use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, StreamType};
use servo_media::{ServoMedia, SupportsMediaType};
use servo_url::ServoUrl;
use std::cell::Cell;
use std::collections::VecDeque;
use std::f64;
use std::mem;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use time::{self, Duration, Timespec};
//use webrender_api::{ExternalImageData, ExternalImageId, ExternalImageType, TextureTarget};
use webrender_api::{ImageData, ImageDescriptor, ImageFormat, ImageKey, RenderApi};
use webrender_api::{RenderApiSender, Transaction};

pub struct MediaFrameRenderer {
    api: RenderApi,
    current_frame: Option<(ImageKey, i32, i32)>,
    old_frame: Option<ImageKey>,
    very_old_frame: Option<ImageKey>,
}

impl MediaFrameRenderer {
    fn new(render_api_sender: RenderApiSender) -> Self {
        Self {
            api: render_api_sender.create_api(),
            current_frame: None,
            old_frame: None,
            very_old_frame: None,
        }
    }

    fn render_poster_frame(&mut self, image: Arc<Image>) {
        if let Some(image_id) = image.id {
            self.current_frame = Some((image_id, image.width as i32, image.height as i32));
        }
    }
}

impl FrameRenderer for MediaFrameRenderer {
    fn render(&mut self, frame: Frame) {
        let mut txn = Transaction::new();

        if let Some(old_image_key) = mem::replace(&mut self.very_old_frame, self.old_frame.take()) {
            txn.delete_image(old_image_key);
        }

        let descriptor = ImageDescriptor::new(
            frame.get_width(),
            frame.get_height(),
            ImageFormat::BGRA8,
            false,
            false,
        );

        match self.current_frame {
            Some((ref image_key, ref mut width, ref mut height))
                if *width == frame.get_width() && *height == frame.get_height() =>
            {
                if !frame.is_gl_texture() {
                    txn.update_image(
                        *image_key,
                        descriptor,
                        ImageData::Raw(frame.get_data()),
                        &webrender_api::DirtyRect::All,
                    );
                }

                if let Some(old_image_key) = self.old_frame.take() {
                    txn.delete_image(old_image_key);
                }
            }
            Some((ref mut image_key, ref mut width, ref mut height)) => {
                self.old_frame = Some(*image_key);

                let new_image_key = self.api.generate_image_key();

                if !frame.is_gl_texture() {
                    txn.add_image(
                        new_image_key,
                        descriptor,
                        ImageData::Raw(frame.get_data()),
                        None,
                    );
                } else {
                    // txn.add_image(
                    //     new_image_key,
                    //     descriptor,
                    //     ImageData::External(ExternalImageData {
                    //         id: ExternalImageId(0), // let's try to fool webgl
                    //         channel_index: 0,
                    //         image_type: ExternalImageType::TextureHandle(TextureTarget::Default),
                    //     }),
                    //     None,
                    // );
                }

                /* update current_frame */
                *image_key = new_image_key;
                *width = frame.get_width();
                *height = frame.get_height();
            },
            None => {
                let image_key = self.api.generate_image_key();

                if !frame.is_gl_texture() {
                    txn.add_image(
                        image_key,
                        descriptor,
                        ImageData::Raw(frame.get_data()),
                        None,
                    );
                } else {
                    // txn.add_image(
                    //     image_key,
                    //     descriptor,
                    //     ImageData::External(ExternalImageData {
                    //         id: ExternalImageId(0), // let's try to fool webgl
                    //         channel_index: 0,
                    //         image_type: ExternalImageType::TextureHandle(TextureTarget::Default),
                    //     }),
                    //     None,
                    // );
                }

                self.current_frame = Some((image_key, frame.get_width(), frame.get_height()));
            },
        }
        self.api.update_resources(txn.resource_updates);
    }
}

#[must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum SrcObject {
    MediaStream(Dom<MediaStream>),
    Blob(Dom<Blob>),
}

impl From<MediaStreamOrBlob> for SrcObject {
    #[allow(unrooted_must_root)]
{'fraction_non_alphanumeric': 0.13073871150576233, 'fraction_numerical': 0.0022671452862270923, 'mean_word_length': 3.561907497845447, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7647223', 'n_tokens_mistral': 4668, 'n_tokens_neox': 4593, 'n_words': 842}