diff options
Diffstat (limited to 'modules/webm/video_stream_webm.cpp')
-rw-r--r-- | modules/webm/video_stream_webm.cpp | 150 |
1 files changed, 51 insertions, 99 deletions
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index ca78d664f7..832e14d91a 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -48,41 +48,39 @@ #include <mkvparser/mkvparser.h> class MkvReader : public mkvparser::IMkvReader { - public: MkvReader(const String &p_file) { - file = FileAccess::open(p_file, FileAccess::READ); ERR_FAIL_COND_MSG(!file, "Failed loading resource: '" + p_file + "'."); } ~MkvReader() { - - if (file) + if (file) { memdelete(file); + } } virtual int Read(long long pos, long len, unsigned char *buf) { - if (file) { - - if (file->get_position() != (size_t)pos) + if (file->get_position() != (size_t)pos) { file->seek(pos); - if (file->get_buffer(buf, len) == len) + } + if (file->get_buffer(buf, len) == len) { return 0; + } } return -1; } virtual int Length(long long *total, long long *available) { - if (file) { - const size_t len = file->get_len(); - if (total) + if (total) { *total = len; - if (available) + } + if (available) { *available = len; + } return 0; } return -1; @@ -95,47 +93,23 @@ private: /**/ VideoStreamPlaybackWebm::VideoStreamPlaybackWebm() : - audio_track(0), - webm(nullptr), - video(nullptr), - audio(nullptr), - video_frames(nullptr), - audio_frame(nullptr), - video_frames_pos(0), - video_frames_capacity(0), - num_decoded_samples(0), - samples_offset(-1), - mix_callback(nullptr), - mix_udata(nullptr), - playing(false), - paused(false), - delay_compensation(0.0), - time(0.0), - video_frame_delay(0.0), - video_pos(0.0), - texture(memnew(ImageTexture)), - pcm(nullptr) {} -VideoStreamPlaybackWebm::~VideoStreamPlaybackWebm() { + texture(memnew(ImageTexture)) {} +VideoStreamPlaybackWebm::~VideoStreamPlaybackWebm() { delete_pointers(); } bool VideoStreamPlaybackWebm::open_file(const String &p_file) { - file_name = p_file; webm = memnew(WebMDemuxer(new MkvReader(file_name), 0, audio_track)); if (webm->isOpen()) { - video = memnew(VPXDecoder(*webm, OS::get_singleton()->get_processor_count())); if (video->isOpen()) { - audio = memnew(OpusVorbisDecoder(*webm)); if (audio->isOpen()) { - audio_frame = memnew(WebMFrame); pcm = (float *)memalloc(sizeof(float) * audio->getBufferSamples() * webm->getChannels()); } else { - memdelete(audio); audio = nullptr; } @@ -157,9 +131,7 @@ bool VideoStreamPlaybackWebm::open_file(const String &p_file) { } void VideoStreamPlaybackWebm::stop() { - if (playing) { - delete_pointers(); pcm = nullptr; @@ -180,8 +152,8 @@ void VideoStreamPlaybackWebm::stop() { time = 0.0; playing = false; } -void VideoStreamPlaybackWebm::play() { +void VideoStreamPlaybackWebm::play() { stop(); delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms"); @@ -191,58 +163,52 @@ void VideoStreamPlaybackWebm::play() { } bool VideoStreamPlaybackWebm::is_playing() const { - return playing; } void VideoStreamPlaybackWebm::set_paused(bool p_paused) { - paused = p_paused; } -bool VideoStreamPlaybackWebm::is_paused() const { +bool VideoStreamPlaybackWebm::is_paused() const { return paused; } void VideoStreamPlaybackWebm::set_loop(bool p_enable) { - //Empty } -bool VideoStreamPlaybackWebm::has_loop() const { +bool VideoStreamPlaybackWebm::has_loop() const { return false; } float VideoStreamPlaybackWebm::get_length() const { - - if (webm) + if (webm) { return webm->getLength(); + } return 0.0f; } float VideoStreamPlaybackWebm::get_playback_position() const { - return video_pos; } -void VideoStreamPlaybackWebm::seek(float p_time) { +void VideoStreamPlaybackWebm::seek(float p_time) { //Not implemented } void VideoStreamPlaybackWebm::set_audio_track(int p_idx) { - audio_track = p_idx; } Ref<Texture2D> VideoStreamPlaybackWebm::get_texture() const { - return texture; } void VideoStreamPlaybackWebm::update(float p_delta) { - - if ((!playing || paused) || !video) + if ((!playing || paused) || !video) { return; + } time += p_delta; @@ -253,16 +219,13 @@ void VideoStreamPlaybackWebm::update(float p_delta) { bool audio_buffer_full = false; if (samples_offset > -1) { - //Mix remaining samples const int to_read = num_decoded_samples - samples_offset; const int mixed = mix_callback(mix_udata, pcm + samples_offset * webm->getChannels(), to_read); if (mixed != to_read) { - samples_offset += mixed; audio_buffer_full = true; } else { - samples_offset = -1; } } @@ -270,10 +233,8 @@ void VideoStreamPlaybackWebm::update(float p_delta) { const bool hasAudio = (audio && mix_callback); while ((hasAudio && !audio_buffer_full && !has_enough_video_frames()) || (!hasAudio && video_frames_pos == 0)) { - if (hasAudio && !audio_buffer_full && audio_frame->isValid() && audio->getPCMF(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) { - const int mixed = mix_callback(mix_udata, pcm, num_decoded_samples); if (mixed != num_decoded_samples) { @@ -284,42 +245,37 @@ void VideoStreamPlaybackWebm::update(float p_delta) { WebMFrame *video_frame; if (video_frames_pos >= video_frames_capacity) { - WebMFrame **video_frames_new = (WebMFrame **)memrealloc(video_frames, ++video_frames_capacity * sizeof(void *)); ERR_FAIL_COND(!video_frames_new); //Out of memory (video_frames = video_frames_new)[video_frames_capacity - 1] = memnew(WebMFrame); } video_frame = video_frames[video_frames_pos]; - if (!webm->readFrame(video_frame, audio_frame)) //This will invalidate frames + if (!webm->readFrame(video_frame, audio_frame)) { //This will invalidate frames break; //Can't demux, EOS? + } - if (video_frame->isValid()) + if (video_frame->isValid()) { ++video_frames_pos; + } }; bool video_frame_done = false; while (video_frames_pos > 0 && !video_frame_done) { - WebMFrame *video_frame = video_frames[0]; // It seems VPXDecoder::decode has to be executed even though we might skip this frame if (video->decode(*video_frame)) { - VPXDecoder::IMAGE_ERROR err; VPXDecoder::Image image; if (should_process(*video_frame)) { - if ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) { - if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) { - uint8_t *w = frame_data.ptrw(); bool converted = false; if (image.chromaShiftW == 0 && image.chromaShiftH == 0 && image.cs == VPX_CS_SRGB) { - uint8_t *wp = w; unsigned char *rRow = image.planes[2]; unsigned char *gRow = image.planes[0]; @@ -337,22 +293,18 @@ void VideoStreamPlaybackWebm::update(float p_delta) { } converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { - yuv420_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) { - yuv422_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) { - yuv444_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) { - //libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2] image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); //converted = true; } @@ -372,25 +324,27 @@ void VideoStreamPlaybackWebm::update(float p_delta) { video_frames[video_frames_pos] = video_frame; } - if (video_frames_pos == 0 && webm->isEOS()) + if (video_frames_pos == 0 && webm->isEOS()) { stop(); + } } void VideoStreamPlaybackWebm::set_mix_callback(VideoStreamPlayback::AudioMixCallback p_callback, void *p_userdata) { - mix_callback = p_callback; mix_udata = p_userdata; } -int VideoStreamPlaybackWebm::get_channels() const { - if (audio) +int VideoStreamPlaybackWebm::get_channels() const { + if (audio) { return webm->getChannels(); + } return 0; } -int VideoStreamPlaybackWebm::get_mix_rate() const { - if (audio) +int VideoStreamPlaybackWebm::get_mix_rate() const { + if (audio) { return webm->getSampleRate(); + } return 0; } @@ -415,52 +369,54 @@ bool VideoStreamPlaybackWebm::should_process(WebMFrame &video_frame) { } void VideoStreamPlaybackWebm::delete_pointers() { - - if (pcm) + if (pcm) { memfree(pcm); + } - if (audio_frame) + if (audio_frame) { memdelete(audio_frame); + } if (video_frames) { - for (int i = 0; i < video_frames_capacity; ++i) + for (int i = 0; i < video_frames_capacity; ++i) { memdelete(video_frames[i]); + } memfree(video_frames); } - if (video) + if (video) { memdelete(video); - if (audio) + } + if (audio) { memdelete(audio); + } - if (webm) + if (webm) { memdelete(webm); + } } /**/ -VideoStreamWebm::VideoStreamWebm() : - audio_track(0) {} +VideoStreamWebm::VideoStreamWebm() {} Ref<VideoStreamPlayback> VideoStreamWebm::instance_playback() { - Ref<VideoStreamPlaybackWebm> pb = memnew(VideoStreamPlaybackWebm); pb->set_audio_track(audio_track); - if (pb->open_file(file)) + if (pb->open_file(file)) { return pb; + } return nullptr; } void VideoStreamWebm::set_file(const String &p_file) { - file = p_file; } -String VideoStreamWebm::get_file() { +String VideoStreamWebm::get_file() { return file; } void VideoStreamWebm::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamWebm::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamWebm::get_file); @@ -468,14 +424,12 @@ void VideoStreamWebm::_bind_methods() { } void VideoStreamWebm::set_audio_track(int p_track) { - audio_track = p_track; } //////////// -RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { @@ -499,19 +453,17 @@ RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_origina } void ResourceFormatLoaderWebm::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("webm"); } bool ResourceFormatLoaderWebm::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "VideoStream"); } String ResourceFormatLoaderWebm::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "webm") + if (el == "webm") { return "VideoStreamWebm"; + } return ""; } |