diff --git a/src/add-ons/media/plugins/Jamfile b/src/add-ons/media/plugins/Jamfile index fff565baf0..00a32d7408 100644 --- a/src/add-ons/media/plugins/Jamfile +++ b/src/add-ons/media/plugins/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons media plugins ; SubInclude HAIKU_TOP src add-ons media plugins ape_reader ; SubInclude HAIKU_TOP src add-ons media plugins au_reader ; +SubInclude HAIKU_TOP src add-ons media plugins dvd_streamer ; SubInclude HAIKU_TOP src add-ons media plugins ffmpeg ; SubInclude HAIKU_TOP src add-ons media plugins http_streamer ; SubInclude HAIKU_TOP src add-ons media plugins raw_decoder ; diff --git a/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.cpp b/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.cpp new file mode 100644 index 0000000000..f4786b1c50 --- /dev/null +++ b/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.cpp @@ -0,0 +1,253 @@ +/* + * Copyright 2019, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "DVDMediaIO.h" + +#include +#include +#include +#include +#include +#include + +#include "MediaDebug.h" + +using namespace BCodecKit; + + +#define DVD_READ_CACHE 1 + +#define DEFAULT_LANGUAGE "en" + + +DVDMediaIO::DVDMediaIO(const char* path) + : + BAdapterIO( + B_MEDIA_STREAMING | B_MEDIA_SEEKABLE, + B_INFINITE_TIMEOUT), + fPath(path), + fLoopThread(-1), + fExit(false) +{ + fBuffer = (uint8_t*) malloc(DVD_VIDEO_LB_LEN); +} + + +DVDMediaIO::~DVDMediaIO() +{ + fExit = true; + + status_t status; + if (fLoopThread != -1) + wait_for_thread(fLoopThread, &status); + + free(fBuffer); +} + + +ssize_t +DVDMediaIO::WriteAt(off_t position, const void* buffer, size_t size) +{ + return B_NOT_SUPPORTED; +} + + +status_t +DVDMediaIO::SetSize(off_t size) +{ + return B_NOT_SUPPORTED; +} + + +status_t +DVDMediaIO::Open() +{ + fInputAdapter = BuildInputAdapter(); + + if (dvdnav_open(&fDvdNav, fPath) != DVDNAV_STATUS_OK) { + TRACE("DVDMediaIO::Open() dvdnav_open error\n"); + return B_ERROR; + } + + // read ahead cache usage + if (dvdnav_set_readahead_flag(fDvdNav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { + TRACE("DVDMediaIO::Open() dvdnav_set_readahead_flag error: %s\n", + dvdnav_err_to_string(fDvdNav)); + return B_ERROR; + } + + // set language + if (dvdnav_menu_language_select(fDvdNav, DEFAULT_LANGUAGE) != DVDNAV_STATUS_OK || + dvdnav_audio_language_select(fDvdNav, DEFAULT_LANGUAGE) != DVDNAV_STATUS_OK || + dvdnav_spu_language_select(fDvdNav, DEFAULT_LANGUAGE) != DVDNAV_STATUS_OK) { + TRACE("DVDMediaIO::Open() setting languages error: %s\n", + dvdnav_err_to_string(fDvdNav)); + return B_ERROR; + } + + // set the PGC positioning flag + if (dvdnav_set_PGC_positioning_flag(fDvdNav, 1) != DVDNAV_STATUS_OK) { + TRACE("DVDMediaIO::Open() dvdnav_set_PGC_positioning_flag error: %s\n", + dvdnav_err_to_string(fDvdNav)); + return 2; + } + + fLoopThread = spawn_thread(_LoopThread, "two and two are five", + B_NORMAL_PRIORITY, this); + + if (fLoopThread <= 0 || resume_thread(fLoopThread) != B_OK) + return B_ERROR; + + return B_OK; +} + + +int32 +DVDMediaIO::_LoopThread(void* data) +{ + static_cast(data)->LoopThread(); + return 0; +} + + +void +DVDMediaIO::LoopThread() +{ + while (!fExit) { + int err; + int event; + int len; + +#if DVD_READ_CACHE + err = dvdnav_get_next_cache_block(fDvdNav, &fBuffer, &event, &len); +#else + err = dvdnav_get_next_block(fDvdNav, fBuffer, &event, &len); +#endif + + if (err == DVDNAV_STATUS_ERR) { + TRACE("DVDMediaIO::LoopThread(): Error getting next block: %s\n", + dvdnav_err_to_string(fDvdNav)); + continue; + } + + HandleDVDEvent(event, len); + +#if DVD_READ_CACHE + dvdnav_free_cache_block(fDvdNav, fBuffer); +#endif + } + + if (dvdnav_close(fDvdNav) != DVDNAV_STATUS_OK) { + TRACE("DVDMediaIO::LoopThread() dvdnav_close error: %s\n", + dvdnav_err_to_string(fDvdNav)); + } + fLoopThread = -1; +} + + +void +DVDMediaIO::HandleDVDEvent(int event, int len) +{ + switch (event) { + case DVDNAV_BLOCK_OK: + fInputAdapter->Write(fBuffer, len); + break; + + case DVDNAV_NOP: + break; + + case DVDNAV_STILL_FRAME: + { + dvdnav_still_event_t* still_event + = (dvdnav_still_event_t*) fBuffer; + if (still_event->length < 0xff) { + TRACE("DVDMediaIO::HandleDVDEvent: Skipped %d " + "seconds of still frame\n", + still_event->length); + } else { + TRACE("DVDMediaIO::HandleDVDEvent: Skipped " + "indefinite length still frame\n"); + } + dvdnav_still_skip(fDvdNav); + break; + } + + case DVDNAV_WAIT: + TRACE("DVDMediaIO::HandleDVDEvent: Skipping wait condition\n"); + dvdnav_wait_skip(fDvdNav); + break; + + case DVDNAV_SPU_CLUT_CHANGE: + break; + + case DVDNAV_SPU_STREAM_CHANGE: + break; + + case DVDNAV_AUDIO_STREAM_CHANGE: + break; + + case DVDNAV_HIGHLIGHT: + { + dvdnav_highlight_event_t* highlight_event + = (dvdnav_highlight_event_t*) fBuffer; + TRACE("DVDMediaIO::HandleDVDEvent: Button: %d\n", + highlight_event->buttonN); + break; + } + + case DVDNAV_VTS_CHANGE: + break; + + case DVDNAV_CELL_CHANGE: + { + int32_t title = 0, chapter = 0; + uint32_t pos, len; + + dvdnav_current_title_info(fDvdNav, &title, &chapter); + dvdnav_get_position(fDvdNav, &pos, &len); + TRACE("DVDMediaIO::HandleDVDEvent: Cell: Title %d, Chapter %d\n", + tt, ptt); + TRACE("DVDMediaIO::HandleDVDEvent: At position %.0f%% inside " + "the feature\n", 100 * (double)pos / (double)len); + break; + } + + case DVDNAV_NAV_PACKET: + break; + + case DVDNAV_HOP_CHANNEL: + break; + + case DVDNAV_STOP: + fExit = true; + break; + + default: + TRACE("DVDMediaIO::HandleDVDEvent: unknown event (%i)\n", + event); + fExit = true; + break; + } +} + + +status_t +DVDMediaIO::SeekRequested(off_t position) +{ + dvdnav_sector_search(fDvdNav, position, SEEK_SET); + return B_OK; +} + + +//void +//DVDMediaIO::MouseMoved() +//{ + // if Mouse moved + // dvdnav_mouse_select(fDvdNav, pci, x, y); + // else button pressed + // update button + // dvdnav_mouse_activate(fDvdNav, pci, x, y); +//} diff --git a/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.h b/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.h new file mode 100644 index 0000000000..af402cea8b --- /dev/null +++ b/src/add-ons/media/plugins/dvd_streamer/DVDMediaIO.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _DVD_MEDIA_IO_H +#define _DVD_MEDIA_IO_H + + +#include +#include + +#include + + +using BCodecKit::BAdapterIO; +using BCodecKit::BInputAdapter; + + +class DVDMediaIO : public BAdapterIO +{ +public: + DVDMediaIO(const char* path); + virtual ~DVDMediaIO(); + + virtual ssize_t WriteAt(off_t position, + const void* buffer, + size_t size); + + virtual status_t SetSize(off_t size); + + virtual status_t Open(); + + void LoopThread(); + + virtual status_t SeekRequested(off_t position); + + void HandleDVDEvent(int event, int len); + +private: + static int32 _LoopThread(void* data); + + const char* fPath; + + thread_id fLoopThread; + bool fExit; + + BInputAdapter* fInputAdapter; + + dvdnav_t* fDvdNav; + uint8_t* fBuffer; +}; + + +#endif diff --git a/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.cpp b/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.cpp new file mode 100644 index 0000000000..a27222c476 --- /dev/null +++ b/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2019, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "DVDStreamerPlugin.h" + +#include "DVDMediaIO.h" + + +B_DECLARE_CODEC_KIT_PLUGIN( + DVDStreamerPlugin, + "dvd_streamer", + B_CODEC_KIT_PLUGIN_VERSION +); + + +DVDStreamer::DVDStreamer() + : + BStreamer() +{ +} + + +DVDStreamer::~DVDStreamer() +{ +} + + +status_t +DVDStreamer::Sniff(const BUrl& url, BDataIO** source) +{ + BString path = url.UrlString(); + BString protocol = url.Protocol(); + if (protocol == "dvd") { + path = path.RemoveFirst("dvd://"); + } else if(protocol == "file") { + path = path.RemoveFirst("file://"); + } else + return B_UNSUPPORTED; + + DVDMediaIO* outSource = new DVDMediaIO(path); + status_t ret = outSource->Open(); + if (ret == B_OK) { + *source = outSource; + return B_OK; + } + delete outSource; + return ret; +} + + +BStreamer* +DVDStreamerPlugin::NewStreamer() +{ + return new DVDStreamer(); +} diff --git a/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.h b/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.h new file mode 100644 index 0000000000..b095028533 --- /dev/null +++ b/src/add-ons/media/plugins/dvd_streamer/DVDStreamerPlugin.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _DVD_STREAMER_PLUGIN_H +#define _DVD_STREAMER_PLUGIN_H + + +#include + +using BCodecKit::BStreamer; +using BCodecKit::BStreamerPlugin; + + +class DVDStreamer : public BStreamer +{ +public: + DVDStreamer(); + virtual ~DVDStreamer(); + + virtual status_t Sniff(const BUrl& url, BDataIO** source); +}; + + +class DVDStreamerPlugin : public BStreamerPlugin { +public: + virtual BStreamer* NewStreamer(); +}; + + +#endif // _DVD_STREAMER_PLUGIN_H diff --git a/src/add-ons/media/plugins/dvd_streamer/Jamfile b/src/add-ons/media/plugins/dvd_streamer/Jamfile new file mode 100644 index 0000000000..a9e939a5be --- /dev/null +++ b/src/add-ons/media/plugins/dvd_streamer/Jamfile @@ -0,0 +1,32 @@ +SubDir HAIKU_TOP src add-ons media plugins dvd_streamer ; + +# For MediaDebug.h +UsePrivateHeaders media ; + +local architectureObject ; +for architectureObject in [ MultiArchSubDirSetup ] { + on $(architectureObject) { + + UseBuildFeatureHeaders libdvdnav ; + UseBuildFeatureHeaders libdvdread ; + + Includes [ FGristFiles + DVDStreamerPlugin.cpp + DVDMediaIO.cpp ] + : [ BuildFeatureAttribute libdvdnav : headers ] ; + + Includes [ FGristFiles + DVDStreamerPlugin.cpp + DVDMediaIO.cpp ] + : [ BuildFeatureAttribute libdvdread : headers ] ; + + Addon [ MultiArchDefaultGristFiles dvd_streamer ] : + DVDStreamerPlugin.cpp + DVDMediaIO.cpp + : + [ BuildFeatureAttribute libdvdnav : libraries ] + be codec shared + [ TargetLibstdc++ ] [ TargetLibsupc++ ] + ; + } +}