560 Commits

Author SHA1 Message Date
GetAway
3ff02b06f2 ShowPicture: return boolean expression 2019-01-12 11:48:14 +01:00
Thilo Graf
da0d4290a3 version_hal: simplify methodes
adopt method names similar to cs name convention
2019-01-02 17:30:05 +01:00
Thilo Graf
9bd798def2 configure: remove config from separat include dir
Not really needed
2019-01-02 17:29:34 +01:00
Thilo Graf
3869c32e82 configure: add missing entry
build was broken
2019-01-01 21:03:12 +01:00
Thilo Graf
ed8e3743d5 version_hal.cpp/h: add methodes to get package data 2019-01-01 16:03:12 +01:00
Thilo Graf
bc9eca8588 configure: add additional config header
config.h was not usable with neutrino.
2018-12-31 11:21:41 +01:00
Thilo Graf
1e47a62926 .gitignore: ignore some unneeded config and local stuff
picked from mpx branch
2018-12-31 11:20:31 +01:00
Jacek Jendrzej
4fecdd558a fix generic compil 2018-12-01 12:35:02 +01:00
Jacek Jendrzej
2e8aa93895 add getFD 2018-02-17 13:28:03 +01:00
Jacek Jendrzej
8d6b3f71c0 add dumb functions for streaminfo2 compil 2017-12-13 17:26:57 +01:00
Jacek Jendrzej
2673ba0940 fix possible segfault 2017-12-07 11:39:27 +01:00
Jacek Jendrzej
78b3403303 fix generic compil 2017-12-07 11:13:28 +01:00
Jacek Jendrzej
dd01a95ddb Revert "remove unused"
This reverts commit 3f9525e42e.
2017-11-03 19:57:28 +01:00
Jacek Jendrzej
3f9525e42e remove unused 2017-11-03 19:01:09 +01:00
Jacek Jendrzej
a47c399a19 fix generic build 2017-11-03 18:27:35 +01:00
Thilo Graf
056db018ab version 0.2.0-generic-pc
for generic-pc
2017-11-02 20:26:37 +01:00
Thilo Graf
793ae7a605 version 1.0.0-mpx
hd51 support
2017-11-02 20:12:56 +01:00
Thilo Graf
29a96a35bd adjust .gitignore for untracked files 2017-11-02 20:11:56 +01:00
Thilo Graf
c723af9313 add default files 2017-11-02 20:11:18 +01:00
Thilo Graf
328c93fb0d add update script 2017-11-02 20:11:12 +01:00
Jacek Jendrzej
6100244f5e return current_video_system 2017-08-23 14:30:12 +02:00
Jacek Jendrzej
41212e3c1a add GetVideoSystem() 2017-06-18 13:15:35 +02:00
Jacek Jendrzej
d1569e6114 fix compil 2017-06-15 13:20:22 +02:00
Jacek Jendrzej
497e31c3fd fix KEY_STOP typo 2017-04-15 14:18:47 +02:00
Jacek Jendrzej
ef8868cbbd fix error with empty video buffer 2017-03-22 19:29:57 +01:00
Jacek Jendrzej
757cce78af fix scale screenshot with clutterfb 2017-03-22 18:59:39 +01:00
Jacek Jendrzej
9823295de1 supplement to 85819d69ee, fix2 2017-03-22 17:37:37 +01:00
svenhoefer
c376875c39 Merge remote-tracking branch 'neutrino-mp/master' 2017-03-21 10:48:27 +01:00
svenhoefer
0f857a1836 - generic-pc/clutterfb.cpp: fix my stupid c/p error :/ 2017-03-20 20:58:24 +01:00
svenhoefer
055803dbac - generic-pc: add some more and change some existing keys; ...
I've tried to keep the functions on the right keys. 'r' for Radio,
't' for TV and so on.
2017-03-20 17:58:54 +01:00
Jacek Jendrzej
809c9047ea generic-pc/video.cpp dont set output format with negative height size 2017-03-20 14:30:16 +01:00
Stefan Seyfried
c3f4432496 libtriple: fix hw_caps build 2017-03-19 14:08:54 +01:00
svenhoefer
8709d3ad85 - .gitignore: add compile 2017-03-19 02:03:48 +01:00
Jacek Jendrzej
85819d69ee fix error handling in swscale 2017-03-18 15:12:21 +01:00
svenhoefer
e8ad377b4f - generic-pc/audio.cpp: add default-section to c->codec_id switch ...
to avoid compiler warnings
2017-03-17 11:19:27 +01:00
Jacek Jendrzej
ca355eecd1 check if av_image_fill_arrays return error 2017-03-16 19:06:06 +01:00
Stefan Seyfried
8a1bf4f41e Merge pull request #1 from tuxbox-neutrino/master
Some fixes by Jacek. :)
2017-03-15 20:49:39 +01:00
Jacek Jendrzej
89bd4b00c4 add GetScreenImage to cVideo 2017-03-15 19:07:35 +01:00
Jacek Jendrzej
e68a82cd50 fix audio video rate info 2017-03-14 21:31:02 +01:00
svenhoefer
82a6c40bc4 - cs_api.h: add missing cs_get_chip_type() dummy 2017-03-11 15:28:47 +01:00
Stefan Seyfried
4aed33ff9c hw_caps: add caps for 14:9 AR and broken tuner driver 2017-02-26 19:43:42 +01:00
Stefan Seyfried
d812ac52c5 spark/video: add missing O_CLOEXEC to memory fd 2017-02-19 17:54:56 +01:00
Stefan Seyfried
dac47fd266 pwrmngr: promote standby message to "info" 2017-02-19 17:54:19 +01:00
Stefan Seyfried
9715204498 generic/video: better A/V sync with clutterfb 2017-02-19 17:53:30 +01:00
Stefan Seyfried
9348cef2a6 generic/clutterfb: implement PIG 2017-02-19 17:52:12 +01:00
Stefan Seyfried
0226277758 triple: fix narrowing warning in video_td, add FD_CLOEXEC 2017-02-11 19:00:51 +01:00
Stefan Seyfried
aa683951fc td: fix GetScreenImage() for OSD-only mode 2017-02-09 00:02:57 +01:00
Stefan Seyfried
a5aeb217c5 acinclude: remove unused TUXBOX_APPS_* stuff 2017-02-04 09:23:46 +01:00
Stefan Seyfried
575107b5e1 configure: get rid of TUXBOX_APPS_*PKGCONFIG macros
Use PKG_PROG_PKG_CONFIG / PKG_CHECK_MODULES instead of home-grown macros
2017-02-04 09:23:46 +01:00
Stefan Seyfried
42fb4fe182 generic-pc: port audio/video decoders to newer ffmpeg API
this reduces the amount of deprecation warnings wih newer
ffmpeg releases quite a bit :-)
2016-11-12 17:47:02 +01:00
Stefan Seyfried
43a28b317c generic-pc: fix video shutdown 2016-11-03 11:33:42 +01:00
Stefan Seyfried
2525823506 generic-pc/video: fix stillpicture race condition 2016-10-30 15:57:18 +01:00
Stefan Seyfried
95d07cdfc9 generic-pc: add alternative clutter based framebuffer
Add a framebuffer implementation based on clutter instead of "raw"
OpenGL. The performance is slightly worse, but it might bring some
platform abstraction and other benefits for the future.
2016-10-30 13:08:34 +01:00
Stefan Seyfried
acac2e4f5a generic-pc: fix build with newer ffmpeg 2016-10-22 11:31:31 +02:00
Stefan Seyfried
fd2f0f1fd4 cPlayback: implement new libcoolstream interfaces
a new "Start" and changed "SelectSubtitles" function are
implemented to fix compilation (mostly stubbed out, though)
2016-10-22 11:29:32 +02:00
Stefan Seyfried
db3ec7352e hardware_caps: add boxarch field 2016-01-22 19:02:33 +01:00
Stefan Seyfried
42267080f9 libeplayer3: enable streams that use http auth 2016-01-09 15:43:30 +01:00
Stefan Seyfried
be9ebb472a libeplayer3: fix signed/unsigend comparison warning 2016-01-08 17:40:50 +01:00
Stefan Seyfried
635ce08a89 libspark: allow to seek backwards from EOF in cPlayback 2016-01-08 17:34:49 +01:00
Stefan Seyfried
238f2636d6 libspark: allow streams to play for more than 10 seconds
Neutrino determines "end of file" amongst others by checking if
the current position is less than one second before file length.
So for the streaming case, alwas pretend to be two seconds behind.
2016-01-08 17:29:56 +01:00
Stefan Seyfried
23c64535be libeplayer3: speed up Player::Stop() 2016-01-08 17:28:25 +01:00
Stefan Seyfried
66cc42cb19 libeplayer3: add comments to input class, fix warning 2016-01-08 17:27:51 +01:00
max10
d7403705d9 test aac 2016-01-08 17:23:35 +01:00
Stefan Seyfried
444ccdad5d libeplayer3: disable debug output printf's 2016-01-08 17:16:19 +01:00
Stefan Seyfried
042057b565 libeplayer3: add aac_adtstoasc bitstream filter
Add the aac_adtstoasc bitstream filter for AAC streams. In the
cases where it is not needed, it does not seem to hurt, and in
other cases it fixes audio playback.
TODO: improve the handling of the bsfc allocation / deallocation,
      this should go in a Track() destructor or similar.
2016-01-08 17:03:04 +01:00
Stefan Seyfried
18db6acbc2 spark/video: implicitly do StopPicture() on CVideo::Start()
This seems to be what the coolstream code does.
TODO: look out for side effects (in radio mode etc...)
2015-12-25 19:08:31 +01:00
Stefan Seyfried
d22660a4a1 add video_cs.h header to reduce number of #ifdefs needed 2015-12-25 16:28:06 +01:00
Stefan Seyfried
7613411406 ca: add SlotType parameter to SendCAPMT() 2015-12-13 16:45:27 +01:00
Stefan Seyfried
e7f5c17256 add cPlayback::GetReadCount() 2015-12-13 16:16:24 +01:00
Stefan Seyfried
d863ebc181 generic: fix build with newer openSUSE ffmpeg packages 2015-12-13 13:03:38 +01:00
Stefan Seyfried
a0037c51f0 spark: clear video in StopPicture()
this fixes video playback after audioplayer or upnp browser
2015-03-07 19:40:48 +01:00
Stefan Seyfried
49a9834ac5 spark/record: move buffer allocation outside record thread
move the allocation of the recording buffer outside the
recording thread, so that allocation failures can be
communicated as "failure to start recording" instantly
2015-03-07 18:59:04 +01:00
Stefan Seyfried
ef2df97bde libeplayer3: allow disabling of AAC hardware decoder
export HAL_AAC_SWDEC=1 before starting neutrino and
the (slow) software decoder will be used
2015-03-07 18:45:46 +01:00
max10
8f9a53e40c so it is better thx DboxOldie 2015-03-07 18:31:47 +01:00
max10
f163af47d2 add aac.cpp THX DboxOldie 2015-03-07 18:31:37 +01:00
Stefan Seyfried
00b856173d libspark/playback_libeplayer3: fix EOF signalling 2015-02-28 19:59:28 +01:00
Stefan Seyfried
0a53f3467e spark: select highest quality stream for multi-program streams 2015-02-27 20:06:01 +01:00
martii
9663f535cd libspark/hardware_caps: set has_SCART unconditionally 2015-02-27 18:31:33 +01:00
martii
3ba5512abc libspark: complement vendor ids 2015-02-27 18:30:59 +01:00
martii
0ec87d5a95 libspark/hardware_caps: recognize dvfd [untested] 2015-02-27 18:30:00 +01:00
martii
908df1e86e libspark/hw_caps: check vfd version first (needed to discriminate between Pingulux and Pingulux Plus) 2015-02-27 18:29:44 +01:00
Stefan Seyfried
ab076a85f8 spark: do not freeze/continue in GetScreenImage() 2015-02-25 21:47:36 +01:00
Stefan Seyfried
0dc812e80f spark: implement GetScreenImage for video and audio 2015-02-25 00:51:10 +01:00
Stefan Seyfried
3b6333cc59 spark: implement cRecord::GetStatus() 2015-02-22 22:23:59 +01:00
Stefan Seyfried
1df6cfc16d libspark: port a prior version of martii's cRecord
This imports most of the changes of martii's cRecord
https://gitorious.org/neutrino-hd/martiis-libstb-hal,
commmit 23bea61473
2015-02-22 22:21:33 +01:00
Stefan Seyfried
efb860f20d libtriple: remove absolute file names 2015-02-22 12:33:20 +01:00
Stefan Seyfried
f5e9cceb64 libeplayer3: remove absolute file names
this makes debug output nicer to read for out-of-tree builds
2015-02-22 12:08:47 +01:00
Stefan Seyfried
5007debb3a libspark: tone down cDemux debug messages 2015-02-21 22:26:25 +01:00
Stefan Seyfried
5904b79e38 spark: remove dead code from cDemux 2015-02-21 22:25:29 +01:00
Stefan Seyfried
5830d4adc3 spark: remove videodecoder hack from dmx destructor 2015-02-21 22:14:47 +01:00
Stefan Seyfried
d09ff5bb29 Revert "libspark/dmx: try to fix mysterious crash with gcc4.9"
This reverts commit 860d6bdbe7.

as known by now, this had nothing to do with gcc4.9, but with
the cDemux destructor racing with cDemux::Read()
2015-02-20 09:37:34 +01:00
Stefan Seyfried
2bb5b8e8a9 libspark/playback: fix hds streams by selecting a program
right now there is no way to specify which program to play,
just the first one is selected
2015-02-20 09:34:36 +01:00
Stefan Seyfried
e878f5f751 spark: fix race condition in cDemux
cDemux destructor was racing with Read() which did lead to all
sorts of nasty crashes because after poll returned, the dmx object
could be gone and its memory replaced with totally different things.
2015-02-20 09:30:19 +01:00
Stefan Seyfried
860d6bdbe7 libspark/dmx: try to fix mysterious crash with gcc4.9 2015-02-15 19:54:37 +01:00
Stefan Seyfried
8e36402902 libeplayer3: try to fix dynamic linking 2015-02-13 19:55:54 +01:00
Stefan Seyfried
d1674e2327 libspark/playback_libeplayer3: switch to lt_info/lt_debug 2015-02-13 19:26:12 +01:00
Stefan Seyfried
62283244b4 spark: fix compiler warning in CVideo 2015-02-13 19:13:05 +01:00
martii
4e02a62e48 libspark/video: add missing newline 2015-02-13 18:33:38 +01:00
martii
8dd2a4091b libspark/video: ShowPicture: use VIDEO_STILLPICTURE 2015-02-13 18:32:02 +01:00
Stefan Seyfried
2f24c2bcba libspark/irmp: fix compiler warning 2015-02-13 18:20:58 +01:00
Stefan Seyfried
c2d2be320f libeplayer3: fix compiler warning 2015-02-13 18:15:48 +01:00
Stefan Seyfried
64f4702691 includes: remove *_td.h, we use is *_hal.h now 2015-02-13 18:13:10 +01:00
Stefan Seyfried
78f49580e0 use audio_hal.h and dmx_hal.h instead of *_td.h 2015-02-13 18:11:16 +01:00
Stefan Seyfried
100830e805 spark: use pkg-config for ffmpeg ldflags 2015-02-13 18:08:46 +01:00
Stefan Seyfried
d4365037f6 libeplayer: disable subtitle code
current neutrino is not prepared for this, so comment
it out to fix linking
2015-02-13 17:57:55 +01:00
Stefan Seyfried
dc5067e5d2 playback_libeplayer3: mention contributors in file header 2015-02-13 17:56:41 +01:00
Stefan Seyfried
270e282d1f spark: adpapt playback_libeplayer3 to martii's eplayer3 code
Most of this code is from martii, (see the original repo at
https://gitorious.org/neutrino-hd/martiis-libstb-hal). Unfortunately
our code bases have diverged enough that a proper merge or cherry-
picking with git, preserving authorship and history was not possible.
I do not claim authorship for most of this.
2015-02-13 17:48:47 +01:00
Stefan Seyfried
535b12d63a Merge branch 'martii-libeplayer3'
This merges the libeplayer3 changes from martii.
Does not even compile yet, libspark/player code needs
to be fixed first.

Conflicts:
  libeplayer3/Makefile.am libeplayer3/README
  libeplayer3/include/manager.h libeplayer3/include/misc.h
  libeplayer3/include/output.h libeplayer3/include/pes.h
  libeplayer3/include/writer.h
2015-02-13 11:58:21 +01:00
Stefan Seyfried
fc799dc6bf triple: remove videodecoder hack from dmx destructor 2015-02-06 19:56:19 +01:00
Stefan Seyfried
56e6d04719 triple: set audioDecoder to NULL in destructor
this avoids blowing up in the CPlayback destructor
2015-02-06 19:52:49 +01:00
Stefan Seyfried
746fe7bf87 triple: abuse dmx->getBuffer as 'dmx running' indicator 2015-02-06 19:46:30 +01:00
Stefan Seyfried
757f7de70c libeplayer3: add "subdir-objects" automake option 2015-01-26 10:20:48 +01:00
martii
67a6810022 libeplayer3/manager: use AVDISCARD_NONE instead of AVDISCARD_DEFAULT to disable programs 2014-08-31 12:36:22 +02:00
martii
79c203676f libeplayer3/h264: partially revert 9112c4d16d 2014-08-25 18:36:23 +02:00
martii
ad0b3175c1 libeplayer3: implement multi-program support 2014-08-22 18:53:52 +02:00
martii
099ccfe6bb libeplayer3/h264: simplify 2014-08-22 18:52:45 +02:00
martii
d4a8c87ec3 libeplayer3/input: amend 545732a12b 2014-07-28 18:02:50 +02:00
martii
760b46a373 libeplayer3/input: disable avformat logging 2014-07-27 11:09:45 +02:00
martii
8449c055e0 libeplayer3/input: don't modify avformat stream id 2014-07-27 10:36:43 +02:00
martii
8dd6d00ef1 libeplayer3/Makefile.am: set AUTOMAKE_OPTIONS = subdir-objects 2014-07-19 16:54:12 +02:00
martii
286955f888 libeplayer3/writer: minor cleanup, no binary change 2014-07-16 21:47:34 +02:00
martii
e7381352d4 libeplayer3/player: support bluray urls 2014-06-19 10:46:36 +02:00
martii
4e2ff2ce6d libeplayer3/input: allow access to AVFormatContext 2014-05-29 21:57:38 +02:00
martii
23d912c034 libeplayer3/writer/pcm.cpp: break potential infinite loop 2014-05-24 13:05:16 +02:00
martii
fe095b5a2c libeplayer3/input.cpp: filter duplicated messages 2014-05-24 13:04:06 +02:00
Stefan Seyfried
45576494e5 raspi: fix audio decoding with newer libavcodec
Current libavcodec does no longer always return S16 sample format, but
the conversion needs to be done explicitly. Use libswscale for that.
Not tested on raspbian, only on yocto/ffmpeg.
2014-05-03 21:01:38 +02:00
martii
33726e48d0 libeplayer3/input: no need for alloca() 2014-05-03 14:29:26 +02:00
martii
96ae9b1d40 libeplayer3/input: fix SwitchVideo (unused, but anyway) 2014-05-03 12:35:59 +02:00
martii
263f211cbe libeplayer3: limit video frame skipping to network streams 2014-05-02 15:05:47 +02:00
martii
b0a734c607 libeplayer3: skip video until first audio frame was found 2014-05-02 14:52:10 +02:00
martii
3c2f594147 libeplayer3: minor adjustments 2014-05-02 13:34:08 +02:00
martii
e7d95eb3d3 libeplayer3: fix audio switching on already terminated playback 2014-05-01 12:52:38 +02:00
martii
5ffbeafa49 libeplayer3/writer: add fd to writer class 2014-05-01 12:51:41 +02:00
martii
65890b2e14 libeplayer3/writer: add fd to writer class 2014-05-01 12:51:26 +02:00
martii
de993ea5b1 libeplayer3: cleanup AVFormatContext propagation to writers 2014-05-01 10:15:14 +02:00
martii
64a524ab5c libeplayer3/input: fix audio flush packet initialization 2014-05-01 10:01:36 +02:00
martii
5ab9e2deda libeplayer3/input: stream duration fix 2014-04-30 19:08:30 +02:00
martii
ef58a765bb libeplayer3: remove flac writer (now handled by mp3 writer) 2014-04-27 12:52:15 +02:00
martii
0fe0e5ce6d libeplayer3: remove flac writer (now handled by mp3 writer) 2014-04-27 12:51:40 +02:00
martii
f9931b3b1b libeplayer3/writer: implement decoder flushing 2014-04-27 12:45:15 +02:00
martii
d195c29769 libeplayer3/writer/pcm: remove debug output 2014-04-26 19:54:42 +02:00
martii
8128fe3289 libeplayer3/writer/pcm: move reinit code out of packet loop 2014-04-26 19:20:32 +02:00
martii
32e8bd8252 libeplayer3/writer: remove constructors/destructors from writer class 2014-04-26 14:57:22 +02:00
martii
35ff3bb69c libeplayer3/Makefile: minor rewrite 2014-04-26 14:56:15 +02:00
martii
1b4b110c26 libeplayer3: move calcPts to Input class 2014-04-26 14:54:38 +02:00
martii
fc658e27b0 libeplayer3/output: unbreak GetFrameCount() 2014-04-26 14:53:43 +02:00
martii
40557ac647 libeplayer3/writer/pcm: simplify 2014-04-26 14:53:02 +02:00
martii
dd7db83276 libeplayer3/input: unbreak dvbsub pts calculation 2014-04-26 14:51:54 +02:00
martii
a6b0acda6d libeplayer3/writer/pcm: cleanup 2014-04-21 14:08:40 +02:00
martii
bdc242d29b libeplayer3/writer/pcm: simplify pts handling 2014-04-21 14:00:51 +02:00
martii
6906e9f929 libeplayer3/writer/pcm: minor adjustments 2014-04-21 13:24:52 +02:00
martii
25811b99be libeplayer3: minimize debug output 2014-04-18 16:20:07 +02:00
martii
c5426c8596 libeplayer3: fix backward mode 2014-04-18 16:09:54 +02:00
martii
ae1bcb466b libeplayer3: use av_rescale for pts calulations 2014-04-18 11:16:44 +02:00
martii
9d6397ac35 libeplayer3/input: disable noprobe and retry if probing fails 2014-04-18 09:48:28 +02:00
martii
12845ab18c libeplayer3: minor adjustments 2014-04-16 17:26:53 +02:00
martii
a3eb634030 libeplayer3/writer/pcm: unbreak 2014-04-15 21:59:22 +02:00
martii
06449fcbfd libeplayer3/input: don't segv in deconstructor 2014-04-15 19:47:59 +02:00
martii
b4ec2c34b9 libeplayer3: optimizations (untested) 2014-04-15 17:12:22 +02:00
martii
62d526f799 libeplayer3: use uint64_t instead of float/double for position calculations 2014-04-14 21:47:40 +02:00
martii
046da3c411 libeplayer3/output: reset stream variables after Close() 2014-04-13 21:29:26 +02:00
martii
578dc39595 libeplayer3: minor optimization 2014-04-13 19:29:07 +02:00
martii
d53589353e libeplayer3/input: increase probesize 2014-04-13 16:30:33 +02:00
martii
4b648be6fa libeplayer3/input: fix AV_CODEC_ID_MP2 usage 2014-04-12 16:53:55 +02:00
martii
a8a2d917fb libeplayer3 adjustments 2014-04-11 18:40:39 +02:00
martii
bbe2472f2d libeplayer3: cast away compiler warning 2014-04-11 14:49:42 +02:00
martii
4da9260b54 libeplayer3: cleanup 2014-04-11 14:20:22 +02:00
martii
1a808def2f libeplayer3: ffmpeg now provides teletext details in codec->extradata 2014-04-11 14:11:36 +02:00
martii
6c594a7cda libeplayer3: cleanup 2014-04-10 23:51:17 +02:00
martii
be26d8d46b libeplayer3: work around duplicate ffmpeg stream ids by comparing stream addresses instead of pids (plus a couple of optimizations) 2014-04-10 23:35:38 +02:00
martii
478a83efad libeplayer3/input: rename some variables 2014-04-10 20:47:44 +02:00
martii
3f30607fbd libeplayer3/output: remove redundant videofd check 2014-04-10 20:46:39 +02:00
martii
5f340ec4a8 libeplayer3/writer: unsigned char => uint8_t 2014-04-10 20:45:57 +02:00
martii
33d7a29134 libeplayer3/Makefile: disable debugging flags 2014-04-09 22:07:12 +02:00
martii
6c340eb752 libeplayer3: extend API 2014-04-09 22:06:41 +02:00
martii
eafc00a861 libeplayer is now C++, no more need for extern "C" to access Neutrino functions 2014-04-08 20:42:17 +02:00
martii
2fc7cac404 libeplayer3: rename player thread 2014-04-08 20:24:22 +02:00
martii
7bb603a8af libeplayer3: change compile options 2014-04-08 20:12:35 +02:00
martii
bfbe8ed51a libeplayer3: track update: remove redundant teletext pid from return string 2014-04-08 20:10:05 +02:00
martii
cb3db6256c libeplayer3: continue refresh 2014-04-08 20:02:07 +02:00
martii
fcd1dc8399 libeplayer3: cleanups 2014-04-07 23:00:03 +02:00
martii
5448fb35bf libeplayer3: rename files 2014-04-07 21:34:01 +02:00
martii
514398ad2a libeplayer3: remove debug.h 2014-04-07 21:28:20 +02:00
martii
12c9643978 libeplayer3: merge Playback to Player class 2014-04-07 21:25:30 +02:00
martii
ca5effe1bc libeplayer3: implement Playback and Input classes 2014-04-07 21:01:02 +02:00
martii
1112111e2d libeplayer3: implement Manager class 2014-04-06 21:12:56 +02:00
martii
2067355059 libeplayer3: rename linuxdvb.cpp => output.cpp 2014-04-06 18:21:31 +02:00
martii
6e37a5bcc1 libeplayer3: implement Output class 2014-04-06 18:19:00 +02:00
martii
f945fe34aa libeplayer3: eliminate intermediate output layer 2014-04-06 13:30:20 +02:00
martii
2777eb4788 libeplayer3: rename common.h => player.h 2014-04-06 12:13:18 +02:00
martii
85fcd7379d libeplayer3: rename Content_t => Player 2014-04-06 12:11:40 +02:00
martii
7bf5a5f290 libeplayer3: remove unused code 2014-04-06 11:39:11 +02:00
martii
d97d2a84d8 libeplayer3: implement Writer class 2014-04-06 11:35:17 +02:00
martii
25948637ab libeplayer: simplify writer/pcm 2014-04-05 19:32:58 +02:00
martii
06c260681f libeplayer3: remove writeReverseData (unused) 2014-04-05 17:50:22 +02:00
martii
23bad752df libeplayer3: cleanup pcm writer 2014-04-05 17:44:42 +02:00
martii
9f9d1b64ce libeplayer: cleanup writers 2014-04-05 16:40:03 +02:00
martii
896a08e145 libeplayer3: unbreak ipcm 2014-04-05 16:34:03 +02:00
martii
1a04102c23 libeplayer3: let writers use AVPacket 2014-04-05 16:17:57 +02:00
martii
2d0ca622f8 libeplayer3: c++ adjustments 2014-04-05 16:02:06 +02:00
martii
97f1aff64f libeplayer3: rename to c++ 2014-04-05 16:01:12 +02:00
martii
15964474f3 libeplayer3: delete include/aac.h (unused) 2014-04-05 13:27:13 +02:00
martii
4ccc66e6cc libeplayer3: remove wmv version (unused) 2014-04-05 13:26:24 +02:00
martii
7a80a1f3e1 libeplayer: remove inject_raw_pcm (unused) 2014-04-05 13:24:39 +02:00
martii
500e8e8eac libeplayer3: move audio resampling to dedicated ipcm writer 2014-04-05 13:21:58 +02:00
martii
ff13f75588 libeplayer3: move width/height/framerate/timescale calculation to writers 2014-04-05 11:36:49 +02:00
martii
85bcfb4a17 libeplayer3: change extradata handling 2014-04-05 11:05:37 +02:00
martii
5e2d44cc5d libeplayer3: remove writer/wma.c and writer/aac.c (handled by ffmpeg instead) 2014-04-05 10:39:55 +02:00
martii
01144c864b libeplayer3: make ffmpeg data available to manager, output and writer 2014-04-05 10:16:30 +02:00
martii
a4baa13ed1 libeplayer3: cleanup types 2014-04-05 10:01:52 +02:00
martii
46cd3a2703 libeplayer3: remove tools 2014-04-05 09:51:24 +02:00
martii
9fbb682eda libeplayer3: remove tools 2014-04-05 09:50:56 +02:00
martii
ff24109403 libeplayer/container_ffmpeg: switch to ffmpeg 2.0 API 2014-04-03 18:10:03 +02:00
martii
794ced8b3d libeplayer3/container_ffmpeg: remove latestPts variable 2014-03-26 17:59:50 +01:00
martii
4f32aa4ea0 libeplayer3: more cleanups 2014-03-23 17:55:12 +01:00
martii
a0cd63ce87 libeplayer3: remove no longer needed teletext output handling 2014-03-23 14:46:31 +01:00
martii
9eb23c78f4 libeplayer3: change teletext handling to directly inject packets in tuxtext 2014-03-23 13:54:40 +01:00
martii
173880cb31 libeplayer3: cleanup unused code 2014-03-23 10:31:53 +01:00
martii
6fcfafc604 libeplayer3/container_ffmpeg: fix seek bitrate calculation 2014-03-23 10:09:17 +01:00
martii
7767f23a0f libeplayer3/container_ffmpeg: don't set pts if audio-only 2014-03-22 14:18:37 +01:00
martii
243bbc3f5b libeplayer3: initalize AVSubtitle 2014-03-22 13:27:34 +01:00
martii
dc9f75646c libeplayer3: remove debugging output; abort if neither an audio nor a video stream is available 2014-03-22 13:26:29 +01:00
martii
2c4979f6b5 cleanup 2014-03-21 23:27:37 +01:00
martii
77dce975a3 libeplayer3: remove subtitle.h 2014-03-21 22:37:55 +01:00
martii
6572e5538c libeplayer3/container_ffmpeg: drop subtitle.h include 2014-03-21 22:34:48 +01:00
martii
9393207c4c libeplayer3: cleanup 2014-03-21 20:18:17 +01:00
martii
cd7c6086d2 libeplayer3: subtitles will now be displayed by neutrino 2014-03-21 20:15:01 +01:00
martii
f60e040d03 libeplayer3: let neutrino handle bitmap subtitles 2014-03-16 07:29:38 +01:00
martii
0e55c3f01b eplayer3: fix playback termination handling 2014-03-09 14:24:50 +01:00
martii
76a42bda44 eplayer3: fix playback termination handling 2014-03-09 14:16:45 +01:00
Stefan Seyfried
d71950c4a2 start versioning libstb-hal 2014-02-23 15:13:15 +01:00
Stefan Seyfried
bbb50fc606 add dummy cPlayback GetTitles() and SetTitle(); 2014-02-23 15:02:31 +01:00
Stefan Seyfried
3ff4fd923b libtriple: do not read from invalid dmx 2014-02-23 14:38:58 +01:00
Stefan Seyfried
043bde93c1 update ca.h to currently used interface 2014-01-28 15:04:24 +01:00
Stefan Seyfried
4e30d5ded6 triple: hack cDemux::GetSource() 2014-01-25 20:23:51 +01:00
Stefan Seyfried
39103f03d2 remove obsolete copies of mmi.h 2014-01-23 13:18:19 +01:00
Stefan Seyfried
e3f53de4ae include/mmi: fix spelling (but keep compatibility) 2014-01-23 13:16:27 +01:00
martii
8da0fecb53 libeplayer3/libspark: cPlayback: implement retrieval of metadata 2014-01-19 12:25:35 +01:00
martii
5fb12c8048 libeplayer3/container_ffmpeg: fix metadata access 2014-01-18 16:54:41 +01:00
martii
dd242bda4a libeplayer3/playback: fix seeking/neutrino bookmarks 2013-12-30 12:26:02 +01:00
martii
0df645f5c7 libeplayer3, libspark/playback_libeplayer3: chapter support 2013-12-30 12:25:54 +01:00
martii
1073220ff4 libeplayer3/container_ffmpeg: only log ffmpeg errors at debug_level > 10 2013-12-30 12:17:42 +01:00
martii
ff099b9356 libeplayer3/container_ffmpeg: don't modify AVPacket internals (I don't believe this actually hurts, but better safe than sorry) 2013-12-30 12:17:31 +01:00
martii
80daefef90 libeplayer3/linuxdvb: reduce debug spam 2013-12-30 12:16:33 +01:00
martii
6546462c4e libspark/playback: speed up abort 2013-12-30 12:16:04 +01:00
martii
51a920d26f libeplayer3: cleanup, indent 2013-12-30 12:15:38 +01:00
martii
31482f5286 libeplayer3: fix audio recoding, yt aac stuttering should be gone now 2013-12-30 12:15:15 +01:00
martii
6c84031759 libeplayer3/playback: disable debugging output 2013-12-30 12:14:55 +01:00
martii
32ec25ec4d libeplayer3/ffmpeg: minor cleanup 2013-12-30 12:14:47 +01:00
martii
62df38174e fix last commits 2013-12-30 12:14:41 +01:00
martii
129206c5db libeplayer3: run through indent, no binary change 2013-12-30 12:14:09 +01:00
martii
c229a6019d libeplayer3/container: fix compiler warning 2013-12-30 12:11:34 +01:00
martii
051507623e libeplayer3/ffmpeg: rearrange seeking code 2013-12-30 12:10:59 +01:00
martii
455749f311 libeplayer3/ffmpeg: don't initialize container if context already exists 2013-12-30 12:10:46 +01:00
martii
db48911f37 libeplayer3: fix seeking 2013-12-30 12:10:32 +01:00
martii
7142d4de2d libeplayer3/ffmpeg: add 3gp and ogm extensions 2013-12-30 12:10:19 +01:00
martii
9b1c3353de libeplayer3: modify fast-backward 2013-12-30 12:09:49 +01:00
martii
a2631567fe tools/spark_fp: add flashing period option 2013-12-30 12:08:17 +01:00
martii
af5f30ae92 tools/spark_fp: add option for enabling/disabling icons 2013-12-30 12:05:02 +01:00
martii
ed9299c780 libspark/audio, libeplayer3: audio type adjustments 2013-12-30 11:32:36 +01:00
martii
be656d7cee libeplayer3/playback: fix seeking/neutrino bookmarks 2013-12-28 22:44:10 +01:00
Stefan Seyfried
beab047387 playback: add MAX_PLAYBACK_PIDS define
TODO: actually fix the code to return more than 10 PIDs.
2013-12-28 19:38:28 +01:00
Stefan Seyfried
f082c8dcd0 libspark: add missing librt to linker flags 2013-12-26 11:14:19 +01:00
Stefan Seyfried
4b8568d79a libspark: add missing unistd.h includes for gcc 4.7+ 2013-12-26 10:53:49 +01:00
martii
9b6880102e libeplayer3, libspark/playback_libeplayer3: chapter support 2013-12-23 16:47:29 +01:00
Stefan Seyfried
d76cf27929 pic2m2v: implement as a script
The C code was only calling ffmpeg binary anyway...
Additionally create a md5 sum of the input file to avoid
unnecessary conversions.
2013-12-21 23:56:11 +01:00
martii
4db66e226f libeplayer3/container_ffmpeg: only log ffmpeg errors at debug_level > 10 2013-12-17 15:39:11 +01:00
martii
2b1bb1f9ca libeplayer3/container_ffmpeg: don't modify AVPacket internals (I don't believe this actually hurts, but better safe than sorry) 2013-12-15 19:23:15 +01:00
martii
76bdd325c1 libeplayer3/linuxdvb: reduce debug spam 2013-12-15 15:14:35 +01:00
martii
b08a39c4c1 libspark/playback: speed up abort 2013-12-11 09:13:25 +01:00
martii
b6ba5ea298 libeplayer3: cleanup, indent 2013-12-09 16:47:15 +01:00
martii
8ce41532e7 libeplayer3: fix audio recoding, yt aac stuttering should be gone now 2013-12-09 12:15:37 +01:00
Stefan Seyfried
e4dba8b30e libtriple: avoid race conditions in cVideo::ShowPicture
ShowPicture() and Stop() were racing, and the calling order from
neutrino seems to be not necessarily "correct". With gcc-4.8 /
glibc-2.16 binaries it happened that on switching to radio mode,
ShowPicture() was called and then the Stop() from stopping video
playback happened. This broke the stillpicture. Fix by adding more
locks and explicitly bailing out of Stop() if a picture is shown.
2013-12-02 00:58:37 +01:00
Stefan Seyfried
f403e3b3e2 libtriple: load blank mpegs from DATADIR 2013-12-02 00:57:55 +01:00
Stefan Seyfried
1590198998 libtriple: fix build with yocto gcc-4.8.1/eglibc-2.16 toolchain 2013-11-24 20:47:56 +01:00
martii
2a720c6106 libeplayer3/playback: disable debugging output 2013-11-23 14:40:28 +01:00
martii
11191c62dd libeplayer3/ffmpeg: minor cleanup 2013-11-22 18:08:00 +01:00
martii
ad4a850426 fix last commits 2013-11-21 23:15:35 +01:00
martii
4b5391ad4d libeplayer3: run through indent, no binary change 2013-11-21 19:40:47 +01:00
martii
76f873e191 libeplayer3/container: fix compiler warning 2013-11-21 19:28:57 +01:00
martii
6de629b4af libeplayer3/ffmpeg: rearrange seeking code 2013-11-21 19:25:20 +01:00
martii
7e39d85631 libeplayer3/ffmpeg: don't initialize container if context already exists 2013-11-21 18:18:13 +01:00
martii
615f8d9708 libeplayer3: fix seeking 2013-11-19 22:38:26 +01:00
martii
6094f51e2d libeplayer3/ffmpeg: add 3gp and ogm extensions 2013-11-19 19:33:33 +01:00
martii
6fc19089c4 libeplayer3: modify fast-backward 2013-11-17 15:24:33 +01:00
martii
d61e9f4f2b libspark/audio, libeplayer3: audio type adjustments 2013-11-11 12:30:47 +01:00
Stefan Seyfried
5137575c11 libspark/eplayer3: fix ffmpeg linker flags 2013-11-09 23:18:08 +01:00
Stefan Seyfried
db22215f9e libspark: fix build after libeplayer update
only build tested for now.
2013-11-09 22:47:44 +01:00
Stefan Seyfried
a2a4651c46 libeplayer3: fix merge errors 2013-11-09 22:45:13 +01:00
martii
068769c110 libstb-hal/libspark/playback: add method for retrieving read-count 2013-11-09 22:40:08 +01:00
martii
6cff3e3377 libeplayer3: speed up termination 2013-11-09 22:39:41 +01:00
martii
6b3062d3ec libspark/player, libeplayer3/ffmpeg: improve termination handling 2013-11-09 22:39:32 +01:00
martii
7738a24be1 libspark/player: use int instead of short in some places 2013-11-09 22:37:56 +01:00
martii
fc06947ba7 libeplayer3/ffmpeg: minor cleanup 2013-11-09 22:36:26 +01:00
martii
e01a3d5312 libeplayer3/playback: convert mms urls to mmst instead of rtsp 2013-11-09 22:36:19 +01:00
martii
ff63d40176 libeplayer3/manager: initialize track IDs 2013-11-09 22:36:08 +01:00
martii
545a3208d4 libeplayer3: tracks update is now lock-free 2013-11-09 22:35:45 +01:00
martii
7645863bfb libeplayer3/container_ffmpeg: mutex fix 2013-11-09 22:35:38 +01:00
martii
f20fc1f81d libeplayer3/wmv: revert to (almost) original version 2013-11-09 22:35:30 +01:00
martii
60dd40a5ad libeplayer/text_srt: minor optimization 2013-11-09 22:35:23 +01:00
martii
07709ce1cd libeplayer3: drop non-shared framebuffer support 2013-11-09 22:00:19 +01:00
martii
a51f79352b libeplayer3: unbreak srt subs 2013-11-09 21:58:57 +01:00
martii
1a3ac317c2 libeplayer3: cleanup 2013-11-09 21:58:43 +01:00
martii
37c573041a libeplayer3: vc1, wmv: use InsertPesHeader for initial PES headers, too 2013-11-09 21:58:36 +01:00
martii
0fa7469487 libeplayer3/output/writer/: remove PesHeader memset (both wrong and unneeded) 2013-11-09 21:58:17 +01:00
martii
95d724ced0 libeplayer3 optimizations 2013-11-09 21:58:05 +01:00
martii
aa5f59c5e6 libeplayer3/container_ass: cosmetics 2013-11-09 21:56:28 +01:00
martii
998607edfc libeplayer3/container_ffmpeg: cleanup 2013-11-09 21:56:21 +01:00
martii
6931fcd838 libeplayer3/writer/framebuffer: small optimization 2013-11-09 21:56:14 +01:00
martii
027660da47 libeplayer3/container_ass: set thread name 2013-11-09 21:56:08 +01:00
martii
3bc8b09638 libeplayer3/pcm: cleanup 2013-11-09 21:55:59 +01:00
martii
5b9837b3a9 libeplayer3/pcm: minor clean-up, no code change 2013-11-09 21:55:51 +01:00
martii
d9e8115cae Fix libeplayer3's broken PCM injection implementation. Jumps in movieplayer now works without losing a/v sync. 2013-11-09 21:55:43 +01:00
martii
75da827371 libeplayer3/container_ffmpeg: don't flush instead of clear 2013-11-09 21:55:34 +01:00
martii
8e0c61ead0 libeplayer3: use uint32_t for frame buffer access 2013-11-09 21:55:23 +01:00
martii
9f27e84225 libeplayer3/continer_ass: crude hack to improve subtitle readability 2013-11-09 21:54:46 +01:00
martii
e7f0879153 libeplayer3/subtitles/spark: use backbuffer and blit 2013-11-09 21:54:22 +01:00
martii
185acae677 libeplayer3/container_ass: font size adjusted 2013-11-09 21:53:35 +01:00
martii
d301826998 libeplayer/playback: disable subtitle init hack 2013-11-09 21:53:27 +01:00
martii
864bd7d422 libeplayer3/subtitle: reduce debugging level 2013-11-09 21:53:18 +01:00
martii
c550a79d7c libeplayer3: initial attempt to unbreak ass/ssa subtitles 2013-11-09 21:53:12 +01:00
martii
5a255e9c4a libeplayer/linuxdvb: cleanup 2013-11-09 21:53:05 +01:00
martii
019b2a5dca libeplayer3/containter_ffmpeg: fix track update 2013-11-09 21:52:59 +01:00
martii
6395850a91 libeplayer3/container_ffmpeg: no need for copying the input packet 2013-11-09 21:52:50 +01:00
martii
0c295bcfc0 libeplayer/container_ffmpeg: subtitle fix 2013-11-09 21:52:42 +01:00
martii
10488303fc libeplayer3/container_ffmpeg.c: re-order packet.data check (not sure whether this is needed at all) 2013-11-09 21:52:35 +01:00
martii
c212dae7b1 libeplayer/container_ffmpeg: correct misplaced brackets 2013-11-09 21:52:15 +01:00
martii
8ba924c471 libeplayer3/container_ffmpeg: initialize stream ids, if unset 2013-11-09 21:51:37 +01:00
martii
e30ad7d035 libeplayer3/container_ffmpeg: av_samples_alloc: use actual number for channels 2013-11-09 21:51:21 +01:00
martii
c7ddfbf8be libeplayer3/container_ffmpeg: align av_samples_alloc buffer 2013-11-09 21:50:41 +01:00
martii
8f06d2558e libeplayer3/container_ffmpeg: fix mono->stereo conversion 2013-11-09 21:50:24 +01:00
martii
e3f1d23acc libeplayer/container_ffmpeg: audio pts fix 2013-11-09 21:50:08 +01:00
martii
1c296f02bf libeplayer3: remove outdated include/stm_ioctl.h 2013-11-09 21:49:47 +01:00
martii
40b3c4459d container_ffmpeg: flush streams immediately after seek 2013-11-09 21:49:39 +01:00
martii
396077ccb2 libeplayer3: cleanup 2013-11-09 21:49:31 +01:00
martii
a49a33c983 libeplayer: reduce debugging output 2013-11-09 21:49:21 +01:00
martii
852d4e69ea h264: don't mess with packet length 2013-11-09 21:49:13 +01:00
martii
b59343cf69 libeplayer3/h264: unbreak 2013-11-09 21:48:29 +01:00
martii
80a86fa72f libeplayer3/container_ffmpeg: No attributes needed for mutex init 2013-11-09 21:48:14 +01:00
martii
9d51907c5d libeplayer3 cleanup 2013-11-09 21:47:45 +01:00
martii
51f112dabb libeplayer3/h264 cleanup 2013-11-09 21:47:32 +01:00
martii
f61395efdf libeplayer3: experimental h.264 playback fix 2013-11-09 21:47:01 +01:00
martii
b9c8d61b3a libeplayer3: cleanup 2013-11-09 21:46:43 +01:00
martii
8affebdef6 libeplayer3: use actual pids instead of indexes 2013-11-09 21:46:26 +01:00
martii
12f6a51f49 ffmpeg-2.0 2013-11-09 21:42:04 +01:00
martii
22d4f40fb9 libeplayer3/container_ffmpeg: revert swr_next_pts call 2013-11-09 21:41:41 +01:00
martii
dfa1a3e32b libeplayer3: minor changes 2013-11-09 21:41:30 +01:00
martii
dc85e1c284 libeplayer3: re-enable audio after seeking (still broken) 2013-11-09 21:39:30 +01:00
martii
5e38511807 libeplayer3: need to call avcodec_free_frame after swresample, too 2013-11-09 21:39:09 +01:00
martii
0a386a264d libeplayer3: the mp3 handler can easily take care of vorbis data, too. 2013-11-09 21:38:39 +01:00
martii
8e64b9c7b1 libeplayer3: vorbis can easily be handled by the mp3 writer 2013-11-09 21:38:21 +01:00
martii
96c0c7c3a5 libeplayer3/h264: disable debugging 2013-11-09 21:37:47 +01:00
martii
c3bbda3e9c libeplayer3: get rid of compiler warnings 2013-11-09 21:37:38 +01:00
martii
dd618fc883 libeplayer3: drop legacy ffmpeg support 2013-11-09 21:35:48 +01:00
martii
fffbbacd74 libeplayer/h264: Fix playback. 2013-11-09 21:34:52 +01:00
martii
267788f14e libeplayer3: deactivate debugging 2013-11-09 21:34:42 +01:00
martii
f5091bcd35 libeplayer3: cleanup 2013-11-09 21:31:50 +01:00
martii
546eb23e0e libeplayer3: further malloc-memcpy-write -> writev replacements; not fully regression tested 2013-11-09 21:27:07 +01:00
martii
9556f935bf libeplayer3/h264: replace malloc/memcpy/write with writev 2013-11-09 21:25:19 +01:00
martii
4e0f7f9a91 libeplayer3: drop buffering code due to crashes 2013-11-09 21:25:10 +01:00
martii
9ce0d977b1 replace libavresample with libswresample 2013-11-09 21:24:46 +01:00
martii
d5b57e281d libeplayer reverse play: experimental adjustment to find previous I-frame 2013-11-09 21:21:00 +01:00
martii
9edd4277c3 libeplayer3: fix segv 2013-11-09 21:20:52 +01:00
martii
2368ec790f eplayer3: subtitle fixes 2013-11-09 21:20:43 +01:00
martii
fec74fdcc7 crude hack for movieplayer tuxtxt integration 2013-11-09 21:20:34 +01:00
martii
6106d014e9 teletext handling changes 2013-11-09 21:20:14 +01:00
martii
8d3fba60a3 libeplayer3: dynamically update pid list 2013-11-09 21:19:21 +01:00
martii
a2e60ad48a libeplayer/container_ffmpeg: use injected PCM for raw PCM, too 2013-11-09 21:18:39 +01:00
martii
ed7c956e7f libeplayer3/container_ffmpeg: handle .wtv extensions, too 2013-11-09 21:18:32 +01:00
martii
4569654545 libeplayer3/container_ffmpeg: fix WMA playback 2013-11-09 21:18:24 +01:00
martii
9b2d5761a9 libeplayer3: add callback to abort avformat_open_input 2013-11-09 21:18:11 +01:00
martii
b976862530 libeplayer3/container_ffmpeg: cleanup 2013-11-09 21:17:37 +01:00
martii
aae498250b libeplayer3: merge buffered IO code from TDT; implement proper audio resampling 2013-11-09 21:15:30 +01:00
martii
fb8c2f33d1 libeplayer3/container_ffmpeg: minor cleanup 2013-11-09 21:15:04 +01:00
martii
824b328ec1 libeplayer3/container_ffmpeg: no need to scale the buffer 2013-11-09 21:14:30 +01:00
martii
a01b70f226 libeplayer3: this may improve recovery from broken streams 2013-11-09 21:14:21 +01:00
martii
dc95df1150 libeplayer3: switch back to software decoding for AAC; crude fix for PCM injection (newer ffmpeg versions return floats instead of shorts), injected PCM streams (OGG, for example), will now work again. I'd be grateful if anybody with a deeper understanding of the FFMPEG API would supply a cleaner fix ... 2013-11-09 21:14:12 +01:00
martii
78307db056 libeplayer: set 65535 as maximum PES length 2013-11-09 21:14:04 +01:00
martii
e99a8fd76a libeplayer: assume unlimited PES length for too large packets 2013-11-09 21:13:56 +01:00
martii
0bee4efa6e libeplayer3: experimental fixes 2013-11-09 21:13:47 +01:00
martii
fd72343f69 libeplayer/playback: initialize length to -1 2013-11-09 21:13:25 +01:00
martii
525cd01c2c libeplayer3 fix 2013-11-09 21:13:18 +01:00
martii
1c1d85e582 libeplayer3: check for valid avContext pointer 2013-11-09 21:13:10 +01:00
martii
4cf92f8102 improve subtitle handling 2013-11-09 21:12:50 +01:00
martii
f0446eeeb2 libspark/libeplayer: rudimentary subtitle support, probably unstable 2013-11-09 21:12:20 +01:00
martii
1cc9619c49 get rid of most compiler warnings 2013-11-09 21:11:32 +01:00
martii
e94b7daf85 fix indent 2013-11-09 21:08:33 +01:00
martii
d431e60284 libeplayer3: add support for teletext and dvbsubtitle streams 2013-11-09 21:02:35 +01:00
Stefan Seyfried
8563837c8b libtriple: fix memory allocation size 2013-11-09 18:00:08 +01:00
Stefan Seyfried
4c74b822ca spark: add missing initialization of flt variable 2013-11-09 14:39:29 +01:00
Stefan Seyfried
8f7e6e981f generic-pc: fix exporting of vdec 2013-11-09 14:16:29 +01:00
Stefan Seyfried
2dd8dd1d20 raspi: rename EGL_CFLAGS to OMX_CFLAGS
we are not really interested in EGL but in OpenMAX ;-)
2013-11-07 10:53:25 +01:00
martii
33b204df8a libstb-hal/libspark/playback: add method for retrieving read-count 2013-11-04 14:15:21 +01:00
Stefan Seyfried
1b5a6076d9 raspi: comment unused variable which breaks newer ffmpeg 2013-11-03 14:18:45 +01:00
Stefan Seyfried
e953af61c2 raspi: update egl configure hack 2013-11-03 14:18:07 +01:00
Stefan Seyfried
32d83d32c5 raspi: use egl packages if available 2013-11-03 13:30:51 +01:00
Stefan Seyfried
ecab8ca7c0 install library headers 2013-11-03 01:28:07 +01:00
Stefan Seyfried
95a20e181b all: clean up cRecord header, hide private stuff 2013-11-03 01:04:27 +01:00
Stefan Seyfried
fc0300416b all: clean up pwrmngr header file 2013-11-03 00:15:19 +01:00
Stefan Seyfried
e746daaf5a all: clean up cPlayback header, hide private stuff
compile tested only ;)
2013-11-02 23:39:31 +01:00
Stefan Seyfried
d94e47c757 spark: use proc_tools 2013-11-02 20:24:56 +01:00
Stefan Seyfried
1311c58e35 move glfb.h to include dir 2013-11-02 20:23:56 +01:00
Stefan Seyfried
1166d49486 all: clean up cAudio header, separate private stuff 2013-11-02 20:06:29 +01:00
Stefan Seyfried
69527185a9 all: clean up cVideo header, separate private stuff 2013-11-02 18:44:34 +01:00
Stefan Seyfried
5a56339925 all: clean up cDemux headers 2013-11-02 16:44:39 +01:00
martii
77f26b69a6 libeplayer3: speed up termination 2013-11-02 16:02:33 +01:00
Stefan Seyfried
60cc22c58a all: clean up cs_api.h / init_td.h 2013-11-02 14:27:47 +01:00
martii
7434bcacae libspark/player, libeplayer3/ffmpeg: improve termination handling 2013-11-02 12:58:29 +01:00
Stefan Seyfried
0bfaccd2ee generic-pc: clean up cAudio header, separate private stuff 2013-11-01 21:52:05 +01:00
Stefan Seyfried
50b1d46af1 raspi: clean up cAudio header 2013-11-01 21:09:27 +01:00
Stefan Seyfried
9563559afb generic-pc: remove unused stuff from playback.h header 2013-11-01 20:47:31 +01:00
Stefan Seyfried
cc973092ed generic-pc: fix build with gcc 4.8 2013-11-01 20:38:30 +01:00
Stefan Seyfried
04ae3878cc raspi: add missing include dir 2013-11-01 20:36:28 +01:00
martii
ab3a145c63 libspark/player: use int instead of short in some places 2013-10-31 15:58:49 +01:00
Stefan Seyfried
d0a4a496ec generic-pc: rework glfb / cVideo internals
* hide implementation details in private classes / objects
* remove unneccessary internals from library include files
The goal is to finally have identical include files for all
platforms to faciliate easy cross-platform library installation.
2013-10-31 08:48:44 +01:00
Stefan Seyfried
91775a6029 move dependent headers into one directory
in preparation of proper installation of the lib
2013-10-27 14:34:45 +01:00
Stefan Seyfried
ffc375869b raspi: add support for MPEG2
TODO: check if the MPEG2 license is present (and warn if not)
2013-10-22 01:14:58 +02:00
Stefan Seyfried
de0950ffa9 raspi: cover the linux framebuffer with black background 2013-10-22 00:37:19 +02:00
Stefan Seyfried
c697d633aa generic-pc: don't crash in getAudioInfo if no codec is set 2013-10-21 17:44:31 +02:00
Stefan Seyfried
03754e8bc5 playback: add dummy RequestAbort() functions 2013-10-21 17:32:21 +02:00
Stefan Seyfried
0b1c4bcb9c raspi: first try of aspect ratio setting
this needs more work / testing with 4:3 input material
2013-10-21 00:29:01 +02:00
Stefan Seyfried
a78e983d5f raspi: improve set_volume 2013-10-21 00:21:56 +02:00
Stefan Seyfried
e0f5184900 raspi: first implementation of PIG in AVDec 2013-10-21 00:08:47 +02:00
Stefan Seyfried
824c602fb6 raspi/glfb: export info about display 2013-10-21 00:02:34 +02:00
Stefan Seyfried
0e49bfdb00 raspi/avdec: improve demux read function 2013-10-20 22:36:52 +02:00
Stefan Seyfried
2f7cb6401f raspi/AVDec: various improvements for A/V decoders
* retry on errors in the decoding loop
* better interaction with avcodec_omx
2013-10-20 01:11:36 +02:00
Stefan Seyfried
2784941b7e raspi/avcodec_omx: various hacks to the state machine
* fix invalid locking when for MSG_NEWCHANNEL
* fix restarting video decoder with proper omx teardown
2013-10-20 01:05:30 +02:00
Stefan Seyfried
b424d34536 raspi/codec: fix memleak when skipping packets 2013-10-20 01:04:40 +02:00
Stefan Seyfried
4c13442e05 raspi/avdec: allow setting audio out via RASPI_AUDIO variable 2013-10-20 01:02:56 +02:00
Stefan Seyfried
d71ae5b4f9 raspi/omx_utils: fix ordering of shutdown sequence
apparently, all ports need to be disabled before the inter-component
tunnels are teared down, otherwise video_decodeRIL:image pool objects
will leak
see http://www.raspberrypi.org/phpBB3/viewtopic.php?f=70&t=48177
2013-10-20 00:47:03 +02:00
Stefan Seyfried
d736e87d4e raspi/glfb: clean up objects on exit, remove double buffer 2013-10-20 00:03:12 +02:00
Stefan Seyfried
48df8f882a raspi: fix ordering of AVDec and GLFB
it looks like the videocore libs are leaking objects if
OMX_Init() is called after the dispmanx setup, so do it
in the correct order
2013-10-19 22:59:41 +02:00
Stefan Seyfried
fa1eadcc56 fix wrong libtool initialization order
allow to build dynamic libraries (but keep static as default)
2013-10-14 00:35:55 +02:00
Stefan Seyfried
06035e8ea1 raspi/avcodec_omx: set thread names 2013-10-13 22:51:30 +02:00
Stefan Seyfried
e9b6f6c88b lt_debug: use C linkage, allows usage from non-C++ code 2013-10-13 22:43:19 +02:00
Stefan Seyfried
510b655710 raspi: use decoder implementation from pidvbip
* remove ilclient
* use a decoder implementation similar to pidvbip instead,
  see https://github.com/linuxstb/pidvbip
* video is decoded in hardware (videocore)
* audio is decoded by libavcodec
* add a AVDec wrapper class for both audio and video decoders
* very raw, needs more polishing. But decodes audio and video :-)
* only tested with h264
2013-10-13 22:36:45 +02:00
martii
ec58e86ae4 libeplayer3/ffmpeg: minor cleanup 2013-10-12 19:11:17 +02:00
Stefan Seyfried
19b0ff20e1 raspi: add first try of video decoder implementation
This is very raw and unfinished, it clearly needs some more polishing.
But it decodes h264 channels :-)
2013-10-10 00:10:21 +02:00
Stefan Seyfried
0f9bc4f95c raspi: switch demux target to internal decoder 2013-10-10 00:05:55 +02:00
Stefan Seyfried
7c942c3745 raspi: add ilclient files
these are from the raspberrypi firmware git example apps that
show how to use the videocore for encoding / decoding.
I'll try to use them for accessing the a / v decoders.
License is 3-Clause BSD and thus compatible with GPLv2.
2013-10-09 23:50:50 +02:00
martii
2f7d1b15e0 libeplayer3/playback: convert mms urls to mmst instead of rtsp 2013-08-18 19:10:18 +02:00
martii
7d34affd1d libeplayer3/manager: initialize track IDs 2013-08-16 19:50:20 +02:00
martii
370efa3852 libeplayer3: tracks update is now lock-free 2013-08-16 19:35:07 +02:00
martii
d1a2ceaa67 libeplayer3/container_ffmpeg: mutex fix 2013-08-16 14:33:30 +02:00
martii
f5f0eb0f26 libeplayer3/wmv: revert to (almost) original version 2013-08-15 17:05:55 +02:00
martii
2c6b721987 libeplayer/text_srt: minor optimization 2013-08-04 16:42:21 +02:00
martii
cb34d91c57 libeplayer3: drop non-shared framebuffer support 2013-08-04 16:22:07 +02:00
martii
be2ae1cbd8 libeplayer3: unbreak srt subs 2013-08-04 16:21:39 +02:00
martii
baff0efeb4 revert 286675f430 2013-08-02 15:07:15 +02:00
martii
78ae8e8a62 libeplayer3: divx fix 2013-08-02 14:37:03 +02:00
martii
45f4924ee4 libeplayer3: cleanup 2013-08-02 12:44:51 +02:00
martii
9dd8efc76d libeplayer3: vc1, wmv: use InsertPesHeader for initial PES headers, too 2013-08-02 08:37:17 +02:00
martii
9987291e36 libeplayer3/output/writer/: remove PesHeader memset (both wrong and unneeded) 2013-08-01 20:35:22 +02:00
martii
3738572731 libeplayer3 optimizations 2013-07-29 18:35:48 +02:00
martii
e11af5361b libeplayer3/container_ass: cosmetics 2013-07-28 14:40:30 +02:00
martii
81aeb8f182 libeplayer3/container_ffmpeg: cleanup 2013-07-28 13:04:20 +02:00
martii
6147c3ef5e libeplayer3/writer/framebuffer: small optimization 2013-07-28 12:33:24 +02:00
martii
ef7ba87754 libeplayer3/container_ass: set thread name 2013-07-28 11:40:42 +02:00
martii
1215ab73a3 libeplayer3/pcm: cleanup 2013-07-28 10:12:36 +02:00
martii
373976ca3d libeplayer3/pcm: minor clean-up, no code change 2013-07-28 10:06:21 +02:00
martii
c004f52cca Fix libeplayer3's broken PCM injection implementation. Jumps in movieplayer now works without losing a/v sync. 2013-07-28 09:54:39 +02:00
martii
4433f4ad43 libeplayer3/container_ffmpeg: don't flush instead of clear 2013-07-27 12:24:50 +02:00
martii
34cb8f4030 libeplayer3: use uint32_t for frame buffer access 2013-07-27 11:17:49 +02:00
martii
b6d6afc07f libeplayer3/continer_ass: crude hack to improve subtitle readability 2013-07-27 09:24:51 +02:00
martii
1fa3303cf7 libeplayer3/subtitles/spark: use backbuffer and blit 2013-07-27 08:12:03 +02:00
martii
6dba65cd53 libeplayer3/container_ass: font size adjusted 2013-07-26 22:50:26 +02:00
martii
0572e368df libeplayer/playback: disable subtitle init hack 2013-07-26 21:39:57 +02:00
martii
bed6d04851 libeplayer3/subtitle: reduce debugging level 2013-07-26 20:29:01 +02:00
martii
fbb8780418 libeplayer3: initial attempt to unbreak ass/ssa subtitles 2013-07-26 16:59:58 +02:00
martii
5734870578 libeplayer/linuxdvb: cleanup 2013-07-24 21:38:31 +02:00
martii
23da35350a libeplayer3/containter_ffmpeg: fix track update 2013-07-24 20:42:17 +02:00
martii
32f4d0b60b libeplayer3/container_ffmpeg: no need for copying the input packet 2013-07-23 21:45:44 +02:00
martii
65f9fc02d4 libeplayer/container_ffmpeg: subtitle fix 2013-07-23 21:00:14 +02:00
martii
2f34f9fd12 libeplayer3/container_ffmpeg.c: re-order packet.data check (not sure whether this is needed at all) 2013-07-22 18:39:11 +02:00
martii
1523ad974e libeplayer/container_ffmpeg: correct misplaced brackets 2013-07-21 19:50:14 +02:00
martii
ccc7f61813 libeplayer3/container_ffmpeg: initialize stream ids, if unset 2013-07-21 19:02:58 +02:00
martii
ac29852565 libeplayer3/container_ffmpeg: av_samples_alloc: use actual number for channels 2013-07-21 16:17:18 +02:00
martii
d461967885 libeplayer3/container_ffmpeg: align av_samples_alloc buffer 2013-07-21 16:11:53 +02:00
martii
23356fa5d8 libeplayer3/container_ffmpeg: fix mono->stereo conversion 2013-07-21 14:54:57 +02:00
martii
a4f6f6e6b4 libeplayer/container_ffmpeg: audio pts fix 2013-07-21 12:06:38 +02:00
martii
f8787493bf libeplayer3: remove outdated include/stm_ioctl.h 2013-07-20 15:36:22 +02:00
martii
6bb00d7bc7 container_ffmpeg: flush streams immediately after seek 2013-07-20 09:08:31 +02:00
martii
a1c809cd47 libeplayer3: cleanup 2013-07-19 14:36:25 +02:00
martii
025e2082e9 libeplayer: reduce debugging output 2013-07-19 10:43:56 +02:00
martii
44f19e563a h264: don't mess with packet length 2013-07-19 10:30:04 +02:00
martii
876c7e95e1 libeplayer3/h264: unbreak 2013-07-14 16:07:15 +02:00
martii
ea4054f258 libeplayer3/container_ffmpeg: No attributes needed for mutex init 2013-07-14 15:17:36 +02:00
martii
43f6a4cdb6 libeplayer3 cleanup 2013-07-14 14:55:48 +02:00
martii
13a488c1e3 libeplayer3/h264 cleanup 2013-07-14 13:36:19 +02:00
martii
28a5f96c8b libeplayer3: experimental h.264 playback fix 2013-07-14 13:30:50 +02:00
martii
ec73a2bcd4 libeplayer3: cleanup 2013-07-14 10:04:05 +02:00
martii
29d549ff3f libeplayer3: use actual pids instead of indexes 2013-07-12 22:34:39 +02:00
martii
233c330e4c ffmpeg-2.0 2013-07-10 19:27:57 +02:00
martii
42018c2f9c libeplayer3/container_ffmpeg: revert swr_next_pts call 2013-07-07 16:20:01 +02:00
martii
83756d1f9b libeplayer3: minor changes 2013-07-07 15:59:55 +02:00
martii
59d83d0bd4 libeplayer3: re-enable audio after seeking (still broken) 2013-07-07 10:34:29 +02:00
martii
fcd2c1b246 libeplayer3: need to call avcodec_free_frame after swresample, too 2013-07-06 17:06:01 +02:00
martii
4037122259 sync with seife 2013-06-19 12:41:13 +02:00
Stefan Seyfried
03c9c65bea modernize configure.ac and Makefile.am
autoconf-1.13 has new warnings, silence them by updating
the buildsystem
2013-06-16 22:16:12 +02:00
martii
b2eb2038d7 libeplayer3: the mp3 handler can easily take care of vorbis data, too. 2013-06-13 20:58:08 +02:00
martii
d2ee743530 libeplayer3: vorbis can easily be handled by the mp3 writer 2013-06-10 15:49:38 +02:00
martii
17a2a6553a libeplayer3/h264: disable debugging 2013-06-10 15:11:13 +02:00
martii
65e69b07fb libeplayer3: get rid of compiler warnings 2013-06-10 15:06:00 +02:00
martii
997af12a20 libeplayer3: drop legacy ffmpeg support 2013-06-10 13:13:52 +02:00
martii
429a9df2a5 libeplayer/h264: Fix playback. 2013-06-10 12:38:47 +02:00
martii
4b5228cfb0 libeplayer3: deactivate debugging 2013-06-08 12:34:19 +02:00
martii
4f56cae01d libeplayer3: cleanup 2013-06-08 12:05:36 +02:00
martii
6e25a6f00f libeplayer3: further malloc-memcpy-write -> writev replacements; not fully regression tested 2013-06-08 11:15:09 +02:00
martii
0d54652815 libeplayer3/h264: replace malloc/memcpy/write with writev 2013-06-08 10:19:40 +02:00
martii
076715fd68 libeplayer3: drop buffering code due to crashes 2013-06-07 15:16:29 +02:00
martii
b035d8ef59 replace libavresample with libswresample 2013-06-01 13:47:47 +02:00
martii
7b8f5aede9 libeplayer reverse play: experimental adjustment to find previous I-frame 2013-04-11 17:59:22 +02:00
martii
093b3fd51a libeplayer3: fix segv 2013-04-10 20:41:44 +02:00
martii
4a7c1fb975 eplayer3: subtitle fixes 2013-04-01 11:57:36 +02:00
martii
f3f3a49b87 crude hack for movieplayer tuxtxt integration 2013-03-31 11:55:51 +02:00
martii
76992e2f0c teletext handling changes 2013-03-29 18:14:52 +01:00
martii
997d162cd3 libeplayer3: dynamically update pid list 2013-03-25 20:42:36 +01:00
martii
9e74193f34 libeplayer3/playback_libeplayer3: change noprobe handling 2013-03-18 18:49:00 +01:00
martii
1a499b7054 libeplayer/container_ffmpeg: use injected PCM for raw PCM, too 2013-03-17 09:47:18 +01:00
martii
bd87abd06b libeplayer3/container_ffmpeg: handle .wtv extensions, too 2013-03-16 19:43:25 +01:00
martii
0cdfdc60ae libeplayer3/container_ffmpeg: fix WMA playback 2013-03-16 18:24:49 +01:00
martii
f546bd5218 libeplayer3: add callback to abort avformat_open_input 2013-03-10 15:44:30 +01:00
martii
bf87a25c4d libeplayer3/container_ffmpeg: cleanup 2013-03-09 16:40:54 +01:00
martii
ee0e87dc05 libeplayer3/container_ffmpeg: cleanup 2013-03-09 16:37:05 +01:00
martii
78c53d1baa libeplayer3: merge buffered IO code from TDT; implement proper audio resampling 2013-03-09 14:47:34 +01:00
martii
ba9ba931ed libeplayer3/container_ffmpeg: minor cleanup 2013-03-04 19:22:47 +01:00
martii
4417f2549d libeplayer3/container_ffmpeg: no need to scale the buffer 2013-03-04 17:37:44 +01:00
martii
8d5e5a7cd2 libeplayer3: this may improve recovery from broken streams 2013-03-03 20:55:39 +01:00
martii
d4c0cfe133 libeplayer3: switch back to software decoding for AAC; crude fix for PCM injection (newer ffmpeg versions return floats instead of shorts), injected PCM streams (OGG, for example), will now work again. I'd be grateful if anybody with a deeper understanding of the FFMPEG API would supply a cleaner fix ... 2013-03-03 13:38:39 +01:00
martii
17f3713093 libeplayer: set 65535 as maximum PES length 2013-02-26 19:57:15 +01:00
martii
9bb9a8d5fd libeplayer: assume unlimited PES length for too large packets 2013-02-26 19:56:08 +01:00
martii
a367d1f5db sync with seife 2013-01-30 19:13:45 +01:00
martii
3641f0ef6f libeplayer3: experimental fixes 2013-01-17 18:37:45 +01:00
Stefan Seyfried
3f2a7a8809 deuglify library build
* build intermediate libraries for each subdirectory
* link those libs in main directory instead of single objects
* ugly hack in configure.ac to disable dynamic lib for now
2012-12-01 13:29:27 +01:00
martii
a8bb8bb705 libeplayer/playback: initialize length to -1 2012-11-12 14:20:55 +01:00
martii
0243da9367 libeplayer3 fix 2012-11-10 13:41:59 +01:00
martii
83fe4c7174 libeplayer3: check for valid avContext pointer 2012-11-09 17:43:11 +01:00
martii
0d9281063b improve subtitle handling 2012-11-06 14:34:31 +01:00
martii
4a7345e6e6 sync 2012-11-04 18:46:58 +01:00
martii
41daed4748 libspark/libeplayer: rudimentary subtitle support, probably unstable 2012-11-04 15:39:48 +01:00
Stefan Seyfried
e544fab4f2 libeplayer3: sync with tdt git commit 06fe782fd6
This ports this commit:
    Author: Matthias <matthias@Build-VM.(none)>
    Date:   Fri Oct 26 19:54:46 2012 +0200

        [libeplayer3] enable wav payback (16 bit le)
2012-11-03 17:25:52 +01:00
martii
986b39c04e get rid of most compiler warnings 2012-10-27 18:08:29 +02:00
martii
65c64c77b4 enable wav payback (16 bit le) (from TDT, thanks hellmaster1024) 2012-10-27 18:07:02 +02:00
martii
8b33e32cf8 libeplayer3: disable noprobe hack 2012-10-04 09:42:28 +02:00
martii
bf7e63689d sync 2012-10-04 09:32:05 +02:00
Stefan Seyfried
ed10c47327 libeplayer3: fix invalid free()
according to the man pages....
* dirname() can not return NULL
* the pointer returned by dirname must not be free()d
* strdup() can return NULL
2012-10-04 00:02:51 +02:00
Stefan Seyfried
c048f57223 libeplayer3: sync with tdt git commit fed2a419dc 2012-10-03 23:51:56 +02:00
Stefan Seyfried
df067953b4 libeplayer3: add hack to decrease libavcodec probe size
almost disable the libavcodec format probing when using
"myts://" instead of "file://" urls to improve startup speed
for timeshift etc
2012-10-03 23:22:58 +02:00
martii
07a0da1b99 eplayer3 h263 fix 2012-08-31 12:33:59 +02:00
martii
4d1b35e4ac fix indent 2012-08-13 18:42:15 +02:00
martii
2627072d1d libeplayer3: add support for teletext and dvbsubtitle streams 2012-08-04 13:31:28 +02:00
martii
1bcc899430 fix some movieplayer issues 2012-07-27 20:09:26 +02:00
martii
60aeebb68e libeplayer3: sync with tdt 2012-07-21 21:03:59 +02:00
martii
94d8b8b57d support newer ffmpeg versions 2012-07-13 16:22:19 +02:00
Stefan Seyfried
6f8ce7c8ca libeplayer3: silence a seemingly harmless warning 2012-04-08 17:16:06 +02:00
Stefan Seyfried
91582dc5af libeplayer3: get rid of __FILE__ for shorter logmessages 2012-02-26 16:11:45 +01:00
Stefan Seyfried
b83945b4ce libeplayer3: silence many warnings 2012-02-18 12:06:10 +01:00
Stefan Seyfried
ba958c809d build static libeplayer3 and link eplayer3 and meta against it 2012-02-18 12:05:11 +01:00
Stefan Seyfried
2693d2a21e spark: build libeplayer3 statically into libstb-hal 2012-02-15 00:17:38 +01:00
Stefan Seyfried
1005c3f53e add libeplayer3 from tdt git
This imports libeplayer3 as of commit 9160371ccc6 (2012-02-02)
git://gitorious.org/open-duckbox-project-sh4/tdt.git
It would be better to use the original repo, but I need too many
changes for now :-(
2012-02-14 23:01:24 +01:00
339 changed files with 16601 additions and 58032 deletions

67
.gitignore vendored
View File

@@ -1,68 +1,19 @@
### http://www.gnu.org/software/automake
Makefile
Makefile.in
### http://www.gnu.org/software/autoconf
autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/autom4te.cache/
Makefile.in
/config.guess
/config.h.in
/config.log
/config.status
/config.sub
*/*-config.h
*/*-config.h.in
/configure
/configure.scan
/compile
*.directory
/depcomp
/install-sh
/missing
/stamp-h*
### https://www.gnu.org/software/libtool/
/libtool
/ltmain.sh
### http://www.gnu.org/software/m4/
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
### compiled objects and libs
.libs
*.lo
/m4/
/missing
*.*~
*.o
*.so
*.lai
*.la
*.a
### dependency files
.deps
*.Plo
*.Po
### diff and patch files
*.patch
*.diff
*.orig
*.rej
### system generated stuff
# dolphin
.directory
# kate
*-swp
.*.swp
### generally excluded files
*~
*.pc
git-*
go_*
### header files that fall out of the build
libstb-hal-config.h

339
COPYING
View File

@@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

2537
ChangeLog

File diff suppressed because it is too large Load Diff

View File

View File

@@ -3,81 +3,61 @@ ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libstb-hal.la
libstb_hal_la_SOURCES =
SUBDIRS = common tools
#bin_PROGRAMS = libstb-hal-test
libstb_hal_la_LIBADD = \
common/libcommon.la
#bin_PROGRAMS = libstb-hal-test
#libstb_hal_test_SOURCES = libtest.cpp
#libstb_hal_test_LDADD = libstb-hal.la
libstb_hal_la_LDFLAGS = -version-info 1:0:1
libstb_hal_test_SOURCES = libtest.cpp
libstb_hal_test_LDADD = libstb-hal.la
# there has to be a better way to do this...
if BOXTYPE_TRIPLE
SUBDIRS += libtriple
libstb_hal_la_LIBADD += \
libtriple/libtriple.la
endif
if BOXTYPE_AZBOX
SUBDIRS += azbox
libstb_hal_la_LIBADD += \
azbox/libazbox.la
endif
if BOXTYPE_GENERIC
if BOXMODEL_RASPI
SUBDIRS += libraspi
SUBDIRS += raspi
libstb_hal_la_LIBADD += \
libraspi/libraspi.la
raspi/libraspi.la
else
SUBDIRS += libgeneric-pc
SUBDIRS += generic-pc
libstb_hal_la_LIBADD += \
libgeneric-pc/libgeneric.la
generic-pc/libgeneric.la
endif
endif
if BOXTYPE_SPARK
#libstb_hal_test_LDADD += -lasound
SUBDIRS += libspark libeplayer3-sh4
SUBDIRS += libspark libeplayer3
libstb_hal_la_LIBADD += \
libspark/libspark.la \
libeplayer3-sh4/libeplayer3_sh4.la
endif
if BOXTYPE_DUCKBOX
#libstb_hal_test_LDADD += -lasound
SUBDIRS += libduckbox libeplayer3-sh4 libdvbci
libstb_hal_la_LIBADD += \
libduckbox/libduckbox.la \
libeplayer3-sh4/libeplayer3_sh4.la \
libdvbci/libdvbci.la
endif
if BOXTYPE_ARMBOX
if BOXMODEL_HD60
SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
if BOXMODEL_OSMIO4K
SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
if BOXMODEL_OSMIO4KPLUS
SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
#libstb_hal_test_LDADD += -lasound
SUBDIRS += libarmbox libdvbci
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la \
libdvbci/libdvbci.la
endif
endif
endif
if !ENABLE_GSTREAMER_10
SUBDIRS += libeplayer3
libstb_hal_la_LIBADD += \
libeplayer3/libeplayer3.la
endif
endif
if BOXTYPE_MIPSBOX
SUBDIRS += libmipsbox libdvbci
libstb_hal_la_LIBADD += \
libmipsbox/libmipsbox.la \
libdvbci/libdvbci.la
SUBDIRS += libeplayer3
libstb_hal_la_LIBADD += \
libeplayer3/libeplayer3.la
endif
pkginclude_HEADERS = \
include/audio_hal.h \
include/ca_cs.h \
include/ca.h \
include/cs_api.h \
include/cs_types.h \
include/dmx_cs.h \
include/dmx_hal.h \
include/glfb.h \
include/hardware_caps.h \
include/init_cs.h \
include/init_td.h \
include/mmi.h \
include/playback.h \
include/playback_hal.h \
include/pwrmngr.h \
include/record_hal.h \
include/version_hal.h \
include/video_cs.h

View File

@@ -1,2 +0,0 @@
libstb-hal
==========

View File

@@ -1,27 +1,24 @@
AC_DEFUN([TUXBOX_APPS], [
AC_DEFUN([TUXBOX_APPS],[
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_GNU_SOURCE
AC_SYS_LARGEFILE
AC_ARG_WITH(target,
AS_HELP_STRING([--with-target=TARGET], [target for compilation [[native,cdk]]]),
[TARGET="$withval"],
[TARGET="native"])
[ --with-target=TARGET target for compilation [[native,cdk]]],
[TARGET="$withval"],[TARGET="native"])
AC_ARG_WITH(targetprefix,
AS_HELP_STRING([--with-targetprefix=PATH], [prefix relative to target root (only applicable in cdk mode)]),
[TARGET_PREFIX="$withval"],
[TARGET_PREFIX=""])
[ --with-targetprefix=PATH prefix relative to target root (only applicable in cdk mode)],
[targetprefix="$withval"],[targetprefix="NONE"])
AC_ARG_WITH(debug,
AS_HELP_STRING([--without-debug], [disable debugging code @<:@default=no@:>@]),
[DEBUG="$withval"],
[DEBUG="yes"])
[ --without-debug disable debugging code],
[DEBUG="$withval"],[DEBUG="yes"])
if test "$DEBUG" = "yes"; then
DEBUG_CFLAGS="-g3 -ggdb"
AC_DEFINE(DEBUG, 1, [enable debugging code])
AC_DEFINE(DEBUG,1,[Enable debug messages])
fi
AC_MSG_CHECKING(target)
@@ -37,341 +34,238 @@ if test "$TARGET" = "native"; then
prefix=/usr/local
fi
targetprefix=$prefix
TARGET_PREFIX=$prefix
AC_DEFINE_UNQUOTED(TARGET_PREFIX, "$TARGET_PREFIX", [The targets prefix])
elif test "$TARGET" = "cdk"; then
AC_MSG_RESULT(cdk)
if test "$CC" = "" -a "$CXX" = ""; then
AC_MSG_ERROR([you need to specify variables CC or CXX in cdk])
fi
if test "$CFLAGS" = "" -o "$CXXFLAGS" = ""; then
AC_MSG_ERROR([you need to specify variables CFLAGS and CXXFLAGS in cdk])
fi
if test "$prefix" = "NONE"; then
AC_MSG_ERROR([invalid prefix, you need to specify one in cdk mode])
AC_MSG_ERROR(invalid prefix, you need to specify one in cdk mode)
fi
if test "$TARGET_PREFIX" != "NONE"; then
AC_DEFINE_UNQUOTED(TARGET_PREFIX, "$TARGET_PREFIX", [The targets prefix])
fi
if test "$TARGET_PREFIX" = "NONE"; then
AC_MSG_ERROR([invalid targetprefix, you need to specify one in cdk mode])
TARGET_PREFIX=""
if test "$targetprefix" = "NONE"; then
targetprefix=""
fi
else
AC_MSG_RESULT(none)
AC_MSG_ERROR([invalid target $TARGET, choose on from native,cdk]);
fi
if test "$exec_prefix" = "NONE"; then
exec_prefix=$prefix
fi
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_SYS_LARGEFILE
])
AC_DEFUN([TUXBOX_BOXTYPE], [
dnl expand nested ${foo}/bar
AC_DEFUN([TUXBOX_EXPAND_VARIABLE],[__$1="$2"
for __CNT in false false false false true; do dnl max 5 levels of indirection
$1=`eval echo "$__$1"`
echo ${$1} | grep -q '\$' || break # 'grep -q' is POSIX, exit if no $ in variable
__$1="${$1}"
done
$__CNT && AC_MSG_ERROR([can't expand variable $1=$2]) dnl bail out if we did not expand
])
AC_DEFUN([TUXBOX_APPS_DIRECTORY_ONE],[
AC_ARG_WITH($1,[ $6$7 [[PREFIX$4$5]]],[
_$2=$withval
if test "$TARGET" = "cdk"; then
$2=`eval echo "${targetprefix}$withval"` # no indirection possible IMNSHO
else
$2=$withval
fi
TARGET_$2=${$2}
],[
# RFC 1925: "you can always add another level of indirection..."
TUXBOX_EXPAND_VARIABLE($2,"${$3}$5")
if test "$TARGET" = "cdk"; then
TUXBOX_EXPAND_VARIABLE(_$2,"${target$3}$5")
else
_$2=${$2}
fi
TARGET_$2=$_$2
])
dnl automake <= 1.6 don't support this
dnl AC_SUBST($2)
AC_DEFINE_UNQUOTED($2,"$_$2",$7)
AC_SUBST(TARGET_$2)
])
AC_DEFUN([TUXBOX_APPS_DIRECTORY],[
AC_REQUIRE([TUXBOX_APPS])
if test "$TARGET" = "cdk"; then
datadir="\${prefix}/share"
sysconfdir="\${prefix}/etc"
localstatedir="\${prefix}/var"
libdir="\${prefix}/lib"
targetdatadir="\${targetprefix}/share"
targetsysconfdir="\${targetprefix}/etc"
targetlocalstatedir="\${targetprefix}/var"
targetlibdir="\${targetprefix}/lib"
fi
TUXBOX_APPS_DIRECTORY_ONE(configdir,CONFIGDIR,localstatedir,/var,/tuxbox/config,
[--with-configdir=PATH ],[where to find the config files])
TUXBOX_APPS_DIRECTORY_ONE(datadir,DATADIR,datadir,/share,/tuxbox,
[--with-datadir=PATH ],[where to find data])
TUXBOX_APPS_DIRECTORY_ONE(fontdir,FONTDIR,datadir,/share,/fonts,
[--with-fontdir=PATH ],[where to find the fonts])
TUXBOX_APPS_DIRECTORY_ONE(gamesdir,GAMESDIR,localstatedir,/var,/tuxbox/games,
[--with-gamesdir=PATH ],[where games data is stored])
TUXBOX_APPS_DIRECTORY_ONE(libdir,LIBDIR,libdir,/lib,/tuxbox,
[--with-libdir=PATH ],[where to find the internal libs])
TUXBOX_APPS_DIRECTORY_ONE(plugindir,PLUGINDIR,libdir,/lib,/tuxbox/plugins,
[--with-plugindir=PATH ],[where to find the plugins])
TUXBOX_APPS_DIRECTORY_ONE(ucodedir,UCODEDIR,localstatedir,/var,/tuxbox/ucodes,
[--with-ucodedir=PATH ],[where to find the ucodes])
TUXBOX_APPS_DIRECTORY_ONE(themesdir,THEMESDIR,datadir,/share,/tuxbox/neutrino/themes,
[--with-themesdir=PATH ],[where to find the themes (don't change)])
])
dnl automake <= 1.6 needs this specifications
AC_SUBST(CONFIGDIR)
AC_SUBST(DATADIR)
AC_SUBST(FONTDIR)
AC_SUBST(GAMESDIR)
AC_SUBST(LIBDIR)
AC_SUBST(PLUGINDIR)
AC_SUBST(UCODEDIR)
AC_SUBST(THEMESDIR)
dnl end workaround
AC_DEFUN([TUXBOX_BOXTYPE],[
AC_ARG_WITH(boxtype,
AS_HELP_STRING([--with-boxtype], [valid values: generic, spark, duckbox, armbox, mipsbox]),
[ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic],
[case "${withval}" in
generic|spark|duckbox|armbox|mipsbox)
dbox2|dreambox|ipbox|tripledragon|coolstream|spark|azbox|generic)
BOXTYPE="$withval"
;;
;;
dm*)
BOXTYPE="dreambox"
BOXMODEL="$withval"
;;
*)
AC_MSG_ERROR([bad value $withval for --with-boxtype])
;;
esac],
[BOXTYPE="generic"])
AC_MSG_ERROR([bad value $withval for --with-boxtype]) ;;
esac], [BOXTYPE="generic"])
AC_ARG_WITH(boxmodel,
AS_HELP_STRING([--with-boxmodel], [valid for generic: generic, raspi])
AS_HELP_STRING([], [valid for spark: spark, spark7162])
AS_HELP_STRING([], [valid for duckbox: ufs910, ufs912, ufs913, ufs922, atevio7500, fortis_hdbox, octagon1008, hs7110, hs7810a, hs7119, hs7819, dp7000, cuberevo, cuberevo_mini, cuberevo_mini2, cuberevo_250hd, cuberevo_2000hd, cuberevo_3000hd, ipbox9900, ipbox99, ipbox55, arivalink200, tf7700, hl101])
AS_HELP_STRING([], [valid for armbox: hd51, hd60, hd61, bre2ze4k, h7, osmio4k, osmio4kplus, vusolo4k, vuduo4k, vuduo4kse, vuultimo4k, vuuno4k, vuuno4kse, vuzero4k])
AS_HELP_STRING([], [valid for mipsbox: vuduo]),
[ --with-boxmodel valid for dreambox: dm500, dm500plus, dm600pvr, dm56x0, dm7000, dm7020, dm7025
valid for ipbox: ip200, ip250, ip350, ip400],
[case "${withval}" in
generic|raspi)
dm500|dm500plus|dm600pvr|dm56x0|dm7000|dm7020|dm7025)
if test "$BOXTYPE" = "dreambox"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
ip200|ip250|ip350|ip400)
if test "$BOXTYPE" = "ipbox"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
raspi)
if test "$BOXTYPE" = "generic"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
spark|spark7162)
if test "$BOXTYPE" = "spark"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
ufs910|ufs912|ufs913|ufs922|atevio7500|fortis_hdbox|octagon1008|hs7110|hs7810a|hs7119|hs7819|dp7000|cuberevo|cuberevo_mini|cuberevo_mini2|cuberevo_250hd|cuberevo_2000hd|cuberevo_3000hd|ipbox9900|ipbox99|ipbox55|arivalink200|tf7700|hl101)
if test "$BOXTYPE" = "duckbox"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
hd51|hd60|hd61|bre2ze4k|h7|osmio4k|osmio4kplus|vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k)
if test "$BOXTYPE" = "armbox"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
vuduo)
if test "$BOXTYPE" = "mipsbox"; then
BOXMODEL="$withval"
else
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
;;
*)
AC_MSG_ERROR([unsupported value $withval for --with-boxmodel])
;;
;;
esac],
[BOXMODEL="generic"])
[if test "$BOXTYPE" = "dreambox" -o "$BOXTYPE" = "ipbox" && test -z "$BOXMODEL"; then
AC_MSG_ERROR([Dreambox/IPBox needs --with-boxmodel])
fi])
AC_SUBST(BOXTYPE)
AC_SUBST(BOXMODEL)
AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic")
AM_CONDITIONAL(BOXTYPE_AZBOX, test "$BOXTYPE" = "azbox")
AM_CONDITIONAL(BOXTYPE_DBOX2, test "$BOXTYPE" = "dbox2")
AM_CONDITIONAL(BOXTYPE_TRIPLE, test "$BOXTYPE" = "tripledragon")
AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark")
AM_CONDITIONAL(BOXTYPE_DUCKBOX, test "$BOXTYPE" = "duckbox")
AM_CONDITIONAL(BOXTYPE_ARMBOX, test "$BOXTYPE" = "armbox")
AM_CONDITIONAL(BOXTYPE_MIPSBOX, test "$BOXTYPE" = "mipsbox")
AM_CONDITIONAL(BOXTYPE_DREAMBOX, test "$BOXTYPE" = "dreambox")
AM_CONDITIONAL(BOXTYPE_IPBOX, test "$BOXTYPE" = "ipbox")
AM_CONDITIONAL(BOXTYPE_COOL, test "$BOXTYPE" = "coolstream")
AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic")
# generic
AM_CONDITIONAL(BOXMODEL_GENERIC, test "$BOXMODEL" = "generic")
AM_CONDITIONAL(BOXMODEL_RASPI, test "$BOXMODEL" = "raspi")
AM_CONDITIONAL(BOXMODEL_DM500,test "$BOXMODEL" = "dm500")
AM_CONDITIONAL(BOXMODEL_DM500PLUS,test "$BOXMODEL" = "dm500plus")
AM_CONDITIONAL(BOXMODEL_DM600PVR,test "$BOXMODEL" = "dm600pvr")
AM_CONDITIONAL(BOXMODEL_DM56x0,test "$BOXMODEL" = "dm56x0")
AM_CONDITIONAL(BOXMODEL_DM7000,test "$BOXMODEL" = "dm7000" -o "$BOXMODEL" = "dm7020" -o "$BOXMODEL" = "dm7025")
# spark
AM_CONDITIONAL(BOXMODEL_SPARK, test "$BOXMODEL" = "spark")
AM_CONDITIONAL(BOXMODEL_SPARK7162, test "$BOXMODEL" = "spark7162")
AM_CONDITIONAL(BOXMODEL_IP200,test "$BOXMODEL" = "ip200")
AM_CONDITIONAL(BOXMODEL_IP250,test "$BOXMODEL" = "ip250")
AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350")
AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400")
# duckbox
AM_CONDITIONAL(BOXMODEL_UFS910, test "$BOXMODEL" = "ufs910")
AM_CONDITIONAL(BOXMODEL_UFS912, test "$BOXMODEL" = "ufs912")
AM_CONDITIONAL(BOXMODEL_UFS913, test "$BOXMODEL" = "ufs913")
AM_CONDITIONAL(BOXMODEL_UFS922, test "$BOXMODEL" = "ufs922")
AM_CONDITIONAL(BOXMODEL_SPARK, test "$BOXMODEL" = "spark")
AM_CONDITIONAL(BOXMODEL_SPARK7162, test "$BOXMODEL" = "spark7162")
AM_CONDITIONAL(BOXMODEL_ATEVIO7500, test "$BOXMODEL" = "atevio7500")
AM_CONDITIONAL(BOXMODEL_FORTIS_HDBOX, test "$BOXMODEL" = "fortis_hdbox")
AM_CONDITIONAL(BOXMODEL_OCTAGON1008, test "$BOXMODEL" = "octagon1008")
AM_CONDITIONAL(BOXMODEL_HS7110, test "$BOXMODEL" = "hs7110")
AM_CONDITIONAL(BOXMODEL_HS7810A, test "$BOXMODEL" = "hs7810a")
AM_CONDITIONAL(BOXMODEL_HS7119, test "$BOXMODEL" = "hs7119")
AM_CONDITIONAL(BOXMODEL_HS7819, test "$BOXMODEL" = "hs7819")
AM_CONDITIONAL(BOXMODEL_DP7000, test "$BOXMODEL" = "dp7000")
AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi")
AM_CONDITIONAL(BOXMODEL_CUBEREVO, test "$BOXMODEL" = "cuberevo")
AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI, test "$BOXMODEL" = "cuberevo_mini")
AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI2, test "$BOXMODEL" = "cuberevo_mini2")
AM_CONDITIONAL(BOXMODEL_CUBEREVO_250HD, test "$BOXMODEL" = "cuberevo_250hd")
AM_CONDITIONAL(BOXMODEL_CUBEREVO_2000HD, test "$BOXMODEL" = "cuberevo_2000hd")
AM_CONDITIONAL(BOXMODEL_CUBEREVO_3000HD, test "$BOXMODEL" = "cuberevo_3000hd")
AM_CONDITIONAL(BOXMODEL_IPBOX9900, test "$BOXMODEL" = "ipbox9900")
AM_CONDITIONAL(BOXMODEL_IPBOX99, test "$BOXMODEL" = "ipbox99")
AM_CONDITIONAL(BOXMODEL_IPBOX55, test "$BOXMODEL" = "ipbox55")
AM_CONDITIONAL(BOXMODEL_ARIVALINK200, test "$BOXMODEL" = "arivalink200")
AM_CONDITIONAL(BOXMODEL_TF7700, test "$BOXMODEL" = "tf7700")
AM_CONDITIONAL(BOXMODEL_HL101, test "$BOXMODEL" = "hl101")
# armbox
AM_CONDITIONAL(BOXMODEL_HD51, test "$BOXMODEL" = "hd51")
AM_CONDITIONAL(BOXMODEL_HD60, test "$BOXMODEL" = "hd60")
AM_CONDITIONAL(BOXMODEL_HD61, test "$BOXMODEL" = "hd61")
AM_CONDITIONAL(BOXMODEL_BRE2ZE4K, test "$BOXMODEL" = "bre2ze4k")
AM_CONDITIONAL(BOXMODEL_H7, test "$BOXMODEL" = "h7")
AM_CONDITIONAL(BOXMODEL_OSMIO4K, test "$BOXMODEL" = "osmio4k")
AM_CONDITIONAL(BOXMODEL_OSMIO4KPLUS, test "$BOXMODEL" = "osmio4kplus")
AM_CONDITIONAL(BOXMODEL_VUSOLO4K, test "$BOXMODEL" = "vusolo4k")
AM_CONDITIONAL(BOXMODEL_VUDUO4K, test "$BOXMODEL" = "vuduo4k")
AM_CONDITIONAL(BOXMODEL_VUDUO4KSE, test "$BOXMODEL" = "vuduo4kse")
AM_CONDITIONAL(BOXMODEL_VUULTIMO4K, test "$BOXMODEL" = "vuultimo4k")
AM_CONDITIONAL(BOXMODEL_VUUNO4K, test "$BOXMODEL" = "vuuno4k")
AM_CONDITIONAL(BOXMODEL_VUUNO4KSE, test "$BOXMODEL" = "vuuno4kse")
AM_CONDITIONAL(BOXMODEL_VUZERO4K, test "$BOXMODEL" = "vuzero4k")
# mipsbox
AM_CONDITIONAL(BOXMODEL_VUDUO, test "$BOXMODEL" = "vuduo")
if test "$BOXTYPE" = "generic"; then
AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC])
if test "$BOXTYPE" = "dbox2"; then
AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2])
elif test "$BOXTYPE" = "azbox"; then
AC_DEFINE(HAVE_AZBOX_HARDWARE, 1, [building for an azbox])
elif test "$BOXTYPE" = "tripledragon"; then
AC_DEFINE(HAVE_TRIPLEDRAGON, 1, [building for a tripledragon])
elif test "$BOXTYPE" = "spark"; then
AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux])
AC_DEFINE(HAVE_SH4_HARDWARE, 1, [building for a sh4 box])
elif test "$BOXTYPE" = "duckbox"; then
AC_DEFINE(HAVE_DUCKBOX_HARDWARE, 1, [building for a duckbox])
AC_DEFINE(HAVE_SH4_HARDWARE, 1, [building for a sh4 box])
elif test "$BOXTYPE" = "armbox"; then
AC_DEFINE(HAVE_ARM_HARDWARE, 1, [building for an armbox])
elif test "$BOXTYPE" = "mipsbox"; then
AC_DEFINE(HAVE_MIPS_HARDWARE, 1, [building for an mipsbox])
AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a spark st7111 box])
elif test "$BOXTYPE" = "dreambox"; then
AC_DEFINE(HAVE_DREAMBOX_HARDWARE, 1, [building for a dreambox])
elif test "$BOXTYPE" = "ipbox"; then
AC_DEFINE(HAVE_IPBOX_HARDWARE, 1, [building for an ipbox])
elif test "$BOXTYPE" = "coolstream"; then
AC_DEFINE(HAVE_COOL_HARDWARE, 1, [building for a coolstream])
elif test "$BOXTYPE" = "generic"; then
AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC])
fi
# TODO: do we need more defines?
if test "$BOXMODEL" = "generic"; then
AC_DEFINE(BOXMODEL_GENERIC, 1, [generic pc])
if test "$BOXMODEL" = "dm500"; then
AC_DEFINE(BOXMODEL_DM500, 1, [dreambox 500])
elif test "$BOXMODEL" = "ip200"; then
AC_DEFINE(BOXMODEL_IP200, 1, [ipbox 200])
elif test "$BOXMODEL" = "ip250"; then
AC_DEFINE(BOXMODEL_IP250, 1, [ipbox 250])
elif test "$BOXMODEL" = "ip350"; then
AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350])
elif test "$BOXMODEL" = "ip400"; then
AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400])
elif test "$BOXMODEL" = "raspi"; then
AC_DEFINE(BOXMODEL_RASPI, 1, [raspberry pi])
elif test "$BOXMODEL" = "ufs910"; then
AC_DEFINE(BOXMODEL_UFS910, 1, [ufs910])
elif test "$BOXMODEL" = "ufs912"; then
AC_DEFINE(BOXMODEL_UFS912, 1, [ufs912])
elif test "$BOXMODEL" = "ufs913"; then
AC_DEFINE(BOXMODEL_UFS913, 1, [ufs913])
elif test "$BOXMODEL" = "ufs922"; then
AC_DEFINE(BOXMODEL_UFS922, 1, [ufs922])
elif test "$BOXMODEL" = "spark"; then
AC_DEFINE(BOXMODEL_SPARK, 1, [spark])
elif test "$BOXMODEL" = "spark7162"; then
AC_DEFINE(BOXMODEL_SPARK7162, 1, [spark7162])
elif test "$BOXMODEL" = "atevio7500"; then
AC_DEFINE(BOXMODEL_ATEVIO7500, 1, [atevio7500])
elif test "$BOXMODEL" = "fortis_hdbox"; then
AC_DEFINE(BOXMODEL_FORTIS_HDBOX, 1, [fortis_hdbox])
elif test "$BOXMODEL" = "octagon1008"; then
AC_DEFINE(BOXMODEL_OCTAGON1008, 1, [octagon1008])
elif test "$BOXMODEL" = "hs7110"; then
AC_DEFINE(BOXMODEL_HS7110, 1, [hs7110])
elif test "$BOXMODEL" = "hs7810a"; then
AC_DEFINE(BOXMODEL_HS7810A, 1, [hs7810a])
elif test "$BOXMODEL" = "hs7119"; then
AC_DEFINE(BOXMODEL_HS7119, 1, [hs7119])
elif test "$BOXMODEL" = "hs7819"; then
AC_DEFINE(BOXMODEL_HS7819, 1, [hs7819])
elif test "$BOXMODEL" = "dp7000"; then
AC_DEFINE(BOXMODEL_DP7000, 1, [dp7000])
elif test "$BOXMODEL" = "cuberevo"; then
AC_DEFINE(BOXMODEL_CUBEREVO, 1, [cuberevo])
elif test "$BOXMODEL" = "cuberevo_mini"; then
AC_DEFINE(BOXMODEL_CUBEREVO_MINI, 1, [cuberevo_mini])
elif test "$BOXMODEL" = "cuberevo_mini2"; then
AC_DEFINE(BOXMODEL_CUBEREVO_MINI2, 1, [cuberevo_mini2])
elif test "$BOXMODEL" = "cuberevo_250hd"; then
AC_DEFINE(BOXMODEL_CUBEREVO_250HD, 1, [cuberevo_250hd])
elif test "$BOXMODEL" = "cuberevo_2000hd"; then
AC_DEFINE(BOXMODEL_CUBEREVO_2000HD, 1, [cuberevo_2000hd])
elif test "$BOXMODEL" = "cuberevo_3000hd"; then
AC_DEFINE(BOXMODEL_CUBEREVO_3000HD, 1, [cuberevo_3000hd])
elif test "$BOXMODEL" = "ipbox9900"; then
AC_DEFINE(BOXMODEL_IPBOX9900, 1, [ipbox9900])
elif test "$BOXMODEL" = "ipbox99"; then
AC_DEFINE(BOXMODEL_IPBOX99, 1, [ipbox99])
elif test "$BOXMODEL" = "ipbox55"; then
AC_DEFINE(BOXMODEL_IPBOX55, 1, [ipbox55])
elif test "$BOXMODEL" = "arivalink200"; then
AC_DEFINE(BOXMODEL_ARIVALINK200, 1, [arivalink200])
elif test "$BOXMODEL" = "tf7700"; then
AC_DEFINE(BOXMODEL_TF7700, 1, [tf7700])
elif test "$BOXMODEL" = "hl101"; then
AC_DEFINE(BOXMODEL_HL101, 1, [hl101])
elif test "$BOXMODEL" = "hd51"; then
AC_DEFINE(BOXMODEL_HD51, 1, [hd51])
elif test "$BOXMODEL" = "hd60"; then
AC_DEFINE(BOXMODEL_HD60, 1, [hd60])
elif test "$BOXMODEL" = "hd61"; then
AC_DEFINE(BOXMODEL_HD61, 1, [hd61])
elif test "$BOXMODEL" = "bre2ze4k"; then
AC_DEFINE(BOXMODEL_BRE2ZE4K, 1, [bre2ze4k])
elif test "$BOXMODEL" = "h7"; then
AC_DEFINE(BOXMODEL_H7, 1, [h7])
elif test "$BOXMODEL" = "osmio4k"; then
AC_DEFINE(BOXMODEL_OSMIO4K, 1, [osmio4k])
elif test "$BOXMODEL" = "osmio4kplus"; then
AC_DEFINE(BOXMODEL_OSMIO4KPLUS, 1, [osmio4kplus])
elif test "$BOXMODEL" = "vusolo4k"; then
AC_DEFINE(BOXMODEL_VUSOLO4K, 1, [vusolo4k])
elif test "$BOXMODEL" = "vuduo4k"; then
AC_DEFINE(BOXMODEL_VUDUO4K, 1, [vuduo4k])
elif test "$BOXMODEL" = "vuduo4kse"; then
AC_DEFINE(BOXMODEL_VUDUO4KSE, 1, [vuduo4kse])
elif test "$BOXMODEL" = "vuultimo4k"; then
AC_DEFINE(BOXMODEL_VUULTIMO4K, 1, [vuultimo4k])
elif test "$BOXMODEL" = "vuuno4k"; then
AC_DEFINE(BOXMODEL_VUUNO4K, 1, [vuuno4k])
elif test "$BOXMODEL" = "vuuno4kse"; then
AC_DEFINE(BOXMODEL_VUUNO4KSE, 1, [vuuno4kse])
elif test "$BOXMODEL" = "vuzero4k"; then
AC_DEFINE(BOXMODEL_VUZERO4K, 1, [vuzero4k])
elif test "$BOXMODEL" = "vuduo"; then
AC_DEFINE(BOXMODEL_VUDUO, 1, [vuduo])
AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi])
fi
# all vuplus BOXMODELs
case "$BOXMODEL" in
vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k|vuduo)
AC_DEFINE(BOXMODEL_VUPLUS_ALL, 1, [vuplus_all])
vuplus_all=true
;;
*)
vuplus_all=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_ALL, test "$vuplus_all" = "true")
# all vuplus arm BOXMODELs
case "$BOXMODEL" in
vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k)
AC_DEFINE(BOXMODEL_VUPLUS_ARM, 1, [vuplus_arm])
vuplus_arm=true
;;
*)
vuplus_arm=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_ARM, test "$vuplus_arm" = "true")
# all vuplus mips BOXMODELs
case "$BOXMODEL" in
vuduo)
AC_DEFINE(BOXMODEL_VUPLUS_MIPS, 1, [vuplus_mips])
vuplus_mips=true
;;
*)
vuplus_mips=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_MIPS, test "$vuplus_mips" = "true")
# all hisilicon BOXMODELs
case "$BOXMODEL" in
hd60|hd61)
AC_DEFINE(BOXMODEL_HISILICON, 1, [hisilicon])
hisilicon=true
;;
*)
hisilicon=false
;;
esac
AM_CONDITIONAL(BOXMODEL_HISILICON, test "$hisilicon" = "true")
])
dnl backward compatiblity
AC_DEFUN([AC_GNU_SOURCE], [
AH_VERBATIM([_GNU_SOURCE], [
/* Enable GNU extensions on systems that have them. */
AC_DEFUN([AC_GNU_SOURCE],
[AH_VERBATIM([_GNU_SOURCE],
[/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
])dnl
#endif])dnl
AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl
AC_BEFORE([$0], [AC_RUN_IFELSE])dnl
AC_DEFINE([_GNU_SOURCE])
])
AC_DEFUN([AC_PROG_EGREP], [
AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], [
if echo a | (grep -E '(a|b)') >/dev/null 2>&1; then
ac_cv_prog_egrep='grep -E'
else
ac_cv_prog_egrep='egrep'
fi
])
EGREP=$ac_cv_prog_egrep
AC_SUBST([EGREP])
AC_DEFUN([AC_PROG_EGREP],
[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
[if echo a | (grep -E '(a|b)') >/dev/null 2>&1
then ac_cv_prog_egrep='grep -E'
else ac_cv_prog_egrep='egrep'
fi])
EGREP=$ac_cv_prog_egrep
AC_SUBST([EGREP])
])

View File

@@ -1,15 +1,8 @@
#!/bin/sh
package="libstb-hal"
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
cd "$srcdir"
echo "Generating configuration files for $package, please wait ..."
#!/bin/bash
cd $(dirname $0)
aclocal --force
libtoolize --force
autoconf --force
autoheader --force
automake --add-missing --force-missing
automake --add-missing --force-missing --foreign

18
azbox/Makefile.am Normal file
View File

@@ -0,0 +1,18 @@
noinst_LTLIBRARIES = libazbox.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = -lpthread
libazbox_la_SOURCES = \
hardware_caps.c \
dmx.cpp \
video.cpp \
audio.cpp \
init.cpp \
playback.cpp \
record.cpp

403
azbox/audio.cpp Normal file
View File

@@ -0,0 +1,403 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/dvb/audio.h>
#include <proc_tools.h>
#include "audio_hal.h"
#include "lt_debug.h"
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_AUDIO, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_AUDIO, this, args)
#include <linux/soundcard.h>
cAudio * audioDecoder = NULL;
typedef struct audio_pdata
{
int fd;
int clipfd;
int mixer_fd;
int mixer_num;
} audio_pdata;
#define P ((audio_pdata *)pdata)
cAudio::cAudio(void *, void *, void *)
{
pdata = calloc(1, sizeof(audio_pdata));
P->clipfd = -1;
P->mixer_fd = -1;
P->fd = open(AUDIO_DEVICE, O_RDONLY|O_CLOEXEC);
if (P->fd < 0)
lt_info("%s: open failed (%m)\n", __func__);
muted = false;
}
cAudio::~cAudio(void)
{
if (P->fd >= 0) {
ioctl(P->fd, AUDIO_CONTINUE); /* enigma2 also does CONTINUE before close... */
close(P->fd);
P->fd = -1;
}
if (P->clipfd >= 0)
close(P->clipfd);
if (P->mixer_fd >= 0)
close(P->mixer_fd);
free(pdata);
}
int cAudio::mute(void)
{
return SetMute(true);
}
int cAudio::unmute(void)
{
return SetMute(false);
}
int cAudio::SetMute(bool enable)
{
lt_debug("%s(%d)\n", __func__, enable);
muted = enable;
#if 0
/* does not work? */
if (ioctl(fd, AUDIO_SET_MUTE, enable) < 0 )
lt_info("%s: AUDIO_SET_MUTE failed (%m)\n", __func__);
#else
char s[2] = { 0, 0 };
s[0] = '0' + (int)enable;
proc_put("/proc/stb/audio/j1_mute", s, 2);
#endif
return 0;
}
int map_volume(const int volume)
{
unsigned char vol = volume;
if (vol > 100)
vol = 100;
vol = 63 - vol * 63 / 100;
return vol;
}
int cAudio::setVolume(unsigned int left, unsigned int right)
{
lt_debug("%s(%d, %d)\n", __func__, left, right);
volume = (left + right) / 2;
if (P->clipfd != -1 && P->mixer_fd != -1) {
int tmp = 0;
/* not sure if left / right is correct here, but it is always the same anyways ;-) */
if (! muted)
tmp = left << 8 | right;
int ret = ioctl(P->mixer_fd, MIXER_WRITE(P->mixer_num), &tmp);
if (ret == -1)
lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, P->mixer_num, tmp);
return ret;
}
audio_mixer_t mixer;
mixer.volume_left = map_volume(left);
mixer.volume_right = map_volume(right);
if (ioctl(P->fd, AUDIO_SET_MIXER, &mixer) < 0)
lt_info("%s: AUDIO_SET_MIXER failed (%m)\n", __func__);
return 0;
}
int cAudio::Start(void)
{
lt_debug("%s\n", __func__);
int ret;
ioctl(P->fd, AUDIO_CONTINUE);
ret = ioctl(P->fd, AUDIO_PLAY);
return ret;
}
int cAudio::Stop(void)
{
lt_debug("%s\n", __func__);
ioctl(P->fd, AUDIO_STOP);
ioctl(P->fd, AUDIO_CONTINUE); /* no idea why we have to stop and then continue => enigma2 does it, too */
return 0;
}
bool cAudio::Pause(bool /*Pcm*/)
{
return true;
};
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
{
lt_debug("%s %d\n", __func__, Mode);
ioctl(P->fd, AUDIO_SET_AV_SYNC, Mode);
};
//AUDIO_ENCODING_AC3
#define AUDIO_STREAMTYPE_AC3 0
//AUDIO_ENCODING_MPEG2
#define AUDIO_STREAMTYPE_MPEG 1
//AUDIO_ENCODING_DTS
#define AUDIO_STREAMTYPE_DTS 2
#define AUDIO_ENCODING_LPCM 2
#define AUDIO_ENCODING_LPCMA 11
void cAudio::SetStreamType(AUDIO_FORMAT type)
{
int bypass = AUDIO_STREAMTYPE_MPEG;
lt_debug("%s %d\n", __func__, type);
switch (type)
{
case AUDIO_FMT_DOLBY_DIGITAL:
bypass = AUDIO_STREAMTYPE_AC3;
break;
case AUDIO_FMT_DTS:
bypass = AUDIO_STREAMTYPE_DTS;
break;
case AUDIO_FMT_MPEG:
default:
break;
}
// Normaly the encoding should be set using AUDIO_SET_ENCODING
// But as we implemented the behavior to bypass (cause of e2) this is correct here
if (ioctl(P->fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
};
int cAudio::setChannel(int channel)
{
return 0;
};
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
{
int fmt;
unsigned int devmask, stereo, usable;
const char *dsp_dev = getenv("DSP_DEVICE");
const char *mix_dev = getenv("MIX_DEVICE");
lt_debug("%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian);
if (P->clipfd >= 0) {
lt_info("%s: clipfd already opened (%d)\n", __func__, P->clipfd);
return -1;
}
P->mixer_num = -1;
P->mixer_fd = -1;
/* a different DSP device can be given with DSP_DEVICE and MIX_DEVICE
* if this device cannot be opened, we fall back to the internal OSS device
* Example:
* modprobe snd-usb-audio
* export DSP_DEVICE=/dev/sound/dsp2
* export MIX_DEVICE=/dev/sound/mixer2
* neutrino
*/
if ((!dsp_dev) || (access(dsp_dev, W_OK))) {
if (dsp_dev)
lt_info("%s: DSP_DEVICE is set (%s) but cannot be opened,"
" fall back to /dev/dsp1\n", __func__, dsp_dev);
dsp_dev = "/dev/dsp1";
}
lt_info("%s: dsp_dev %s mix_dev %s\n", __func__, dsp_dev, mix_dev); /* NULL mix_dev is ok */
/* the tdoss dsp driver seems to work only on the second open(). really. */
P->clipfd = open(dsp_dev, O_WRONLY|O_CLOEXEC);
if (P->clipfd < 0) {
lt_info("%s open %s: %m\n", dsp_dev, __FUNCTION__);
return -1;
}
/* no idea if we ever get little_endian == 0 */
if (little_endian)
fmt = AFMT_S16_BE;
else
fmt = AFMT_S16_LE;
if (ioctl(P->clipfd, SNDCTL_DSP_SETFMT, &fmt))
perror("SNDCTL_DSP_SETFMT");
if (ioctl(P->clipfd, SNDCTL_DSP_CHANNELS, &ch))
perror("SNDCTL_DSP_CHANNELS");
if (ioctl(P->clipfd, SNDCTL_DSP_SPEED, &srate))
perror("SNDCTL_DSP_SPEED");
if (ioctl(P->clipfd, SNDCTL_DSP_RESET))
perror("SNDCTL_DSP_RESET");
if (!mix_dev)
return 0;
P->mixer_fd = open(mix_dev, O_RDWR|O_CLOEXEC);
if (P->mixer_fd < 0) {
lt_info("%s: open mixer %s failed (%m)\n", __func__, mix_dev);
/* not a real error */
return 0;
}
if (ioctl(P->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
lt_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__);
devmask = 0;
}
if (ioctl(P->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
lt_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
stereo = 0;
}
usable = devmask & stereo;
if (usable == 0) {
lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n",
__func__, devmask, stereo);
close(P->mixer_fd);
P->mixer_fd = -1;
return 0; /* TODO: should we treat this as error? */
}
/* __builtin_popcount needs GCC, it counts the set bits... */
if (__builtin_popcount (usable) != 1) {
/* TODO: this code is not yet tested as I have only single-mixer devices... */
lt_info("%s: more than one mixer control: devmask %08x stereo %08x\n"
"%s: querying MIX_NUMBER environment variable...\n",
__func__, devmask, stereo, __func__);
const char *tmp = getenv("MIX_NUMBER");
if (tmp)
P->mixer_num = atoi(tmp);
lt_info("%s: mixer_num is %d -> device %08x\n",
__func__, P->mixer_num, (P->mixer_num >= 0) ? (1 << P->mixer_num) : 0);
/* no error checking, you'd better know what you are doing... */
} else {
P->mixer_num = 0;
while (!(usable & 0x01)) {
P->mixer_num++;
usable >>= 1;
}
}
setVolume(volume, volume);
return 0;
};
int cAudio::WriteClip(unsigned char *buffer, int size)
{
int ret;
// lt_debug("cAudio::%s\n", __FUNCTION__);
if (P->clipfd <= 0) {
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
ret = write(P->clipfd, buffer, size);
if (ret < 0)
lt_info("%s: write error (%m)\n", __FUNCTION__);
return ret;
};
int cAudio::StopClip()
{
lt_debug("%s\n", __FUNCTION__);
if (P->clipfd <= 0) {
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
close(P->clipfd);
P->clipfd = -1;
if (P->mixer_fd >= 0)
close(P->mixer_fd);
P->mixer_fd = -1;
setVolume(volume, volume);
return 0;
};
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
{
lt_debug("%s\n", __FUNCTION__);
type = 0;
layer = 0;
freq = 0;
bitrate = 0;
mode = 0;
#if 0
unsigned int atype;
static const int freq_mpg[] = {44100, 48000, 32000, 0};
static const int freq_ac3[] = {48000, 44100, 32000, 0};
scratchl2 i;
if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0)
perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP");
if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0)
perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS");
type = atype;
#if 0
/* this does not work, some of the values are negative?? */
AMPEGStatus A;
memcpy(&A, &i.word00, sizeof(i.word00));
layer = A.audio_mpeg_layer;
mode = A.audio_mpeg_mode;
bitrate = A.audio_mpeg_bitrate;
switch(A.audio_mpeg_frequency)
#endif
/* layer and bitrate are not used anyway... */
layer = 0; //(i.word00 >> 17) & 3;
bitrate = 0; //(i.word00 >> 12) & 3;
switch (type)
{
case 0: /* MPEG */
mode = (i.word00 >> 6) & 3;
freq = freq_mpg[(i.word00 >> 10) & 3];
break;
case 1: /* AC3 */
mode = (i.word00 >> 28) & 7;
freq = freq_ac3[(i.word00 >> 16) & 3];
break;
default:
mode = 0;
freq = 0;
}
//fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode);
#endif
};
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
{
lt_debug("%s\n", __FUNCTION__);
};
void cAudio::SetHdmiDD(bool enable)
{
lt_debug("%s %d\n", __func__, enable);
};
#define AUDIO_BYPASS_ON 0
#define AUDIO_BYPASS_OFF 1
void cAudio::SetSpdifDD(bool enable)
{
lt_debug("%s %d\n", __func__, enable);
//setBypassMode(!enable);
int mode = enable ? AUDIO_BYPASS_ON : AUDIO_BYPASS_OFF;
if (ioctl(P->fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
};
void cAudio::ScheduleMute(bool On)
{
lt_debug("%s %d\n", __FUNCTION__, On);
};
void cAudio::EnableAnalogOut(bool enable)
{
lt_debug("%s %d\n", __FUNCTION__, enable);
};
#if 0
void cAudio::setBypassMode(bool disable)
{
lt_debug("%s %d\n", __func__, disable);
int mode = disable ? AUDIO_BYPASS_OFF : AUDIO_BYPASS_ON;
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
return;
}
#endif

520
azbox/dmx.cpp Normal file
View File

@@ -0,0 +1,520 @@
/*
* cDemux implementation for azbox receivers (tested on azbox me and minime)
*
* derived from libtriple/dmx_td.cpp
*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <inttypes.h>
#include <cstring>
#include <cstdio>
#include <string>
#include <sys/ioctl.h>
#include "dmx_hal.h"
#include "lt_debug.h"
/* Ugh... see comment in destructor for details... */
#include "video_hal.h"
#include "video_priv.h"
extern cVideo *videoDecoder;
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
#define dmx_err(_errfmt, _errstr, _revents) do { \
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
} while(0);
cDemux *videoDemux = NULL;
cDemux *audioDemux = NULL;
//cDemux *pcrDemux = NULL;
static const char *DMX_T[] = {
"DMX_INVALID",
"DMX_VIDEO",
"DMX_AUDIO",
"DMX_PES",
"DMX_PSI",
"DMX_PIP",
"DMX_TP",
"DMX_PCR"
};
/* map the device numbers. for now only demux0 is used */
static const char *devname[] = {
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux0"
};
/* uuuugly */
static int dmx_tp_count = 0;
#define MAX_TS_COUNT 8
cDemux::cDemux(int n)
{
if (n < 0 || n > 2)
{
lt_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
num = 0;
}
else
num = n;
fd = -1;
}
cDemux::~cDemux()
{
lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
Close();
/* in zapit.cpp, videoDemux is deleted after videoDecoder
* in the video watchdog, we access videoDecoder
* the thread still runs after videoDecoder has been deleted
* => set videoDecoder to NULL here to make the check in the
* watchdog thread pick this up.
* This is ugly, but it saves me from changing neutrino
*
* if the delete order in neutrino will ever be changed, this
* will blow up badly :-(
*/
if (dmx_type == DMX_VIDEO_CHANNEL)
videoDecoder = NULL;
}
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
{
int devnum = num;
int flags = O_RDWR|O_CLOEXEC;
if (fd > -1)
lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
if (pes_type != DMX_PSI_CHANNEL)
flags |= O_NONBLOCK;
fd = open(devname[devnum], flags);
if (fd < 0)
{
lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
return false;
}
lt_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
num, DMX_T[pes_type], pes_type, uBufferSize, fd);
dmx_type = pes_type;
#if 0
if (!pesfds.empty())
{
lt_info("%s ERROR! pesfds not empty!\n", __FUNCTION__); /* TODO: error handling */
return false;
}
int n = DMX_SOURCE_FRONT0;
if (ioctl(fd, DMX_SET_SOURCE, &n) < 0)
lt_info("%s DMX_SET_SOURCE failed!\n", __func__);
#endif
if (uBufferSize > 0)
{
/* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */
if (ioctl(fd, DMX_SET_BUFFER_SIZE, uBufferSize) < 0)
lt_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
}
buffersize = uBufferSize;
return true;
}
void cDemux::Close(void)
{
lt_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
if (fd < 0)
{
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return;
}
pesfds.clear();
ioctl(fd, DMX_STOP);
close(fd);
fd = -1;
if (dmx_type == DMX_TP_CHANNEL)
{
dmx_tp_count--;
if (dmx_tp_count < 0)
{
lt_info("%s dmx_tp_count < 0!!\n", __func__);
dmx_tp_count = 0;
}
}
}
bool cDemux::Start(bool)
{
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_START);
return true;
}
bool cDemux::Stop(void)
{
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_STOP);
return true;
}
int cDemux::Read(unsigned char *buff, int len, int timeout)
{
#if 0
if (len != 4095 && timeout != 100)
fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n",
__FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout);
#endif
int rc;
int to = timeout;
/* using a one-dimensional array seems to avoid strange segfaults / memory corruption?? */
struct pollfd ufds[1];
ufds[0].fd = fd;
ufds[0].events = POLLIN|POLLPRI|POLLERR;
ufds[0].revents = 0;
/* hack: if the frontend loses and regains lock, the demuxer often will not
* return from read(), so as a "emergency exit" for e.g. NIT scan, set a (long)
* timeout here */
if (dmx_type == DMX_PSI_CHANNEL && timeout <= 0)
to = 60 * 1000;
if (to > 0)
{
retry:
rc = ::poll(ufds, 1, to);
if (!rc)
{
if (timeout == 0) /* we took the emergency exit */
{
dmx_err("timed out for timeout=0!, %s", "", 0);
return -1; /* this timeout is an error */
}
return 0; // timeout
}
else if (rc < 0)
{
dmx_err("poll: %s,", strerror(errno), 0)
//lt_info("%s poll: %m\n", __FUNCTION__);
/* happens, when running under gdb... */
if (errno == EINTR)
goto retry;
return -1;
}
#if 0
if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */
{
dmx_err("received %s,", "POLLERR", ufds.revents);
/* this seems to happen sometimes at recording start, without bad effects */
return 0;
}
#endif
if (ufds[0].revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */
{
dmx_err("received %s,", "POLLHUP", ufds[0].revents);
return -1;
}
if (!(ufds[0].revents & POLLIN)) /* we requested POLLIN but did not get it? */
{
dmx_err("received %s, please report!", "POLLIN", ufds[0].revents);
return 0;
}
}
rc = ::read(fd, buff, len);
//fprintf(stderr, "fd %d ret: %d\n", fd, rc);
if (rc < 0)
dmx_err("read: %s", strerror(errno), 0);
return rc;
}
bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filter,
const unsigned char * const mask, int len, int timeout,
const unsigned char * const negmask)
{
struct dmx_sct_filter_params s_flt;
memset(&s_flt, 0, sizeof(s_flt));
pid = _pid;
if (len > DMX_FILTER_SIZE)
{
lt_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
len = DMX_FILTER_SIZE;
}
s_flt.pid = pid;
s_flt.timeout = timeout;
flt = filter[0];
memcpy(s_flt.filter.filter, filter, len);
memcpy(s_flt.filter.mask, mask, len);
if (negmask != NULL)
memcpy(s_flt.filter.mode, negmask, len);
s_flt.flags = DMX_IMMEDIATE_START|DMX_CHECK_CRC;
int to = 0;
switch (filter[0]) {
case 0x00: /* program_association_section */
to = 2000;
break;
case 0x01: /* conditional_access_section */
to = 6000;
break;
case 0x02: /* program_map_section */
to = 1500;
break;
case 0x03: /* transport_stream_description_section */
to = 10000;
break;
/* 0x04 - 0x3F: reserved */
case 0x40: /* network_information_section - actual_network */
to = 10000;
break;
case 0x41: /* network_information_section - other_network */
to = 15000;
break;
case 0x42: /* service_description_section - actual_transport_stream */
to = 10000;
break;
/* 0x43 - 0x45: reserved for future use */
case 0x46: /* service_description_section - other_transport_stream */
to = 10000;
break;
/* 0x47 - 0x49: reserved for future use */
case 0x4A: /* bouquet_association_section */
to = 11000;
break;
/* 0x4B - 0x4D: reserved for future use */
case 0x4E: /* event_information_section - actual_transport_stream, present/following */
to = 2000;
break;
case 0x4F: /* event_information_section - other_transport_stream, present/following */
to = 10000;
break;
/* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */
/* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */
case 0x70: /* time_date_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
s_flt.flags |= DMX_ONESHOT;
//s_flt.pid = 0x0014;
to = 30000;
break;
case 0x71: /* running_status_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x72: /* stuffing_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x73: /* time_offset_section */
s_flt.flags |= DMX_ONESHOT;
//s_flt.pid = 0x0014;
to = 30000;
break;
/* 0x74 - 0x7D: reserved for future use */
case 0x7E: /* discontinuity_information_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x7F: /* selection_information_section */
to = 0;
break;
/* 0x80 - 0x8F: ca_message_section */
/* 0x90 - 0xFE: user defined */
/* 0xFF: reserved */
default:
break;
// return -1;
}
/* the negmask == NULL is a hack: the users of negmask are PMT-update
* and sectionsd EIT-Version change. And they really want no timeout
* if timeout == 0 instead of "default timeout" */
if (timeout == 0 && negmask == NULL)
s_flt.timeout = to;
lt_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
pid, fd, DMX_T[dmx_type], len, s_flt.timeout,s_flt.flags, s_flt.filter.filter[0]);
#if 0
fprintf(stderr,"filt: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.filter[i]);fprintf(stderr,"\n");
fprintf(stderr,"mask: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.mask [i]);fprintf(stderr,"\n");
fprintf(stderr,"mode: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.mode [i]);fprintf(stderr,"\n");
#endif
ioctl (fd, DMX_STOP);
if (ioctl(fd, DMX_SET_FILTER, &s_flt) < 0)
return false;
ioctl(fd, DMX_START);
return true;
}
bool cDemux::pesFilter(const unsigned short _pid)
{
struct dmx_pes_filter_params p_flt;
pid = _pid;
flt = 0;
/* allow PID 0 for web streaming e.g.
* this check originally is from tuxbox cvs but I'm not sure
* what it is good for...
if (pid <= 0x0001 && dmx_type != DMX_PCR_ONLY_CHANNEL)
return false;
*/
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
return false;
lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
memset(&p_flt, 0, sizeof(p_flt));
p_flt.pid = pid;
p_flt.output = DMX_OUT_DECODER;
p_flt.input = DMX_IN_FRONTEND;
switch (dmx_type) {
case DMX_PCR_ONLY_CHANNEL:
p_flt.pes_type = DMX_PES_PCR;
break;
case DMX_AUDIO_CHANNEL:
p_flt.pes_type = DMX_PES_AUDIO;
break;
case DMX_VIDEO_CHANNEL:
p_flt.pes_type = DMX_PES_VIDEO;
break;
case DMX_PES_CHANNEL:
p_flt.pes_type = DMX_PES_OTHER;
p_flt.output = DMX_OUT_TAP;
break;
case DMX_TP_CHANNEL:
p_flt.pes_type = DMX_PES_OTHER;
p_flt.output = DMX_OUT_TSDEMUX_TAP;
break;
default:
lt_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
return false;
}
return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0);
}
void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/)
{
lt_debug("%s #%d\n", __FUNCTION__, num);
}
void *cDemux::getBuffer()
{
lt_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
void *cDemux::getChannel()
{
lt_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
bool cDemux::addPid(unsigned short Pid)
{
lt_debug("%s: pid 0x%04hx\n", __func__, Pid);
pes_pids pfd;
int ret;
if (dmx_type != DMX_TP_CHANNEL)
{
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return false;
}
if (fd == -1)
lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
pfd.fd = fd; /* dummy */
pfd.pid = Pid;
pesfds.push_back(pfd);
ret = (ioctl(fd, DMX_ADD_PID, &Pid));
if (ret < 0)
lt_info("%s: DMX_ADD_PID (%m)\n", __func__);
return (ret != -1);
}
void cDemux::removePid(unsigned short Pid)
{
if (dmx_type != DMX_TP_CHANNEL)
{
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return;
}
for (std::vector<pes_pids>::iterator i = pesfds.begin(); i != pesfds.end(); ++i)
{
if ((*i).pid == Pid) {
lt_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
lt_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
pesfds.erase(i);
return; /* TODO: what if the same PID is there multiple times */
}
}
lt_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
}
void cDemux::getSTC(int64_t * STC)
{
/* apparently I can only get the PTS of the video decoder,
* but that's good enough for dvbsub */
lt_debug("%s #%d\n", __func__, num);
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->vdec->GetPTS();
*STC = pts;
}
int cDemux::getUnit(void)
{
lt_debug("%s #%d\n", __FUNCTION__, num);
/* just guessed that this is the right thing to do.
right now this is only used by the CA code which is stubbed out
anyway */
return num;
}
bool cDemux::SetSource(int unit, int source)
{
lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
return true;
}
int cDemux::GetSource(int unit)
{
lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
return 0;
}

83
azbox/e2mruainclude.h Normal file
View File

@@ -0,0 +1,83 @@
//Additional Azbox
enum key_command {
KEY_COMMAND_QUIT_ALL = 100,
KEY_COMMAND_QUIT,
KEY_COMMAND_PLAY,
KEY_COMMAND_PAUSE,
KEY_COMMAND_RESUME,
KEY_COMMAND_STOP,
KEY_COMMAND_SEEK_TO_TIME,
KEY_COMMAND_SEEK_TO_PERCENT,
KEY_COMMAND_NEXT_PICT,
KEY_COMMAND_FAST_FWD_ALL_FRAMES,
KEY_COMMAND_SLOW_FWD_ALL_FRAMES,
KEY_COMMAND_IFRAMES_FWD,
KEY_COMMAND_IFRAMES_BWD,
KEY_COMMAND_SILENT_FWD,
KEY_COMMAND_SILENT_BWD,
KEY_COMMAND_SWITCH_VIDEO,
KEY_COMMAND_SWITCH_AUDIO,
KEY_COMMAND_SWITCH_PROGRAM,
KEY_COMMAND_SWITCH_SUBS,
KEY_COMMAND_SWITCH_MULTICAST,
KEY_COMMAND_APPLY_AV_DELAY,
KEY_COMMAND_SUBS_CHANGE_DELAY,
KEY_COMMAND_SUBS_INCREASE_FONT_SIZE,
KEY_COMMAND_SUBS_DECREASE_FONT_SIZE,
KEY_COMMAND_SUBS_INCREASE_POS_Y,
KEY_COMMAND_SUBS_DECREASE_POS_Y,
KEY_COMMAND_SUBS_SWITCH_ENCODING,
KEY_COMMAND_SUBS_RESET_ALL,
KEY_COMMAND_SUBS_CHANGE_COLOR,
KEY_COMMAND_DEBUG,
KEY_COMMAND_PRINT_INFO,
KEY_COMMAND_FULL_SCREEN,
KEY_COMMAND_HALF_SCREEN,
KEY_COMMAND_INCREASE_SIZE,
KEY_COMMAND_DECREASE_SIZE,
KEY_COMMAND_MOVE_LEFT,
KEY_COMMAND_MOVE_RIGHT,
KEY_COMMAND_MOVE_TOP,
KEY_COMMAND_MOVE_BOTTOM,
KEY_COMMAND_NONLINEAR_WIDTH,
KEY_COMMAND_NONLINEAR_LEVEL,
KEY_COMMAND_SWITCH_SCALER,
KEY_COMMAND_HELP,
KEY_COMMAND_FAST_FWD_WITH_AUDIO,
KEY_COMMAND_SLOW_FWD_WITH_AUDIO,
KEY_COMMAND_PRINT_TXT,
SPECIAL_KEY_COMMAND_IFRAMES_FWD,
SPECIAL_KEY_COMMAND_IFRAMES_BWD,
SPECIAL_KEY_COMMAND_NEXT_AUDIO,
SPECIAL_KEY_COMMAND_NEXT_SUBS,
};
enum custom_command {
CUSTOM_COMMAND_GETLENGTH = 200,
CUSTOM_COMMAND_GETPOSITION,
CUSTOM_COMMAND_AUDIOGETPOSITION,
CUSTOM_COMMAND_SEEK_RELATIVE_FWD,
CUSTOM_COMMAND_SEEK_RELATIVE_BWD,
CUSTOM_COMMAND_SUBS_COUNT,
CUSTOM_COMMAND_GET_SUB_BY_ID,
CUSTOM_COMMAND_AUDIO_COUNT,
CUSTOM_COMMAND_GET_AUDIO_BY_ID,
CUSTOM_COMMAND_AUDIO_CUR_STREAM,
CUSTOM_COMMAND_SUBS_CUR_STREAM,
CUSTOM_COMMAND_TRICK_SEEK,
CUSTOM_COMMAND_SET_SUB_SIZE,
CUSTOM_COMMAND_SET_SUB_ENCODING,
CUSTOM_COMMAND_SET_SUB_POS,
};
enum event_msg {
EVENT_MSG_FDOPEN = 300,
EVENT_MSG_PLAYBACK_STARTED,
EVENT_MSG_STOPPED,
EVENT_MSG_PAUSED,
EVENT_MSG_BUFFERING,
EVENT_MSG_EOS,
EVENT_MSG_SUB_CHANGED,
};
//int fd_cmd, fd_in, fd_out, fd_event, msg;

View File

@@ -2,23 +2,19 @@
* determine the capabilities of the hardware.
* part of libstb-hal
*
* (C) 2010-2012 Stefan Seyfried
* (C) 2010-2012,2016 Stefan Seyfried
*
* License: GPL v2 or later
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <hardware_caps.h>
#define FP_DEV "/dev/dbox/oled0"
static int initialized = 0;
static hw_caps_t caps;
@@ -29,24 +25,30 @@ hw_caps_t *get_hwcaps(void)
memset(&caps, 0, sizeof(hw_caps_t));
#if BOXMODEL_VUDUO
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 16;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_can_deepstandby = 1;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "DUO");
strcpy(caps.boxarch, "BCM7335");
#endif
caps.display_xres = 8;
caps.display_has_statusline = 0;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 0;
strcpy(caps.boxvendor, "AZBox");
const char *tmp;
char buf[64];
int len = -1;
int fd = open("/proc/stb/info/model", O_RDONLY);
if (fd != -1) {
len = read(fd, buf, sizeof(buf) - 1);
close(fd);
}
if (len > 0) {
buf[len] = 0;
strcpy(caps.boxname, buf);
}
else
strcpy(caps.boxname, "(unknown model)");
strcpy(caps.boxarch, "mipsel");
return &caps;
}

21
azbox/init.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include <unistd.h>
#include "init_td.h"
#include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
static bool initialized = false;
void init_td_api()
{
if (!initialized)
lt_debug_init();
lt_info("%s begin, initialized=%d, debug=0x%02x\n", __func__, (int)initialized, debuglevel);
initialized = true;
}
void shutdown_td_api()
{
lt_info("%s, initialized = %d\n", __func__, (int)initialized);
initialized = false;
}

574
azbox/playback.cpp Normal file
View File

@@ -0,0 +1,574 @@
/*
* cPlayback implementation for azbox
* this is actually just a wrapper around rmfp_player which does
* all the heavy listing
*
* based on the original aztrino implementation, but almost
* completely rewritten since then
*
* some of the methods and constants were found by stracing the
* AZPlay enigma2 plugin...
*
* (C) 2012 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sstream>
#include <pty.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PLAYBACK, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_PLAYBACK, this, args)
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_PLAYBACK, NULL, args)
#include <proc_tools.h>
/* the file-based commands work better than the FIFOs... */
#define CMD_FILE "/tmp/rmfp.cmd2"
#define IN_FILE "/tmp/rmfp.in2"
#define OUT_FILE "/tmp/rmfp.out2"
#include "playback_hal.h"
extern "C"{
#include "e2mruainclude.h"
}
#if 0
/* useful for debugging */
static time_t monotonic_ms(void)
{
struct timespec t;
time_t ret;
if (clock_gettime(CLOCK_MONOTONIC, &t))
{
perror("monotonic_ms clock_gettime");
return -1;
}
ret = ((t.tv_sec + 604800)& 0x01FFFFF) * 1000; /* avoid overflow */
ret += t.tv_nsec / 1000000;
return ret;
}
#endif
class PBPrivate
{
public:
bool rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen);
void run_rmfp(void);
PBPrivate(void) {
playing = 0;
thread_started = false;
eof = false;
open_success = false;
pthread_mutex_init(&rmfp_cmd_mutex, NULL);
};
~PBPrivate(void) {
pthread_mutex_destroy(&rmfp_cmd_mutex);
};
int duration;
int playing;
int speed;
playmode_t pmode;
uint16_t apid;
uint16_t subpid;
bool eof;
bool open_success;
bool thread_started;
pthread_t thread;
pthread_mutex_t rmfp_cmd_mutex;
char *fname;
};
/* the mutex makes sure that commands are not interspersed */
bool PBPrivate::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen)
{
lt_info("%s: %d %d %d %d\n", __func__, cmd, param, has_param, buflen);
bool ret = true;
int fd;
if (cmd == 222)
{
if (pthread_mutex_trylock(&rmfp_cmd_mutex))
return false;
}
else
pthread_mutex_lock(&rmfp_cmd_mutex);
unlink(OUT_FILE);
if (has_param)
{
fd = open(IN_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
dprintf(fd, "%i", param);
close(fd);
}
fd = open(CMD_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
dprintf(fd, "%i", cmd);
close(fd);
int n = 0, m = 0;
if (buflen > 0)
{
while ((fd = open(OUT_FILE, O_RDONLY)) == -1) {
if (++m > 500) { /* don't wait more than 5 seconds */
lt_info("%s: timed out waiting for %s (cmd %d par %d buflen %d\n",
__func__, OUT_FILE, cmd, param, buflen);
ret = false;
goto out;
}
usleep(10000);
}
unlink(OUT_FILE);
n = read(fd, buf, buflen);
close(fd);
/* some commands (CUSTOM_COMMAND_GET_AUDIO_BY_ID for example) actually
* return the answer in two successive writes, as we are not using the
* FIFO, we need to make sure that the file is deleted immediately, because
* rmfp_player will not overwrite it if it exists */
while ((fd = open(OUT_FILE, O_RDONLY)) == -1) {
if (++m > 10)
break;
usleep(1000);
}
if (fd > -1)
{
read(fd, buf + n, buflen - n);
unlink(OUT_FILE);
close(fd);
}
buf[buflen - 1] = '0';
}
out:
pthread_mutex_unlock(&rmfp_cmd_mutex);
if (cmd != 222) /* called tooo often :-) */
lt_info("%s: reply: '%s' ret: %d m:%d\n", __func__, buf?buf:"(none)", ret, m);
return ret;
}
/*
* runs the rmfp_player in a terminal
* just doing popen() or similar does not work because then
* the output will be buffered after starting up and we will only
* see "Playback has started..." after the player exits
*/
void PBPrivate::run_rmfp()
{
lt_debug("%s: starting\n", __func__);
thread_started = true;
//Watch for the space at the end
std::string base = "rmfp_player -dram 1 -ve 1 -waitexit ";
std::string filename(fname);
std::string file = '"' + filename + '"';
std::string final = base + file;
if (pmode == PLAYMODE_TS && duration != 0)
{
std::stringstream du;
du << (duration /** 60000LL*/);
final = base + "-duration " + du.str() + " " + file;
}
pid_t pid = 0;
int master;
pid = forkpty(&master, NULL, NULL, NULL);
if (! pid) {
execl("/bin/sh", "sh", "-c", final.c_str(), (char *)0);
lt_info("%s: execl returned: %m\n", __func__);
exit(0);
}
if (pid > 0) {
char *output=NULL;
size_t n = 0;
ssize_t len;
FILE *f = fdopen(master, "r");
while ((len = getline(&output, &n, f)) != -1)
{
while (len > 0)
{
len--;
if (!isspace(output[len]))
break;
output[len] = '\0';
}
lt_info("%s out: '%s'\n", __func__, output);
if (strstr(output, "Playback has started..."))
{
playing = 1;
lt_info("%s: ===================> playing = true\n", __func__);
}
else if (strstr(output, "End of file..."))
{
playing = 1; /* this can happen without "Playback has started..." */
eof = true;
lt_info("%s: ===================> eof_reached = true\n", __func__);
}
}
fclose(f);
int s;
while (waitpid(pid, &s, WNOHANG) > 0) {};
if (output)
free(output);
}
lt_info("%s: terminating\n", __func__);
if (playing == 0) /* playback did not start */
playing = 2;
else
playing = 0;
eof = true;
pthread_exit(NULL);
}
/* helper function to call the cpp thread loop */
void *execute_rua_thread(void *c)
{
PBPrivate *obj = (PBPrivate *)c;
lt_info_c("%s\n", __func__);
obj->run_rmfp();
/* free(obj); // this is most likely wrong */
return NULL;
}
//Used by Fileplay
bool cPlayback::Open(playmode_t PlayMode)
{
static const char *aPLAYMODE[] = {
"PLAYMODE_TS",
"PLAYMODE_FILE"
};
pd->pmode = PlayMode;
if (pd->pmode > 1)
{
lt_info("%s: PlayMode %d out of range!\n", __func__, PlayMode);
pd->pmode = PLAYMODE_FILE;
}
lt_info("%s: mode %d (%s)\n", __func__, PlayMode, aPLAYMODE[PlayMode]);
#if 0
while (access("/tmp/continue", R_OK))
sleep(1);
#endif
char c[2] = "0";
int i = 0;
for(;;)
{
proc_get("/proc/player", c, 2);
if (c[0] != '0')
break;
i++;
if (i > 10)
{
lt_info("%s: ERROR - player is not idle after 10 seconds!\n", __func__);
pd->open_success = false;
return false;
}
sleep(1);
}
proc_put("/proc/player", "2", 2);
lt_info("%s: /proc/player switched to '2'\n", __func__);
unlink(CMD_FILE);
unlink(IN_FILE);
unlink(OUT_FILE);
pd->open_success = true;
return 0;
}
bool cPlayback::Start(std::string /*filename*/, std::string /*headers*/)
{
return false;
}
//Used by Fileplay
bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned short _apid,
int ac3, unsigned int duration)
{
bool ret = true;
lt_info("%s: filename=%s\n", __func__, filename);
lt_info("%s: vpid=%u vtype=%d apid=%u ac3=%d duration=%i open_success=%d\n",
__func__, vpid, vtype, _apid, ac3, duration, pd->open_success);
if (!pd->open_success)
return false;
pd->eof = false;
//create playback path
pd->apid = 0;
pd->subpid = 0;
pd->fname = filename;
pd->duration = duration;
if (pthread_create(&pd->thread, 0, execute_rua_thread, pd) != 0)
{
lt_info("%s: error creating rmfp_player thread! (out of memory?)\n", __func__);
ret = false;
}
while (! pd->playing)
sleep(1);
if (pd->playing == 2)
pd->playing = 0;
return ret;
}
void cPlayback::Close(void)
{
lt_info("%s: playing %d thread_started %d\n", __func__, pd->playing, pd->thread_started);
if (pd->thread_started)
{
pd->rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
if (pthread_join(pd->thread, NULL))
lt_info("%s: error joining rmfp thread (%m)\n", __func__);
pd->playing = 0;
pd->thread_started = false;
}
else
lt_info("%s: Warning: thread_started == false!\n", __func__);
if (pd->open_success)
{
proc_put("/proc/player", "1", 2);
pd->open_success = false;
lt_info("%s: /proc/player switched to '1'\n", __func__);
usleep(1000000);
}
}
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
{
lt_info("%s: pid %i\n", __func__, pid);
if (pid != pd->apid) {
pd->rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0);
pd->apid = pid;
}
return true;
}
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
{
lt_info("%s: pid %i\n", __func__, pid);
if (pid != pd->subpid)
{
pd->rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0);
pd->subpid = pid;
}
return true;
}
bool cPlayback::SetSpeed(int speed)
{
lt_info("%s: playing %d speed %d\n", __func__, pd->playing, speed);
if (!pd->playing)
return false;
pd->speed = speed;
if (speed > 1 || speed < 0)
pd->rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
else if (speed == 0)
pd->rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
else
pd->rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
return true;
}
bool cPlayback::GetSpeed(int &/*speed*/) const
{
#if 0
lt_info("%s:\n", __func__);
speed = playback_speed;
#endif
return true;
}
// in milliseconds
bool cPlayback::GetPosition(int &position, int &duration)
{
lt_debug("%s: playing %d\n", __func__, pd->playing);
if (pd->eof)
{
position = pd->duration;
duration = pd->duration;
return true;
}
if (!pd->playing)
return false;
char buf[32];
/* custom command 222 returns "12345\n1234\n",
* first line is duration, second line is position */
if (! pd->rmfp_command(222, 0, false, buf, 32))
return false;
duration = atoi(buf);
char *p = strchr(buf, '\n');
if (!p)
return false;
position = atoi(++p);
/* some mpegs return length 0... which would lead to "eof" after 10 seconds */
if (duration == 0)
duration = position + 1000;
if (pd->pmode == PLAYMODE_TS)
{
if (position > pd->duration)
pd->duration = position + 1000;
duration = pd->duration;
return true;
}
return true;
}
bool cPlayback::SetPosition(int position, bool absolute)
{
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, pd->playing);
if (!pd->playing)
return false;
int seconds = position / 1000;;
if (absolute)
{
pd->rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0);
return true;
}
if (position > 0)
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0);
else if (position < 0)
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
return true;
}
void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language)
{
lt_info("%s\n", __func__);
char buf[32];
pd->rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
unsigned int audio_count = atoi(buf);
*numpida = audio_count;
if (audio_count > 0)
{
for (unsigned int aid = 0; aid < audio_count; aid++)
{
char streamidstring[11];
char audio_lang[21];
memset(buf, 0, sizeof(buf));
pd->rmfp_command(CUSTOM_COMMAND_GET_AUDIO_BY_ID, aid, true, buf, 32);
memcpy(streamidstring, buf, 10);
streamidstring[10] = '\0';
memcpy(audio_lang, buf + 10, 20);
audio_lang[20] = '\0';
apids[aid] = atoi(streamidstring);
ac3flags[aid] = 0;
language[aid] = audio_lang;
lt_info("%s: #%d apid:%d lang: %s\n", __func__, aid, apids[aid], audio_lang);
}
}
}
void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t *numpids, std::string *language)
{
lt_info("%s\n", __func__);
char buf[32];
pd->rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
unsigned int spu_count = atoi(buf);
*numpids = spu_count;
if (spu_count > 0)
{
for (unsigned int sid = 0; sid < spu_count; sid++)
{
char streamidstring[11];
char spu_lang[21];
memset(buf, 0, sizeof(buf));
pd->rmfp_command(CUSTOM_COMMAND_GET_SUB_BY_ID, sid, true, buf, 32);
memcpy(streamidstring, buf, 10);
streamidstring[10] = '\0';
memcpy(spu_lang, buf + 10, 20);
spu_lang[20] = '\0';
spids[sid] = atoi(streamidstring);
language[sid] = spu_lang;
supported[sid] = 1;
lt_info("%s: #%d apid:%d lang: %s\n", __func__, sid, spids[sid], spu_lang);
}
}
//Add streamid -1 to be able to disable subtitles
*numpids = spu_count + 1;
spids[spu_count] = -1;
language[spu_count] = "Disable";
}
/* DVD support is not yet ready... */
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
{
positions.clear();
titles.clear();
}
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current)
{
playlists.clear();
titles.clear();
current = 0;
}
void cPlayback::SetTitle(int /*title*/)
{
}
void cPlayback::RequestAbort(void)
{
}
uint64_t cPlayback::GetReadCount(void)
{
return 0;
}
cPlayback::cPlayback(int /*num*/)
{
lt_info("%s: constructor\n", __func__);
pd = new PBPrivate();
}
cPlayback::~cPlayback()
{
lt_info("%s\n", __func__);
delete pd;
pd = NULL;
}

675
azbox/video.cpp Normal file
View File

@@ -0,0 +1,675 @@
/*
* (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org>
* (C) 2010-2012 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <errno.h>
#include <ctype.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <linux/types.h>
#include <linux/dvb/video.h>
#include <proc_tools.h>
#include "video_hal.h"
#include "video_priv.h"
#define VIDEO_DEVICE "/dev/dvb/adapter0/video0"
#include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args)
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
#define fop(cmd, args...) ({ \
int _r; \
if (fd >= 0) { \
if ((_r = ::cmd(fd, args)) < 0) \
lt_info(#cmd"(fd, "#args")\n"); \
else \
lt_debug(#cmd"(fd, "#args")\n");\
} \
else { _r = fd; } \
_r; \
})
cVideo * videoDecoder = NULL;
int system_rev = 0;
static bool stillpicture = false;
static unsigned char *blank_data;
static ssize_t blank_size;
static pthread_mutex_t stillp_mutex = PTHREAD_MUTEX_INITIALIZER;
/* prototype */
static void show_iframe(int fd, unsigned char *iframe, size_t st_size);
#define VIDEO_STREAMTYPE_MPEG2 0
#define VIDEO_STREAMTYPE_MPEG4_H264 1
#define VIDEO_STREAMTYPE_VC1 3
#define VIDEO_STREAMTYPE_MPEG4_Part2 4
#define VIDEO_STREAMTYPE_VC1_SM 5
#define VIDEO_STREAMTYPE_MPEG1 6
cVideo::cVideo(int, void *, void *, unsigned int)
{
vdec = new VDec();
}
cVideo::~cVideo(void)
{
delete vdec;
vdec = NULL;
}
VDec::VDec(void)
{
lt_debug("%s\n", __FUNCTION__);
//croppingMode = VID_DISPMODE_NORM;
//outputformat = VID_OUTFMT_RGBC_SVIDEO;
video_standby = 0;
fd = -1;
const char *blankname = "/share/tuxbox/blank_576.mpg";
int blankfd;
struct stat st;
blank_data = NULL; /* initialize */
blank_size = 0;
blankfd = open(blankname, O_RDONLY|O_CLOEXEC);
if (blankfd < 0)
lt_info("%s cannot open %s: %m", __func__, blankname);
else
{
if (fstat(blankfd, &st) != -1 && st.st_size > 0)
{
blank_size = st.st_size;
blank_data = (unsigned char *)malloc(blank_size);
if (! blank_data)
lt_info("%s malloc failed (%m)\n", __func__);
else if (read(blankfd, blank_data, blank_size) != blank_size)
{
lt_info("%s short read (%m)\n", __func__);
free(blank_data); /* don't leak... */
blank_data = NULL;
}
}
close(blankfd);
}
openDevice();
Pig(-1, -1, -1, -1, 1, 1);
}
VDec::~VDec(void)
{
closeDevice();
if (blank_data)
free(blank_data);
}
void VDec::openDevice(void)
{
int n = 0;
lt_debug("%s\n", __func__);
/* todo: this fd checking is racy, should be protected by a lock */
if (fd != -1) /* already open */
return;
retry:
if ((fd = open(VIDEO_DEVICE, O_RDWR|O_CLOEXEC)) < 0)
{
if (errno == EBUSY)
{
/* sometimes we get busy quickly after close() */
usleep(50000);
if (++n < 10)
goto retry;
}
lt_info("%s cannot open %s: %m, retries %d\n", __func__, VIDEO_DEVICE, n);
}
playstate = VIDEO_STOPPED;
}
void VDec::closeDevice(void)
{
lt_debug("%s\n", __func__);
if (fd >= 0)
close(fd);
fd = -1;
playstate = VIDEO_STOPPED;
}
int cVideo::setAspectRatio(int aspect, int mode)
{
static const char *a[] = { "n/a", "4:3", "14:9", "16:9" };
/* { "panscan", "letterbox", "fullscreen", "14:9", "(unset)" } */
static const char *m[] = { "1", "2", "0", "1", "(unset)" };
int n;
lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mode < 0||mode > 3) ? 4 : mode]);
if (aspect > 3 || aspect == 0)
lt_info("%s: invalid aspect: %d\n", __func__, aspect);
else if (aspect > 0) /* -1 == don't set */
{
lt_debug("%s: /proc/stb/video/aspect -> %s\n", __func__, a[aspect]);
n = proc_put("/proc/stb/video/aspect", a[aspect], strlen(a[aspect]));
if (n < 0)
lt_info("%s: proc_put /proc/stb/video/aspect (%m)\n", __func__);
}
if (mode == -1)
return 0;
lt_debug("%s: /proc/scalingmode -> %s\n", __func__, m[mode]);
n = proc_put("/proc/scalingmode", m[mode], strlen(m[mode]));
if (n < 0)
return 1;
return 0;
}
int cVideo::getAspectRatio(void)
{
return vdec->getAspectRatio();
}
int VDec::getAspectRatio(void)
{
video_size_t s;
if (fd == -1)
{
/* in movieplayer mode, fd is not opened -> fall back to procfs */
int n = proc_get_hex("/proc/stb/vmpeg/0/aspect");
return n * 2 + 1;
}
if (fop(ioctl, VIDEO_GET_SIZE, &s) < 0)
{
lt_info("%s: VIDEO_GET_SIZE %m\n", __func__);
return -1;
}
lt_debug("%s: %d\n", __func__, s.aspect_ratio);
return s.aspect_ratio * 2 + 1;
}
int cVideo::setCroppingMode(void)
{
return 0;
#if 0
croppingMode = format;
const char *format_string[] = { "norm", "letterbox", "unknown", "mode_1_2", "mode_1_4", "mode_2x", "scale", "disexp" };
const char *f;
if (format >= VID_DISPMODE_NORM && format <= VID_DISPMODE_DISEXP)
f = format_string[format];
else
f = "ILLEGAL format!";
lt_debug("%s(%d) => %s\n", __FUNCTION__, format, f);
return fop(ioctl, MPEG_VID_SET_DISPMODE, format);
#endif
}
int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/)
{
return vdec->Start();
}
int cVideo::Stop(bool blank)
{
return vdec->Stop(blank);
}
int VDec::Start(void)
{
lt_debug("%s playstate=%d\n", __FUNCTION__, playstate);
#if 0
if (playstate == VIDEO_PLAYING)
return 0;
if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */
fop(ioctl, MPEG_VID_CONTINUE);
#endif
playstate = VIDEO_PLAYING;
return fop(ioctl, VIDEO_PLAY);
}
int VDec::Stop(bool blank)
{
lt_debug("%s(%d)\n", __FUNCTION__, blank);
if (stillpicture)
{
lt_debug("%s: stillpicture == true\n", __func__);
return -1;
}
/* blank parameter seems to not work on VIDEO_STOP */
if (blank)
setBlank(1);
playstate = blank ? VIDEO_STOPPED : VIDEO_FREEZED;
return fop(ioctl, VIDEO_STOP, blank ? 1 : 0);
}
int cVideo::setBlank(int b)
{
return vdec->setBlank(b);
}
int VDec::setBlank(int)
{
pthread_mutex_lock(&stillp_mutex);
if (blank_data)
show_iframe(fd, blank_data, blank_size);
pthread_mutex_unlock(&stillp_mutex);
return 1;
}
int cVideo::SetVideoSystem(int video_system, bool remember)
{
lt_debug("%s(%d, %d)\n", __func__, video_system, remember);
char current[32];
static const char *modes[] = {
"480i", // VIDEO_STD_NTSC
"576i", // VIDEO_STD_SECAM
"576i", // VIDEO_STD_PAL
"480p", // VIDEO_STD_480P
"576p", // VIDEO_STD_576P
"720p60", // VIDEO_STD_720P60
"1080i60", // VIDEO_STD_1080I60
"720p50", // VIDEO_STD_720P50
"1080i50", // VIDEO_STD_1080I50
"1080p30", // VIDEO_STD_1080P30
"1080p24", // VIDEO_STD_1080P24
"1080p25", // VIDEO_STD_1080P25
"720p50", // VIDEO_STD_AUTO -> not implemented
"1080p50" // VIDEO_STD_1080P50 -> SPARK only
};
if (video_system > VIDEO_STD_MAX)
{
lt_info("%s: video_system (%d) > VIDEO_STD_MAX (%d)\n", __func__, video_system, VIDEO_STD_MAX);
return -1;
}
int ret = proc_get("/proc/stb/video/videomode", current, 32);
if (strcmp(current, modes[video_system]) == 0)
{
lt_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current);
return 0;
}
lt_info("%s: old: '%s' new: '%s'\n", __func__, current, modes[video_system]);
ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system]));
return ret;
}
int cVideo::getPlayState(void)
{
return vdec->playstate;
}
void cVideo::SetVideoMode(analog_mode_t mode)
{
lt_debug("%s(%d)\n", __func__, mode);
if (!(mode & ANALOG_SCART_MASK))
{
lt_debug("%s: non-SCART mode ignored\n", __func__);
return;
}
const char *m;
switch(mode)
{
case ANALOG_SD_YPRPB_SCART:
m = "yuv";
break;
case ANALOG_SD_RGB_SCART:
m = "rgb";
break;
default:
lt_info("%s unknown mode %d\n", __func__, mode);
m = "rgb";
break; /* default to rgb */
}
proc_put("/proc/stb/avs/0/colorformat", m, strlen(m));
}
bool cVideo::ShowPicture(const char * fname)
{
return vdec->ShowPicture(fname);
}
bool VDec::ShowPicture(const char * fname)
{
bool ret = false;
lt_debug("%s(%s)\n", __func__, fname);
char destname[512];
char cmd[512];
char *p;
int mfd;
unsigned char *iframe;
struct stat st, st2;
if (video_standby)
{
/* does not work and the driver does not seem to like it */
lt_info("%s: video_standby == true\n", __func__);
return ret;
}
if (fd < 0)
{
lt_info("%s: decoder not opened\n", __func__);
return ret;
}
strcpy(destname, "/var/cache");
if (stat(fname, &st2))
{
lt_info("%s: could not stat %s (%m)\n", __func__, fname);
return ret;
}
mkdir(destname, 0755);
/* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg):
/var/cache/share.tuxbox.neutrino.icons.radiomode.jpg.m2v
build that filename first...
TODO: this could cause name clashes, use a hashing function instead... */
strcat(destname, fname);
p = &destname[strlen("/var/cache/")];
while ((p = strchr(p, '/')) != NULL)
*p = '.';
strcat(destname, ".m2v");
/* ...then check if it exists already... */
if (stat(destname, &st) || (st.st_mtime != st2.st_mtime) || (st.st_size == 0))
{
struct utimbuf u;
u.actime = time(NULL);
u.modtime = st2.st_mtime;
/* it does not exist or has a different date, so call ffmpeg... */
sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 1280x720 '%s' </dev/null",
fname, destname);
system(cmd); /* TODO: use libavcodec to directly convert it */
utime(destname, &u);
}
/* the mutex is a workaround: setBlank is apparently called from
a differnt thread and takes slightly longer, so that the decoder
was blanked immediately after displaying the image, which is not
what we want. the mutex ensures proper ordering. */
pthread_mutex_lock(&stillp_mutex);
mfd = open(destname, O_RDONLY|O_CLOEXEC);
if (mfd < 0)
{
lt_info("%s cannot open %s: %m", __func__, destname);
goto out;
}
fstat(mfd, &st);
stillpicture = true;
iframe = (unsigned char *)malloc(st.st_size);
if (! iframe)
{
lt_info("%s: malloc failed (%m)\n", __func__);
goto out;
}
read(mfd, iframe, st.st_size);
show_iframe(fd, iframe, st.st_size);
free(iframe);
ret = true;
out:
close(mfd);
pthread_mutex_unlock(&stillp_mutex);
return ret;
}
void cVideo::StopPicture()
{
lt_debug("%s\n", __func__);
vdec->stillpicture = false;
}
void cVideo::Standby(unsigned int bOn)
{
vdec->Standby(bOn);
}
void VDec::Standby(unsigned int bOn)
{
lt_debug("%s(%d)\n", __func__, bOn);
if (bOn)
{
closeDevice();
proc_put("/proc/stb/avs/0/input", "aux", 4);
}
else
{
proc_put("/proc/stb/avs/0/input", "encoder", 8);
openDevice();
}
video_standby = bOn;
}
int cVideo::getBlank(void)
{
int ret = proc_get_hex("/proc/stb/vmpeg/0/xres");
lt_debug("%s => %d\n", __func__, !ret);
return !ret;
}
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
{
vdec->Pig(x, y, w, h, osd_w, osd_h);
}
void VDec::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
{
char buffer[64];
int _x, _y, _w, _h;
/* the target "coordinates" seem to be in a PAL sized plane
* TODO: check this in the driver sources */
int xres = 720; /* proc_get_hex("/proc/stb/vmpeg/0/xres") */
int yres = 576; /* proc_get_hex("/proc/stb/vmpeg/0/yres") */
lt_debug("%s: x:%d y:%d w:%d h:%d ow:%d oh:%d\n", __func__, x, y, w, h, osd_w, osd_h);
if (x == -1 && y == -1 && w == -1 && h == -1)
{
_w = xres;
_h = yres;
_x = 0;
_y = 0;
}
else
{
_x = x * xres / osd_w;
_w = w * xres / osd_w;
_y = y * yres / osd_h;
_h = h * yres / osd_h;
}
lt_debug("%s: x:%d y:%d w:%d h:%d xr:%d yr:%d\n", __func__, _x, _y, _w, _h, xres, yres);
sprintf(buffer, "%x", _x);
proc_put("/proc/stb/vmpeg/0/dst_left", buffer, strlen(buffer));
sprintf(buffer, "%x", _y);
proc_put("/proc/stb/vmpeg/0/dst_top", buffer, strlen(buffer));
sprintf(buffer, "%x", _w);
proc_put("/proc/stb/vmpeg/0/dst_width", buffer, strlen(buffer));
sprintf(buffer, "%x", _h);
proc_put("/proc/stb/vmpeg/0/dst_height", buffer, strlen(buffer));
}
static inline int rate2csapi(int rate)
{
switch (rate)
{
/* no idea how the float values are represented by the driver */
case 23976:
return 0;
case 24:
return 1;
case 25:
return 2;
case 29976:
return 3;
case 30:
return 4;
case 50:
return 5;
case 50940:
return 6;
case 60:
return 7;
default:
break;
}
return -1;
}
void cVideo::getPictureInfo(int &width, int &height, int &rate)
{
vdec->getPictureInfo(width, height, rate);
}
void VDec::getPictureInfo(int &width, int &height, int &rate)
{
video_size_t s;
int r;
if (fd == -1)
{
/* in movieplayer mode, fd is not opened -> fall back to procfs */
r = proc_get_hex("/proc/stb/vmpeg/0/framerate");
width = proc_get_hex("/proc/stb/vmpeg/0/xres");
height = proc_get_hex("/proc/stb/vmpeg/0/yres");
rate = rate2csapi(r);
return;
}
ioctl(fd, VIDEO_GET_SIZE, &s);
ioctl(fd, VIDEO_GET_FRAME_RATE, &r);
rate = rate2csapi(r);
height = s.h;
width = s.w;
lt_debug("%s: rate: %d, width: %d height: %d\n", __func__, rate, width, height);
}
void cVideo::SetSyncMode(AVSYNC_TYPE mode)
{
lt_debug("%s %d\n", __func__, mode);
/*
* { 0, LOCALE_OPTIONS_OFF },
* { 1, LOCALE_OPTIONS_ON },
* { 2, LOCALE_AUDIOMENU_AVSYNC_AM }
*/
#if 0
switch(Mode)
{
case 0:
ioctl(fd, MPEG_VID_SYNC_OFF);
break;
case 1:
ioctl(fd, MPEG_VID_SYNC_ON, VID_SYNC_VID);
break;
default:
ioctl(fd, MPEG_VID_SYNC_ON, VID_SYNC_AUD);
break;
}
#endif
};
int cVideo::SetStreamType(VIDEO_FORMAT type)
{
return vdec->SetStreamType(type);
}
int VDec::SetStreamType(VIDEO_FORMAT type)
{
static const char *VF[] = {
"VIDEO_FORMAT_MPEG2",
"VIDEO_FORMAT_MPEG4",
"VIDEO_FORMAT_VC1",
"VIDEO_FORMAT_JPEG",
"VIDEO_FORMAT_GIF",
"VIDEO_FORMAT_PNG"
};
int t;
lt_debug("%s type=%s\n", __FUNCTION__, VF[type]);
switch (type)
{
case VIDEO_FORMAT_MPEG4:
t = VIDEO_STREAMTYPE_MPEG4_H264;
break;
case VIDEO_FORMAT_VC1:
t = VIDEO_STREAMTYPE_VC1;
break;
case VIDEO_FORMAT_MPEG2:
default:
t = VIDEO_STREAMTYPE_MPEG2;
break;
}
if (ioctl(fd, VIDEO_SET_STREAMTYPE, t) < 0)
lt_info("%s VIDEO_SET_STREAMTYPE(%d) failed: %m\n", __func__, t);
return 0;
}
int64_t VDec::GetPTS(void)
{
int64_t pts = 0;
if (ioctl(fd, VIDEO_GET_PTS, &pts) < 0)
lt_info("%s: GET_PTS failed (%m)\n", __func__);
return pts;
}
static void show_iframe(int fd, unsigned char *iframe, size_t st_size)
{
static const unsigned char pes_header[] = { 0, 0, 1, 0xE0, 0, 0, 0x80, 0x80, 5, 0x21, 0, 1, 0, 1};
static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 };
unsigned char stuffing[128];
bool seq_end_avail = false;
size_t pos = 0;
int count = 7;
if (ioctl(fd, VIDEO_SET_FORMAT, VIDEO_FORMAT_16_9) < 0)
lt_info_c("%s: VIDEO_SET_FORMAT failed (%m)\n", __func__);
ioctl(fd, VIDEO_SET_STREAMTYPE, VIDEO_FORMAT_MPEG2);
ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
ioctl(fd, VIDEO_PLAY);
ioctl(fd, VIDEO_CONTINUE);
ioctl(fd, VIDEO_CLEAR_BUFFER);
while (pos <= (st_size-4) && !(seq_end_avail = (!iframe[pos] && !iframe[pos+1] && iframe[pos+2] == 1 && iframe[pos+3] == 0xB7)))
++pos;
while (count--)
{
if ((iframe[3] >> 4) != 0xE) // no pes header
write(fd, pes_header, sizeof(pes_header));
else
iframe[4] = iframe[5] = 0x00;
write(fd, iframe, st_size);
usleep(8000);
}
if (!seq_end_avail)
write(fd, seq_end, sizeof(seq_end));
memset(stuffing, 0, sizeof(stuffing));
for (count = 0; count < 8192 / (int)sizeof(stuffing); count++)
write(fd, stuffing, sizeof(stuffing));
ioctl(fd, VIDEO_STOP, 0);
ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
}
void cVideo::SetDemux(cDemux *)
{
lt_debug("%s: not implemented yet\n", __func__);
}

60
azbox/video_priv.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* private video functions, to be used only inside libstb-hal
*/
#ifndef __video_priv__
#define __video_priv__
#include <video_hal.h>
#include <linux/dvb/video.h>
class VDec
{
public:
/* all public, used inside libstb-hal only anyways... */
int fd; /* video device fd */
/* apparently we cannot query the driver's state
=> remember it */
video_play_state_t playstate;
int video_standby;
bool stillpicture;
/* constructor & destructor */
VDec(void);
~VDec(void);
/* used directly by cVideo */
int getAspectRatio(void);
void getPictureInfo(int &width, int &height, int &rate);
int Start(void);
int Stop(bool blank = true);
int setBlank(int blank);
int SetStreamType(VIDEO_FORMAT type);
void SetSyncMode(AVSYNC_TYPE mode);
bool ShowPicture(const char * fname);
void Standby(unsigned int bOn);
void Pig(int x, int y, int w, int h, int osd_w, int osd_h);
/* used internally by dmx */
int64_t GetPTS(void);
/* used internally by playback */
void openDevice(void);
void closeDevice(void);
};
#endif

View File

@@ -5,58 +5,9 @@ AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_CXXFLAGS += \
-I $(top_srcdir)/include
AM_LDFLAGS = -lpthread
if BOXTYPE_DUCKBOX
AM_CXXFLAGS += \
-I $(top_srcdir)/libdvbci
endif
if BOXTYPE_ARMBOX
AM_CXXFLAGS += \
-I $(top_srcdir)/libdvbci
endif
if BOXTYPE_MIPSBOX
AM_CXXFLAGS += \
-I $(top_srcdir)/libdvbci
endif
if BOXTYPE_MIPSBOX
libcommon_la_SOURCES = \
ca_ci.cpp
else
if BOXTYPE_DUCKBOX
libcommon_la_SOURCES = \
ca_ci.cpp
else
if BOXTYPE_ARMBOX
if BOXMODEL_HD60
libcommon_la_SOURCES = \
ca.cpp
else
if BOXMODEL_OSMIO4K
libcommon_la_SOURCES = \
ca.cpp
else
if BOXMODEL_OSMIO4KPLUS
libcommon_la_SOURCES = \
ca.cpp
else
libcommon_la_SOURCES = \
ca_ci.cpp
endif
endif
endif
else
libcommon_la_SOURCES = \
ca.cpp
endif
endif
endif
libcommon_la_SOURCES += \
hal_debug.cpp \
ca.cpp \
lt_debug.c \
proc_tools.c \
pwrmngr.cpp \
version_hal.cpp

View File

@@ -1,8 +1,8 @@
#include <stdio.h>
#include "ca_hal.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_CA, this, args)
#include "ca.h"
#include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_CA, this, args)
static cCA *inst = NULL;
@@ -10,17 +10,17 @@ static cCA *inst = NULL;
/* those are all dummies for now.. */
cCA::cCA(void)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
}
cCA::~cCA()
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
}
cCA *cCA::GetInstance()
{
_hal_debug(HAL_DEBUG_CA, NULL, "%s\n", __FUNCTION__);
_lt_debug(TRIPLE_DEBUG_CA, NULL, "%s\n", __FUNCTION__);
if (inst == NULL)
inst = new cCA();
@@ -29,82 +29,82 @@ cCA *cCA::GetInstance()
void cCA::MenuEnter(enum CA_SLOT_TYPE, uint32_t p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
void cCA::MenuAnswer(enum CA_SLOT_TYPE, uint32_t p, uint32_t /*choice*/)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
void cCA::InputAnswer(enum CA_SLOT_TYPE, uint32_t p, uint8_t * /*Data*/, int /*Len*/)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
void cCA::MenuClose(enum CA_SLOT_TYPE, uint32_t p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
uint32_t cCA::GetNumberCISlots(void)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
return 0;
}
uint32_t cCA::GetNumberSmartCardSlots(void)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
return 0;
}
void cCA::ModuleName(enum CA_SLOT_TYPE, uint32_t p, char * /*Name*/)
{
/* TODO: waht to do with *Name? */
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
bool cCA::ModulePresent(enum CA_SLOT_TYPE, uint32_t p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
return false;
}
void cCA::ModuleReset(enum CA_SLOT_TYPE, uint32_t p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
bool cCA::SendPMT(int, unsigned char *, int, CA_SLOT_TYPE)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
return true;
}
bool cCA::SendMessage(const CA_MESSAGE *)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
return true;
}
bool cCA::Start(void)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
return true;
}
void cCA::Stop(void)
{
hal_debug("%s\n", __FUNCTION__);
lt_debug("%s\n", __FUNCTION__);
}
void cCA::Ready(bool p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}
void cCA::SetInitMask(enum CA_INIT_MASK p)
{
hal_debug("%s param:%d\n", __FUNCTION__, (int)p);
lt_debug("%s param:%d\n", __FUNCTION__, (int)p);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +0,0 @@
#ifndef __HAL_DEBUG_H__
#define __HAL_DEBUG_H__
#define HAL_DEBUG_AUDIO 0
#define HAL_DEBUG_VIDEO 1
#define HAL_DEBUG_DEMUX 2
#define HAL_DEBUG_PLAYBACK 3
#define HAL_DEBUG_PWRMNGR 4
#define HAL_DEBUG_INIT 5
#define HAL_DEBUG_CA 6
#define HAL_DEBUG_RECORD 7
#define HAL_DEBUG_ALL ((1<<8)-1)
extern int debuglevel;
void _hal_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
void _hal_info(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
void hal_debug_init(void);
void hal_set_threadname(const char *name);
#endif // __HAL_DEBUG_H__

View File

@@ -1,4 +1,4 @@
/* libstb-hal debug functions */
/* libtriple debug functions */
#include <stdarg.h>
#include <stdio.h>
@@ -12,7 +12,7 @@ int cnxt_debug = 0; /* compat, unused */
int debuglevel = -1;
static const char* hal_facility[] = {
static const char* lt_facility[] = {
"audio ",
"video ",
"demux ",
@@ -24,10 +24,10 @@ static const char* hal_facility[] = {
NULL
};
void _hal_info(int facility, const void *func, const char *fmt, ...)
void _lt_info(int facility, const void *func, const char *fmt, ...)
{
/* %p does print "(nil)" instead of 0x00000000 for NULL */
fprintf(stderr, "[HAL:%08lx:%s] ", (long) func, hal_facility[facility]);
fprintf(stderr, "[LT:%08lx:%s] ", (long) func, lt_facility[facility]);
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
@@ -35,22 +35,22 @@ void _hal_info(int facility, const void *func, const char *fmt, ...)
}
void _hal_debug(int facility, const void *func, const char *fmt, ...)
void _lt_debug(int facility, const void *func, const char *fmt, ...)
{
if (debuglevel < 0)
fprintf(stderr, "hal_debug: debuglevel not initialized!\n");
fprintf(stderr, "lt_debug: debuglevel not initialized!\n");
if (! ((1 << facility) & debuglevel))
return;
fprintf(stderr, "[HAL:%08lx:%s] ", (long)func, hal_facility[facility]);
fprintf(stderr, "[LT:%08lx:%s] ", (long)func, lt_facility[facility]);
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
void hal_debug_init(void)
void lt_debug_init(void)
{
int i = 0;
char *tmp = getenv("HAL_DEBUG");
@@ -65,16 +65,16 @@ void hal_debug_init(void)
{
fprintf(stderr, "libstb-hal debug options can be set by exporting HAL_DEBUG.\n");
fprintf(stderr, "The following values (or bitwise OR combinations) are valid:\n");
while (hal_facility[i]) {
fprintf(stderr, "\tcomponent: %s 0x%02x\n", hal_facility[i], 1 << i);
while (lt_facility[i]) {
fprintf(stderr, "\tcomponent: %s 0x%02x\n", lt_facility[i], 1 << i);
i++;
}
fprintf(stderr, "\tall components: 0x%02x\n", (1 << i) - 1);
} else {
fprintf(stderr, "libstb-hal debug is active for the following components:\n");
while (hal_facility[i]) {
while (lt_facility[i]) {
if (debuglevel & (1 << i))
fprintf(stderr, "%s ", hal_facility[i]);
fprintf(stderr, "%s ", lt_facility[i]);
i++;
}
fprintf(stderr, "\n");

36
common/lt_debug.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef __LT_DEBUG_H
#define __LT_DEBUG_H
#define TRIPLE_DEBUG_AUDIO 0
#define TRIPLE_DEBUG_VIDEO 1
#define TRIPLE_DEBUG_DEMUX 2
#define TRIPLE_DEBUG_PLAYBACK 3
#define TRIPLE_DEBUG_PWRMNGR 4
#define TRIPLE_DEBUG_INIT 5
#define TRIPLE_DEBUG_CA 6
#define TRIPLE_DEBUG_RECORD 7
#define TRIPLE_DEBUG_ALL ((1<<8)-1)
#define HAL_DEBUG_AUDIO 0
#define HAL_DEBUG_VIDEO 1
#define HAL_DEBUG_DEMUX 2
#define HAL_DEBUG_PLAYBACK 3
#define HAL_DEBUG_PWRMNGR 4
#define HAL_DEBUG_INIT 5
#define HAL_DEBUG_CA 6
#define HAL_DEBUG_RECORD 7
#define HAL_DEBUG_ALL ((1<<8)-1)
#ifdef __cplusplus
extern "C" {
#endif
extern int debuglevel;
void hal_set_threadname(const char *name);
void _lt_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
void _lt_info(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
void lt_debug_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -17,8 +17,9 @@
#include <config.h>
#include "pwrmngr.h"
#include "hal_debug.h"
#include "lt_debug.h"
#if HAVE_TRIPLEDRAGON
#include <stdio.h>
#include <cstdlib>
@@ -28,68 +29,51 @@
#include <sys/stat.h>
#include <sys/types.h>
#if HAVE_TRIPLEDRAGON
#include <avs/avs_inf.h>
#include <tdpanel/lcdstuff.h>
#endif
#define hal_debug(args...) _hal_debug(HAL_DEBUG_PWRMNGR, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_PWRMNGR, this, args)
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PWRMNGR, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_PWRMNGR, this, args)
/* cpufreqmanager */
void cCpuFreqManager::Up(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
void cCpuFreqManager::Down(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
void cCpuFreqManager::Reset(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
/* those function dummies return true or "harmless" values */
bool cCpuFreqManager::SetDelta(unsigned long)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
return true;
}
unsigned long cCpuFreqManager::GetDelta(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
return 0;
}
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE
unsigned long cCpuFreqManager::GetCpuFreq(void) {
int freq = 0;
if (FILE *pll0 = fopen("/proc/cpu_frequ/pll0_ndiv_mdiv", "r")) {
char buffer[120];
while(fgets(buffer, sizeof(buffer), pll0)) {
if (1 == sscanf(buffer, "SH4 = %d MHZ", &freq))
break;
}
fclose(pll0);
return 1000 * 1000 * (unsigned long) freq;
}
return 0;
}
#else
unsigned long cCpuFreqManager::GetCpuFreq(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
return 0;
}
#endif
bool cCpuFreqManager::SetCpuFreq(unsigned long f)
{
hal_info("%s(%lu) => set standby = %s\n", __func__, f, f?"true":"false");
lt_info("%s(%lu) => set standby = %s\n", __func__, f, f?"true":"false");
#if HAVE_TRIPLEDRAGON
/* actually SetCpuFreq is used to determine if the system is in standby
this is an "elegant" hack, because:
@@ -113,11 +97,11 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
ioctl(fd, IOC_AVS_STANDBY_ENTER);
if (getenv("TRIPLE_LCDBACKLIGHT"))
{
hal_info("%s: TRIPLE_LCDBACKLIGHT is set: keeping LCD backlight on\n", __func__);
lt_info("%s: TRIPLE_LCDBACKLIGHT is set: keeping LCD backlight on\n", __func__);
close(fd);
fd = open("/dev/stb/tdlcd", O_RDONLY);
if (fd < 0)
hal_info("%s: open tdlcd error: %m\n", __func__);
lt_info("%s: open tdlcd error: %m\n", __func__);
else
ioctl(fd, IOC_LCD_BACKLIGHT_ON);
}
@@ -131,49 +115,38 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
}
close(fd);
#elif HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE
if (f) {
FILE *pll0 = fopen ("/proc/cpu_frequ/pll0_ndiv_mdiv", "w");
if (pll0) {
f /= 1000000;
fprintf(pll0, "%lu\n", (f/10 << 8) | 3);
fclose (pll0);
return false;
}
}
#endif
return true;
}
cCpuFreqManager::cCpuFreqManager(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
/* powermanager */
bool cPowerManager::Open(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
return true;
}
void cPowerManager::Close(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
bool cPowerManager::SetStandby(bool Active, bool Passive)
{
hal_debug("%s(%d, %d)\n", __func__, Active, Passive);
lt_debug("%s(%d, %d)\n", __func__, Active, Passive);
return true;
}
cPowerManager::cPowerManager(void)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}
cPowerManager::~cPowerManager()
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
}

View File

@@ -1,7 +1,7 @@
# explicit defines for separate revision handling
define(ver_major, 1)
define(ver_minor, 4)
define(ver_micro, 0)
define(ver_major, 0)
define(ver_minor, 2)
define(ver_micro, 1)
# sync with current git
define(ver_git, m4_esyscmd([
@@ -12,9 +12,10 @@ define(ver_git, m4_esyscmd([
AC_PACKAGE_NAME, PACKAGE_NAME_LIBSTB_HAL
AC_INIT([Tuxbox-libstb-hal], [ver_major.ver_minor.ver_micro])
AM_INIT_AUTOMAKE([foreign])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([libstb-hal-config.h:config.h.in])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
AC_CONFIG_MACRO_DIR([m4])
AC_GNU_SOURCE
AC_DEFINE(PACKAGE_VERSION_MAJOR, ver_major, [Major version number])
@@ -23,6 +24,7 @@ AC_DEFINE(PACKAGE_VERSION_MICRO, ver_micro, [Micro version number])
AC_DEFINE(PACKAGE_VERSION_GIT, "ver_git", [internal vcs version info])
TUXBOX_APPS
TUXBOX_APPS_DIRECTORY
TUXBOX_BOXTYPE
AC_PROG_CC
@@ -35,7 +37,7 @@ PKG_PROG_PKG_CONFIG
AC_DISABLE_SHARED
AC_DISABLE_STATIC
AC_SYS_LARGEFILE
LT_INIT
AC_PROG_LIBTOOL
AC_ARG_ENABLE(clutter,
AS_HELP_STRING(--enable-clutter, use clutter instead of OpenGL),
@@ -53,69 +55,51 @@ if test x"$BOXTYPE" = x"tripledragon"; then
PKG_CHECK_MODULES([DIRECTFB], [directfb])
fi
AC_ARG_ENABLE(gstreamer_01,
AS_HELP_STRING(--enable-gstreamer_01, use gstreamer 0.10 playback),
,[enable_gstreamer_01=no])
AM_CONDITIONAL(ENABLE_GSTREAMER_01,test "$enable_gstreamer_01" = "yes")
if test "$enable_gstreamer_01" = "yes"; then
AC_DEFINE(ENABLE_GSTREAMER_01, 1, [use gstreamer 0.10 playback])
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10])
PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10])
fi
AC_ARG_ENABLE(gstreamer_10,
AS_HELP_STRING(--enable-gstreamer_10, use gstreamer 1.0 playback),
,[enable_gstreamer_10=no])
AM_CONDITIONAL(ENABLE_GSTREAMER_10, test "$enable_gstreamer_10" = "yes")
if test "$enable_gstreamer_10" = "yes"; then
AC_DEFINE(ENABLE_GSTREAMER_10, 1, [use gstreamer 1.0 playback])
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0])
PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0])
PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0])
fi
if test x$BOXTYPE = xarmbox -a "$enable_gstreamer_10" = "yes"; then
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0])
PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0])
PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0])
fi
if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
if test x$BOXTYPE = xgeneric; then
if test x"$enable_clutter" = xyes; then
PKG_CHECK_MODULES([CLUTTER], [clutter-1.0])
fi
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
if test x$BOXMODEL != xraspi; then
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
# don't know which version is exactly needed here...
PKG_CHECK_MODULES([SWSCALE], [libswscale])
else
# openmaxil are the broadcom userspace libs
# my yocto (openembedded) layer has an openmaxil package built from userland git.
# Use that if available. If not, just fall back to /opt/vc/...
# can be overridden with OMX_CFLAGS= OMX_LIBS= variables...
#
PKG_CHECK_MODULES([OMX], [openmaxil], echo "OpenMAX/IL userspace package found. Good.",
[ echo "OpenMAX/IL package not found, assuming /opt/vc/..."
OMX_CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux"
OMX_LIBS="-L/opt/vc/lib/ -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -pthread"
])
# raspbian has no current versions and only libav instead of ffmpeg... :-(
PKG_CHECK_MODULES([AVFORMAT], [libavformat])
PKG_CHECK_MODULES([AVCODEC], [libavcodec])
fi
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
# don't know which version is exactly needed here...
PKG_CHECK_MODULES([AVUTIL], [libavutil])
PKG_CHECK_MODULES([SWSCALE], [libswscale])
fi
if test x$BOXTYPE = xspark; then
# versions are probably not correct :-(
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
PKG_CHECK_MODULES([AVUTIL], [libavutil])
fi
AC_ARG_ENABLE(flv2mpeg4,
AS_HELP_STRING(--enable-flv2mpeg4, use flv2mpeg4 libeplayer3),
,[enable_flv2mpeg4=no])
AM_CONDITIONAL(ENABLE_FLV2MPEG4, test "$enable_flv2mpeg4" = "yes")
if test "$enable_flv2mpeg4" = "yes"; then
AC_DEFINE(ENABLE_FLV2MPEG4, 1, [use flv2mpeg4 libeplayer3])
fi
AC_CONFIG_FILES([
AC_OUTPUT([
Makefile
common/Makefile
libmipsbox/Makefile
libarmbox/Makefile
libduckbox/Makefile
libdvbci/Makefile
libeplayer3/Makefile
libeplayer3-sh4/Makefile
libgeneric-pc/Makefile
libraspi/Makefile
azbox/Makefile
generic-pc/Makefile
libtriple/Makefile
libspark/Makefile
raspi/Makefile
tools/Makefile
])
AC_OUTPUT

View File

@@ -11,7 +11,7 @@ AM_CPPFLAGS += \
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = \
-lao -lrt \
-lao \
-lOpenThreads \
@AVFORMAT_LIBS@ \
@AVUTIL_LIBS@ \
@@ -30,6 +30,7 @@ libgeneric_la_SOURCES = \
video.cpp \
audio.cpp \
init.cpp \
playback.cpp \
record.cpp
if USE_CLUTTER
@@ -38,23 +39,3 @@ endif
if USE_OPENGL
libgeneric_la_SOURCES += glfb.cpp
endif
if ENABLE_GSTREAMER_01
libgeneric_la_SOURCES += \
playback_gst_01.cpp
AM_LDFLAGS += \
-lgstreamer-0.10 \
-lgstinterfaces-0.10
else
if ENABLE_GSTREAMER_10
libgeneric_la_SOURCES += \
playback_gst_10.cpp
AM_LDFLAGS += \
-lgstreamer-1.0 \
-lgsttag-1.0 \
-lgstmpegts-1.0
else
libgeneric_la_SOURCES += \
playback.cpp
endif
endif

View File

@@ -22,56 +22,51 @@
#include <cstdio>
#include <cstdlib>
#include "audio_lib.h"
#include "audio_hal.h"
#include "audio_priv.h"
#include "dmx_hal.h"
#include "hal_debug.h"
#include "lt_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_AUDIO, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_AUDIO, this, args)
#define lt_debug(args...) _lt_debug(HAL_DEBUG_AUDIO, this, args)
#define lt_info(args...) _lt_info(HAL_DEBUG_AUDIO, this, args)
#include <OpenThreads/Thread>
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <ao/ao.h>
}
/* ffmpeg buf 2k */
#define INBUF_SIZE 0x0800
/* my own buf 16k */
#define DMX_BUF_SZ 0x4000
cAudio * audioDecoder = NULL;
ADec *adec = NULL;
extern cDemux *audioDemux;
static uint8_t *dmxbuf = NULL;
static int bufpos;
extern bool HAL_nodec;
static cAudio *gThiz = NULL;
static ao_device *adevice = NULL;
static ao_sample_format sformat;
static AVCodecContext *c = NULL;
static AVCodecParameters *p = NULL;
cAudio::cAudio(void *, void *, void *)
{
adec = new ADec();
}
cAudio::~cAudio(void)
{
delete adec;
}
ADec::ADec(void)
{
adevice = NULL;
dmxbuf = NULL;
bufpos = 0;
c = NULL;
thread_started = false;
if (!HAL_nodec)
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
bufpos = 0;
curr_pts = 0;
gThiz = this;
ao_initialize();
}
cAudio::~cAudio(void)
ADec::~ADec(void)
{
closeDevice();
free(dmxbuf);
if (adevice)
ao_close(adevice);
@@ -79,46 +74,56 @@ cAudio::~cAudio(void)
ao_shutdown();
}
void cAudio::openDevice(void)
int cAudio::mute(void)
{
hal_debug("%s\n", __func__);
return SetMute(true);
}
void cAudio::closeDevice(void)
int cAudio::unmute(void)
{
hal_debug("%s\n", __func__);
return SetMute(false);
}
int cAudio::do_mute(bool enable, bool remember)
int cAudio::SetMute(bool enable)
{
hal_debug("%s(%d, %d)\n", __func__, enable, remember);
lt_debug("%s(%d)\n", __func__, enable);
return 0;
}
int cAudio::setVolume(unsigned int left, unsigned int right)
{
hal_debug("%s(%d, %d)\n", __func__, left, right);
lt_debug("%s(%d, %d)\n", __func__, left, right);
return 0;
}
int cAudio::Start(void)
{
hal_debug("%s >\n", __func__);
if (! HAL_nodec)
OpenThreads::Thread::start();
hal_debug("%s <\n", __func__);
return 0;
return adec->Start();
}
int cAudio::Stop(void)
{
hal_debug("%s >\n", __func__);
return adec->Stop();
}
int ADec::Start(void)
{
lt_debug("%s >\n", __func__);
if (! HAL_nodec)
start();
lt_debug("%s <\n", __func__);
return 0;
}
int ADec::Stop(void)
{
lt_debug("%s >\n", __func__);
if (thread_started)
{
thread_started = false;
OpenThreads::Thread::join();
join();
}
hal_debug("%s <\n", __func__);
lt_debug("%s <\n", __func__);
return 0;
}
@@ -129,12 +134,12 @@ bool cAudio::Pause(bool /*Pcm*/)
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
{
hal_debug("%s %d\n", __func__, Mode);
lt_debug("%s %d\n", __func__, Mode);
};
void cAudio::SetStreamType(AUDIO_FORMAT type)
{
hal_debug("%s %d\n", __func__, type);
lt_debug("%s %d\n", __func__, type);
};
int cAudio::setChannel(int /*channel*/)
@@ -144,7 +149,12 @@ int cAudio::setChannel(int /*channel*/)
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
{
hal_debug("%s ch %d srate %d bits %d le %d adevice %p\n", __func__, ch, srate, bits, le, adevice);;
return adec->PrepareClipPlay(ch, srate, bits, le);
}
int ADec::PrepareClipPlay(int ch, int srate, int bits, int le)
{
lt_debug("%s ch %d srate %d bits %d le %d adevice %p\n", __func__, ch, srate, bits, le, adevice);;
int driver;
int byte_format = le ? AO_FMT_LITTLE : AO_FMT_BIG;
if (sformat.bits != bits || sformat.channels != ch || sformat.rate != srate ||
@@ -160,9 +170,9 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
ao_close(adevice);
adevice = ao_open_live(driver, &sformat, NULL);
ao_info *ai = ao_driver_info(driver);
hal_info("%s: changed params ch %d srate %d bits %d le %d adevice %p\n",
lt_info("%s: changed params ch %d srate %d bits %d le %d adevice %p\n",
__func__, ch, srate, bits, le, adevice);;
hal_info("libao driver: %d name '%s' short '%s' author '%s'\n",
lt_info("libao driver: %d name '%s' short '%s' author '%s'\n",
driver, ai->name, ai->short_name, ai->author);
}
return 0;
@@ -170,9 +180,14 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
int cAudio::WriteClip(unsigned char *buffer, int size)
{
hal_debug("cAudio::%s buf 0x%p size %d\n", __func__, buffer, size);
return adec->WriteClip(buffer, size);
}
int ADec::WriteClip(unsigned char *buffer, int size)
{
lt_debug("cAudio::%s buf 0x%p size %d\n", __func__, buffer, size);
if (!adevice) {
hal_info("%s: adevice not opened?\n", __func__);
lt_info("%s: adevice not opened?\n", __func__);
return 0;
}
ao_play(adevice, (char *)buffer, size);
@@ -181,12 +196,12 @@ int cAudio::WriteClip(unsigned char *buffer, int size)
int cAudio::StopClip()
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
#if 0
/* don't do anything - closing / reopening ao all the time makes for long delays
* reinit on-demand (e.g. for changed parameters) instead */
if (!adevice) {
hal_info("%s: adevice not opened?\n", __func__);
lt_info("%s: adevice not opened?\n", __func__);
return 0;
}
ao_close(adevice);
@@ -196,6 +211,11 @@ int cAudio::StopClip()
};
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
{
adec->getAudioInfo(type, layer, freq, bitrate, mode);
}
void ADec::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
{
type = 0;
layer = 0; /* not used */
@@ -261,51 +281,46 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m
mode = 7; // "L/C/R/SL/SR"
break;
default:
hal_info("%s: unknown ch_layout 0x%" PRIx64 "\n",
lt_info("%s: unknown ch_layout 0x%" PRIx64 "\n",
__func__, c->channel_layout);
}
}
}
hal_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n",
lt_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n",
__func__, type, layer, freq, bitrate, mode, c?c->codec_id:-1);
};
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
{
hal_debug("%s\n", __func__);
lt_debug("%s\n", __func__);
};
void cAudio::SetHdmiDD(bool enable)
{
hal_debug("%s %d\n", __func__, enable);
lt_debug("%s %d\n", __func__, enable);
};
void cAudio::SetSpdifDD(bool enable)
{
hal_debug("%s %d\n", __func__, enable);
lt_debug("%s %d\n", __func__, enable);
};
void cAudio::ScheduleMute(bool On)
{
hal_debug("%s %d\n", __func__, On);
lt_debug("%s %d\n", __func__, On);
};
void cAudio::EnableAnalogOut(bool enable)
{
hal_debug("%s %d\n", __func__, enable);
lt_debug("%s %d\n", __func__, enable);
};
void cAudio::setBypassMode(bool disable)
{
hal_debug("%s %d\n", __func__, disable);
}
static int _my_read(void *, uint8_t *buf, int buf_size)
{
return gThiz->my_read(buf, buf_size);
return adec->my_read(buf, buf_size);
}
int cAudio::my_read(uint8_t *buf, int buf_size)
int ADec::my_read(uint8_t *buf, int buf_size)
{
int tmp = 0;
if (audioDecoder && bufpos < DMX_BUF_SZ - 4096) {
@@ -319,7 +334,7 @@ int cAudio::my_read(uint8_t *buf, int buf_size)
}
if (bufpos == 0)
return 0;
//hal_info("%s buf_size %d bufpos %d th %d tmp %d\n", __func__, buf_size, bufpos, thread_started, tmp);
//lt_info("%s buf_size %d bufpos %d th %d tmp %d\n", __func__, buf_size, bufpos, thread_started, tmp);
if (bufpos > buf_size) {
memcpy(buf, dmxbuf, buf_size);
memmove(dmxbuf, dmxbuf + buf_size, bufpos - buf_size);
@@ -332,13 +347,11 @@ int cAudio::my_read(uint8_t *buf, int buf_size)
return tmp;
}
void cAudio::run()
void ADec::run()
{
hal_info("====================== start decoder thread ================================\n");
lt_info("====================== start decoder thread ================================\n");
/* libavcodec & friends */
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
av_register_all();
#endif
AVCodec *codec;
AVFormatContext *avfc = NULL;
@@ -347,7 +360,6 @@ void cAudio::run()
uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE);
AVPacket avpkt;
int ret, driver;
int av_ret = 0;
/* libao */
ao_info *ai;
// ao_device *adevice;
@@ -377,40 +389,35 @@ void cAudio::run()
thread_started = true;
if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) {
hal_info("%s: avformat_open_input() failed.\n", __func__);
lt_info("%s: avformat_open_input() failed.\n", __func__);
goto out;
}
ret = avformat_find_stream_info(avfc, NULL);
hal_debug("%s: avformat_find_stream_info: %d\n", __func__, ret);
lt_debug("%s: avformat_find_stream_info: %d\n", __func__, ret);
if (avfc->nb_streams != 1)
{
hal_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams);
lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams);
goto out;
}
p = avfc->streams[0]->codecpar;
if (p->codec_type != AVMEDIA_TYPE_AUDIO)
hal_info("%s: stream 0 no audio codec? 0x%x\n", __func__, p->codec_type);
lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, p->codec_type);
codec = avcodec_find_decoder(p->codec_id);
if (!codec) {
hal_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
goto out;
}
if (c)
av_free(c);
c = avcodec_alloc_context3(codec);
if (avcodec_open2(c, codec, NULL) < 0) {
hal_info("%s: avcodec_open2() failed\n", __func__);
lt_info("%s: avcodec_open2() failed\n", __func__);
goto out;
}
if(p->sample_rate == 0 || p->channels == 0){
av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt);
hal_info("Header missing %s, sample_fmt %d (%s) sample_rate %d channels %d\n",avcodec_get_name(p->codec_id), c->sample_fmt, tmp, p->sample_rate, p->channels);
goto out2;
}
frame = av_frame_alloc();
if (!frame) {
hal_info("%s: av_frame_alloc failed\n", __func__);
lt_info("%s: av_frame_alloc failed\n", __func__);
goto out2;
}
/* output sample rate, channels, layout could be set here if necessary */
@@ -430,27 +437,27 @@ void cAudio::run()
ao_close(adevice);
adevice = ao_open_live(driver, &sformat, NULL);
ai = ao_driver_info(driver);
hal_info("%s: changed params ch %d srate %d bits %d adevice %p\n",
lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n",
__func__, o_ch, o_sr, 16, adevice);
if(ai)
hal_info("libao driver: %d name '%s' short '%s' author '%s'\n",
lt_info("libao driver: %d name '%s' short '%s' author '%s'\n",
driver, ai->name, ai->short_name, ai->author);
}
#if 0
hal_info(" driver options:");
lt_info(" driver options:");
for (int i = 0; i < ai->option_count; ++i)
fprintf(stderr, " %s", ai->options[i]);
fprintf(stderr, "\n");
#endif
av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt);
hal_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n",
lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n",
avcodec_get_name(p->codec_id), c->sample_fmt, tmp, p->sample_rate, p->channels);
swr = swr_alloc_set_opts(swr,
o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */
p->channel_layout, c->sample_fmt, p->sample_rate, /* input */
0, NULL);
if (! swr) {
hal_info("could not alloc resample context\n");
lt_info("could not alloc resample context\n");
goto out3;
}
swr_init(swr);
@@ -458,31 +465,17 @@ void cAudio::run()
int gotframe = 0;
if (av_read_frame(avfc, &avpkt) < 0)
break;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100)
avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
#else
av_ret = avcodec_send_packet(c, &avpkt);
if (av_ret != 0 && av_ret != AVERROR(EAGAIN)) {
hal_info("%s: avcodec_send_packet %d\n", __func__, av_ret);
}else {
av_ret = avcodec_receive_frame(c, frame);
if (av_ret != 0 && av_ret != AVERROR(EAGAIN)) {
hal_info("%s: avcodec_send_packet %d\n", __func__, av_ret);
}else {
gotframe = 1;
}
}
#endif
if (gotframe && thread_started) {
int out_linesize;
obuf_sz = av_rescale_rnd(swr_get_delay(swr, p->sample_rate) + frame->nb_samples, o_sr, p->sample_rate, AV_ROUND_UP);
obuf_sz = av_rescale_rnd(swr_get_delay(swr, p->sample_rate) +
frame->nb_samples, o_sr, p->sample_rate, AV_ROUND_UP);
if (obuf_sz > obuf_sz_max) {
hal_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max);
lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max);
av_free(obuf);
if (av_samples_alloc(&obuf, &out_linesize, o_ch,
frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) {
hal_info("av_samples_alloc failed\n");
lt_info("av_samples_alloc failed\n");
av_packet_unref(&avpkt);
break; /* while (thread_started) */
}
@@ -490,15 +483,11 @@ void cAudio::run()
}
obuf_sz = swr_convert(swr, &obuf, obuf_sz,
(const uint8_t **)frame->extended_data, frame->nb_samples);
#if (LIBAVUTIL_VERSION_MAJOR < 54)
curr_pts = av_frame_get_best_effort_timestamp(frame);
#else
curr_pts = frame->best_effort_timestamp;
#endif
hal_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0);
int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch, obuf_sz, AV_SAMPLE_FMT_S16, 1);
if (o_buf_sz > 0)
ao_play(adevice, (char *)obuf, o_buf_sz);
lt_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0);
int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch,
obuf_sz, AV_SAMPLE_FMT_S16, 1);
ao_play(adevice, (char *)obuf, o_buf_sz);
}
av_packet_unref(&avpkt);
}
@@ -515,5 +504,5 @@ void cAudio::run()
avformat_close_input(&avfc);
av_free(pIOCtx->buffer);
av_free(pIOCtx);
hal_info("======================== end decoder thread ================================\n");
lt_info("======================== end decoder thread ================================\n");
}

54
generic-pc/audio_priv.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* private stuff for the audio decoder, only used inside libstb-hal
*/
#include <OpenThreads/Thread>
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <ao/ao.h>
}
class ADec : public OpenThreads::Thread
{
public:
ADec();
~ADec();
int Start();
int Stop();
int PrepareClipPlay(int ch, int srate, int bits, int le);
int WriteClip(unsigned char *buffer, int size);
void getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode);
int my_read(uint8_t *buf, int buf_size);
int64_t getPts() { return curr_pts; };
private:
bool thread_started;
int64_t curr_pts;
void run();
ao_device *adevice;
ao_sample_format sformat;
uint8_t *dmxbuf;
int bufpos;
AVCodecContext *c;
AVCodecParameters *p;
};

View File

@@ -39,21 +39,21 @@
#include <unistd.h>
#include <linux/input.h>
#include "glfb_priv.h"
#include "video_lib.h"
#include "audio_lib.h"
#include "video_priv.h"
#include "audio_priv.h"
#include <clutter/x11/clutter-x11.h>
#include "hal_debug.h"
#include "lt_debug.h"
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, this, args)
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_INIT, NULL, args)
#define lt_info_c(args...) _lt_info(HAL_DEBUG_INIT, NULL, args)
#define lt_debug(args...) _lt_debug(HAL_DEBUG_INIT, this, args)
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
extern cVideo *videoDecoder;
extern cAudio *audioDecoder;
extern VDec *vdec;
extern ADec *adec;
/* the private class that does stuff only needed inside libstb-hal.
* is used e.g. by cVideo... */
@@ -123,7 +123,7 @@ GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mS
mkfifo("/tmp/neutrino.input", 0600);
input_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
if (input_fd < 0)
hal_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
initKeys();
}
@@ -137,15 +137,19 @@ GLFbPC::~GLFbPC()
void GLFbPC::initKeys()
{
/*
Keep in sync with initKeys() in glfb.cpp
*/
mKeyMap[CLUTTER_KEY_Up] = KEY_UP;
mKeyMap[CLUTTER_KEY_Down] = KEY_DOWN;
mKeyMap[CLUTTER_KEY_Left] = KEY_LEFT;
mKeyMap[CLUTTER_KEY_Right] = KEY_RIGHT;
mKeyMap[CLUTTER_KEY_F1] = KEY_RED;
mKeyMap[CLUTTER_KEY_F2] = KEY_GREEN;
mKeyMap[CLUTTER_KEY_F3] = KEY_YELLOW;
mKeyMap[CLUTTER_KEY_F4] = KEY_BLUE;
mKeyMap[CLUTTER_KEY_F1] = KEY_RED;
mKeyMap[CLUTTER_KEY_F2] = KEY_GREEN;
mKeyMap[CLUTTER_KEY_F3] = KEY_YELLOW;
mKeyMap[CLUTTER_KEY_F4] = KEY_BLUE;
mKeyMap[CLUTTER_KEY_F5] = KEY_RECORD;
mKeyMap[CLUTTER_KEY_F6] = KEY_PLAY;
@@ -213,13 +217,12 @@ void GLFramebuffer::run()
char **argv = (char **)malloc(sizeof(char *) * 2);
argv[0] = a;
argv[1] = NULL;
hal_info("GLFB: GL thread starting x %d y %d\n", x, y);
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
if (clutter_init(&argc, &argv) != CLUTTER_INIT_SUCCESS) {
hal_info("GLFB: error initializing clutter\n");
free(argv);
lt_info("GLFB: error initializing clutter\n");
return;
}
hal_info("GLFB: %s:%d\n", __func__, __LINE__);
lt_info("GLFB: %s:%d\n", __func__, __LINE__);
ClutterColor stage_color = { 0, 0, 0, 255 };
stage = clutter_stage_new();
clutter_actor_set_size(stage, x, y);
@@ -235,14 +238,14 @@ void GLFramebuffer::run()
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = x * y * 4 * 2;
osd_buf.resize(fbmem);
hal_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
/* video plane is below FB plane, so it comes first */
vid_actor = clutter_actor_new();
ClutterContent *fb = clutter_image_new();
/* osd_buf, because it starts up black */
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGR_888, x, y, x*3, NULL)) {
hal_info("GLFB::%s clutter_image_set_data failed? (vid)\n", __func__);
lt_info("GLFB::%s clutter_image_set_data failed? (vid)\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(vid_actor, fb);
@@ -261,7 +264,7 @@ void GLFramebuffer::run()
fb_actor = clutter_actor_new();
fb = clutter_image_new();
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
hal_info("GLFB::%s clutter_image_set_data failed? (osd)\n", __func__);
lt_info("GLFB::%s clutter_image_set_data failed? (osd)\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(fb_actor, fb);
@@ -282,8 +285,9 @@ void GLFramebuffer::run()
clutter_timeline_set_repeat_count(tl, -1);
clutter_timeline_start(tl);
clutter_main();
hal_info("GLFB: GL thread stopping\n");
g_object_unref(tl);
free(argv);
lt_info("GLFB: GL thread stopping\n");
}
/* static */ void GLFbPC::rendercb()
@@ -295,12 +299,12 @@ void GLFramebuffer::run()
{
guint key = clutter_event_get_key_symbol (event);
int keystate = user_data ? 1 : 0;
hal_info_c("GLFB::%s: 0x%x, %d\n", __func__, key, keystate);
lt_debug_c("GLFB::%s: 0x%x, %d\n", __func__, key, keystate);
struct input_event ev;
if (key == 'f' && keystate)
{
hal_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
glfb_priv->mReInit = true;
return true;
@@ -312,10 +316,8 @@ void GLFramebuffer::run()
ev.value = keystate; /* key own */
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
hal_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
ssize_t w = write(glfb_priv->input_fd, &ev, sizeof(ev));
if(w < 0)
return false;
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(glfb_priv->input_fd, &ev, sizeof(ev));
return true;
}
@@ -327,6 +329,11 @@ void GLFbPC::render()
clutter_main_quit();
mReInitLock.lock();
if (vdec && vdec->pig_changed)
{
mReInit = true;
vdec->pig_changed = false;
}
if (mReInit)
{
int xoff = 0;
@@ -347,16 +354,15 @@ void GLFbPC::render()
// *mX = *mY * mOA.num / mOA.den;
clutter_actor_set_size(stage, *mX, *mY);
}
hal_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
lt_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
__func__, *mX, *mY, xoff, yoff, mFullscreen);
}
mReInitLock.unlock();
bltDisplayBuffer(); /* decoded video stream */
if (mState.blit) {
/* only blit manually after fb->blit(), this helps to find missed blit() calls */
mState.blit = false;
hal_debug("GLFB::%s blit!\n", __func__);
lt_debug("GLFB::%s blit!\n", __func__);
bltOSDBuffer(); /* OSD */
}
@@ -372,10 +378,10 @@ void GLFbPC::render()
default:
case INT_MIN: /* invalid */
case 0: /* identical */
hal_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
lt_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
break;
case 1: /* mVA > mOA -- video is wider than display */
hal_debug("%s: mVA > mOA\n", __func__);
lt_debug("%s: mVA > mOA\n", __func__);
switch (mCrop) {
case DISPLAY_AR_MODE_PANSCAN:
zoom = av_q2d(mVA) / av_q2d(mOA);
@@ -394,7 +400,7 @@ void GLFbPC::render()
}
break;
case -1: /* mVA < mOA -- video is taller than display */
hal_debug("%s: mVA < mOA\n", __func__);
lt_debug("%s: mVA < mOA\n", __func__);
switch (mCrop) {
case DISPLAY_AR_MODE_LETTERBOX:
break;
@@ -403,7 +409,6 @@ void GLFbPC::render()
zoom = av_q2d(mVA) * av_q2d(a149) / av_q2d(mOA);
break;
}
// fall through
/* fallthrough for output format 14:9 */
case DISPLAY_AR_MODE_PANSCAN:
zoom = av_q2d(mOA) / av_q2d(mVA);
@@ -416,7 +421,19 @@ void GLFbPC::render()
}
break;
}
hal_debug("zoom: %f xscale: %f xzoom: %f\n", zoom, xscale,xzoom);
if (vdec &&
vdec->pig_x >= 0 && vdec->pig_y >= 0 &&
vdec->pig_w > 0 && vdec->pig_h > 0) {
int ox = mState.width - vdec->pig_w;
int oy = mState.height - vdec->pig_h;
float ppx = vdec->pig_x / (float) ox;
float ppy = vdec->pig_y / (float) oy;
zoom = zoom * (float)vdec->pig_w / mState.width;
clutter_actor_set_pivot_point(vid_actor, ppx, ppy);
} else {
clutter_actor_set_pivot_point(vid_actor, 0.5, 0.5);
}
lt_debug("zoom: %f xscale: %f xzoom: %f\n", zoom, xscale,xzoom);
clutter_actor_set_scale(vid_actor, xscale*zoom*xzoom, zoom);
}
clutter_timeline_stop(tl);
@@ -426,12 +443,12 @@ void GLFbPC::render()
void GLFbPC::bltOSDBuffer()
{
// hal_info("%s\n", __func__);
// lt_info("%s\n", __func__);
int x = glfb_priv->mState.width;
int y = glfb_priv->mState.height;
ClutterContent *fb = clutter_image_new();
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf->data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
hal_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(fb_actor, fb);
@@ -441,14 +458,14 @@ void GLFbPC::bltOSDBuffer()
void GLFbPC::bltDisplayBuffer()
{
// hal_info("GLFB::%s vdec: %p\n", __func__, vdec);
if (!videoDecoder) /* cannot start yet */
// lt_info("GLFB::%s vdec: %p\n", __func__, vdec);
if (!vdec) /* cannot start yet */
return;
static bool warn = true;
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
VDec::SWFramebuffer *buf = vdec->getDecBuf();
if (!buf) {
if (warn)
hal_info("GLFB::%s did not get a buffer...\n", __func__);
lt_info("GLFB::%s did not get a buffer...\n", __func__);
warn = false;
return;
}
@@ -470,7 +487,7 @@ void GLFbPC::bltDisplayBuffer()
ClutterContent *fb = clutter_image_new();
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), &(*buf)[0], COGL_PIXEL_FORMAT_BGR_888, w, h, w*3, NULL)) {
hal_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(vid_actor, fb);
@@ -482,8 +499,8 @@ void GLFbPC::bltDisplayBuffer()
* better this than nothing... :-) */
int64_t apts = 0;
int64_t vpts = buf->pts();
if (audioDecoder)
apts = audioDecoder->getPts();
if (adec)
apts = adec->getPts();
if (apts != last_apts) {
int rate, dummy1, dummy2;
if (apts < vpts)
@@ -491,7 +508,7 @@ void GLFbPC::bltDisplayBuffer()
else if (sleep_us > 1000)
sleep_us -= 1000;
last_apts = apts;
videoDecoder->getPictureInfo(dummy1, dummy2, rate);
vdec->getPictureInfo(dummy1, dummy2, rate);
if (rate > 0)
rate = 2000000 / rate; /* limit to half the frame rate */
else
@@ -501,6 +518,6 @@ void GLFbPC::bltDisplayBuffer()
else if (sleep_us < 1)
sleep_us = 1;
}
hal_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num);
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
}

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -33,18 +34,18 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include "dmx_hal.h"
#include "hal_debug.h"
#include "lt_debug.h"
#include "video_lib.h"
/* needed for getSTC... */
extern cVideo *videoDecoder;
/* needed for getSTC :-( */
#include "video_priv.h"
extern VDec *vdec;
#define hal_debug(args...) _hal_debug(HAL_DEBUG_DEMUX, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_DEMUX, this, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_DEMUX, NULL, args)
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
#define dmx_err(_errfmt, _errstr, _revents) do { \
hal_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
} while(0);
@@ -80,7 +81,7 @@ cDemux::cDemux(int n)
{
if (n < 0 || n > 2)
{
hal_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
lt_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
num = 0;
}
else
@@ -90,7 +91,7 @@ cDemux::cDemux(int n)
cDemux::~cDemux()
{
hal_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
Close();
}
@@ -99,7 +100,7 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe
int devnum = num;
int flags = O_RDWR|O_CLOEXEC;
if (fd > -1)
hal_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
dmx_type = pes_type;
if (pes_type != DMX_PSI_CHANNEL)
@@ -108,10 +109,10 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe
fd = open(devname[devnum], flags);
if (fd < 0)
{
hal_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
return false;
}
hal_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
lt_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
num, DMX_T[pes_type], pes_type, uBufferSize, fd);
if (dmx_type == DMX_VIDEO_CHANNEL)
@@ -121,18 +122,18 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe
#if 0
if (!pesfds.empty())
{
hal_info("%s ERROR! pesfds not empty!\n", __FUNCTION__); /* TODO: error handling */
lt_info("%s ERROR! pesfds not empty!\n", __FUNCTION__); /* TODO: error handling */
return false;
}
int n = DMX_SOURCE_FRONT0;
if (ioctl(fd, DMX_SET_SOURCE, &n) < 0)
hal_info("%s DMX_SET_SOURCE %d failed! (%m)\n", __func__, n);
lt_info("%s DMX_SET_SOURCE %d failed! (%m)\n", __func__, n);
#endif
if (uBufferSize > 0)
{
/* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */
if (ioctl(fd, DMX_SET_BUFFER_SIZE, uBufferSize) < 0)
hal_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
lt_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
}
buffersize = uBufferSize;
@@ -141,10 +142,10 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe
void cDemux::Close(void)
{
hal_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
lt_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return;
}
pesfds.clear();
@@ -156,7 +157,7 @@ void cDemux::Close(void)
dmx_tp_count--;
if (dmx_tp_count < 0)
{
hal_info("%s dmx_tp_count < 0!!\n", __func__);
lt_info("%s dmx_tp_count < 0!!\n", __func__);
dmx_tp_count = 0;
}
}
@@ -164,10 +165,10 @@ void cDemux::Close(void)
bool cDemux::Start(bool)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_START);
@@ -176,10 +177,10 @@ bool cDemux::Start(bool)
bool cDemux::Stop(void)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_STOP);
@@ -208,7 +209,7 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
else if (rc < 0)
{
dmx_err("poll: %s,", strerror(errno), 0)
//hal_info("%s poll: %m\n", __FUNCTION__);
//lt_info("%s poll: %m\n", __FUNCTION__);
/* happens, when running under gdb... */
if (errno == EINTR)
goto retry;
@@ -252,7 +253,7 @@ bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filt
if (len > DMX_FILTER_SIZE)
{
hal_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
lt_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
len = DMX_FILTER_SIZE;
}
s_flt.pid = pid;
@@ -344,7 +345,7 @@ bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filt
if (timeout == 0 && negmask == NULL)
s_flt.timeout = to;
hal_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
lt_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
pid, fd, DMX_T[dmx_type], len, s_flt.timeout,s_flt.flags, s_flt.filter.filter[0]);
#if 0
fprintf(stderr,"filt: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.filter[i]);fprintf(stderr,"\n");
@@ -372,7 +373,7 @@ bool cDemux::pesFilter(const unsigned short _pid)
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
return false;
hal_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
memset(&p_flt, 0, sizeof(p_flt));
p_flt.pid = pid;
@@ -406,7 +407,7 @@ bool cDemux::pesFilter(const unsigned short _pid)
p_flt.output = DMX_OUT_TSDEMUX_TAP;
break;
default:
hal_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
lt_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
return false;
}
return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0);
@@ -414,39 +415,39 @@ bool cDemux::pesFilter(const unsigned short _pid)
void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/)
{
hal_debug("%s #%d\n", __FUNCTION__, num);
lt_debug("%s #%d\n", __FUNCTION__, num);
}
void *cDemux::getBuffer()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
lt_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
void *cDemux::getChannel()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
lt_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
bool cDemux::addPid(unsigned short Pid)
{
hal_debug("%s: pid 0x%04hx\n", __func__, Pid);
lt_debug("%s: pid 0x%04hx\n", __func__, Pid);
pes_pids pfd;
int ret;
if (dmx_type != DMX_TP_CHANNEL)
{
hal_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return false;
}
if (fd == -1)
hal_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
pfd.fd = fd; /* dummy */
pfd.pid = Pid;
pesfds.push_back(pfd);
ret = (ioctl(fd, DMX_ADD_PID, &Pid));
if (ret < 0)
hal_info("%s: DMX_ADD_PID (%m)\n", __func__);
lt_info("%s: DMX_ADD_PID (%m)\n", __func__);
return (ret != -1);
}
@@ -454,33 +455,33 @@ void cDemux::removePid(unsigned short Pid)
{
if (dmx_type != DMX_TP_CHANNEL)
{
hal_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return;
}
for (std::vector<pes_pids>::iterator i = pesfds.begin(); i != pesfds.end(); ++i)
{
if ((*i).pid == Pid) {
hal_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
lt_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
hal_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
lt_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
pesfds.erase(i);
return; /* TODO: what if the same PID is there multiple times */
}
}
hal_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
lt_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
}
void cDemux::getSTC(int64_t * STC)
{
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->GetPTS();
if (vdec)
pts = vdec->GetPTS();
*STC = pts;
}
int cDemux::getUnit(void)
{
hal_debug("%s #%d\n", __FUNCTION__, num);
lt_debug("%s #%d\n", __FUNCTION__, num);
/* just guessed that this is the right thing to do.
right now this is only used by the CA code which is stubbed out
anyway */
@@ -489,12 +490,12 @@ int cDemux::getUnit(void)
bool cDemux::SetSource(int unit, int source)
{
hal_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
return true;
}
int cDemux::GetSource(int unit)
{
hal_info_c("%s(%d): not implemented yet\n", __func__, unit);
lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
return 0;
}

View File

@@ -39,19 +39,19 @@
#include <unistd.h>
#include <linux/input.h>
#include "glfb_priv.h"
#include "video_lib.h"
#include "audio_lib.h"
#include "video_priv.h"
#include "audio_priv.h"
#include "hal_debug.h"
#include "lt_debug.h"
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, this, args)
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_INIT, NULL, args)
#define lt_info_c(args...) _lt_info(HAL_DEBUG_INIT, NULL, args)
#define lt_debug(args...) _lt_debug(HAL_DEBUG_INIT, this, args)
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
extern cVideo *videoDecoder;
extern cAudio *audioDecoder;
extern VDec *vdec;
extern ADec *adec;
/* the private class that does stuff only needed inside libstb-hal.
* is used e.g. by cVideo... */
@@ -121,7 +121,7 @@ GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mS
mkfifo("/tmp/neutrino.input", 0600);
input_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
if (input_fd < 0)
hal_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
initKeys();
}
@@ -208,7 +208,7 @@ void GLFramebuffer::run()
int y = glfb_priv->mState.height;
/* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 };
hal_info("GLFB: GL thread starting x %d y %d\n", x, y);
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
glutInit(&argc, const_cast<char **>(argv));
glutInitWindowSize(x, y);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
@@ -216,7 +216,7 @@ void GLFramebuffer::run()
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = x * y * 4 * 2;
osd_buf.resize(fbmem);
hal_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
glfb_priv->mInitDone = true; /* signal that setup is finished */
/* init the good stuff */
@@ -225,9 +225,9 @@ void GLFramebuffer::run()
{
if((!GLEW_VERSION_1_5)||(!GLEW_EXT_pixel_buffer_object)||(!GLEW_ARB_texture_non_power_of_two))
{
hal_info("GLFB: Sorry, your graphics card is not supported. "
lt_info("GLFB: Sorry, your graphics card is not supported. "
"Needs at least OpenGL 1.5, pixel buffer objects and NPOT textures.\n");
hal_info("incompatible graphics card: %m");
lt_info("incompatible graphics card: %m");
_exit(1); /* Life is hard */
}
else
@@ -244,8 +244,8 @@ void GLFramebuffer::run()
}
}
else
hal_info("GLFB: error initializing glew: %d\n", err);
hal_info("GLFB: GL thread stopping\n");
lt_info("GLFB: error initializing glew: %d\n", err);
lt_info("GLFB: GL thread stopping\n");
}
#if 0
@@ -254,7 +254,7 @@ void GLFbPC::setupCtx()
int argc = 1;
/* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 };
hal_info("GLFB: GL thread starting x %d y %d\n", mX[0], mY[0]);
lt_info("GLFB: GL thread starting x %d y %d\n", mX[0], mY[0]);
glutInit(&argc, const_cast<char **>(argv));
glutInitWindowSize(mX[0], mY[0]);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
@@ -271,7 +271,7 @@ void GLFbPC::setupOSDBuffer()
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = mState.width * mState.height * 4 * 2;
osd_buf->resize(fbmem);
hal_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
}
}
#endif
@@ -321,11 +321,11 @@ void GLFbPC::releaseGLObjects()
/* static */ void GLFbPC::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
{
hal_debug_c("GLFB::%s: 0x%x\n", __func__, key);
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev;
if (key == 'f')
{
hal_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
glfb_priv->mReInit = true;
return;
@@ -337,7 +337,7 @@ void GLFbPC::releaseGLObjects()
ev.value = 1; /* key own */
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
hal_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0; /* neutrino is stupid, so push key up directly after key down */
write(glfb_priv->input_fd, &ev, sizeof(ev));
@@ -345,7 +345,7 @@ void GLFbPC::releaseGLObjects()
/* static */ void GLFbPC::specialcb(int key, int /*x*/, int /*y*/)
{
hal_debug_c("GLFB::%s: 0x%x\n", __func__, key);
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev;
std::map<int, int>::const_iterator i = glfb_priv->mSpecialMap.find(key);
if (i == glfb_priv->mSpecialMap.end())
@@ -354,7 +354,7 @@ void GLFbPC::releaseGLObjects()
ev.value = 1;
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
hal_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0;
write(glfb_priv->input_fd, &ev, sizeof(ev));
@@ -391,7 +391,7 @@ void GLFbPC::render()
glutFullScreen();
} else
*mX = *mY * mOA.num / mOA.den;
hal_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
lt_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
__func__, *mX, *mY, xoff, yoff, mFullscreen);
glViewport(xoff, yoff, *mX, *mY);
glMatrixMode(GL_PROJECTION);
@@ -417,7 +417,7 @@ void GLFbPC::render()
if (mState.blit) {
/* only blit manually after fb->blit(), this helps to find missed blit() calls */
mState.blit = false;
hal_debug("GLFB::%s blit!\n", __func__);
lt_debug("GLFB::%s blit!\n", __func__);
bltOSDBuffer(); /* OSD */
}
@@ -435,10 +435,10 @@ void GLFbPC::render()
default:
case INT_MIN: /* invalid */
case 0: /* identical */
hal_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
lt_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
break;
case 1: /* mVA > mOA -- video is wider than display */
hal_debug("%s: mVA > mOA\n", __func__);
lt_debug("%s: mVA > mOA\n", __func__);
xscale = av_q2d(mVA) / av_q2d(mOA);
switch (mCrop) {
case DISPLAY_AR_MODE_PANSCAN:
@@ -454,7 +454,7 @@ void GLFbPC::render()
}
break;
case -1: /* mVA < mOA -- video is taller than display */
hal_debug("%s: mVA < mOA\n", __func__);
lt_debug("%s: mVA < mOA\n", __func__);
xscale = av_q2d(mVA) / av_q2d(mOA);
switch (mCrop) {
case DISPLAY_AR_MODE_LETTERBOX:
@@ -484,7 +484,7 @@ void GLFbPC::render()
GLuint err = glGetError();
if (err != 0)
hal_info("GLFB::%s: GLError:%d 0x%04x\n", __func__, err, err);
lt_info("GLFB::%s: GLError:%d 0x%04x\n", __func__, err, err);
if (sleep_us > 0)
usleep(sleep_us);
glutPostRedisplay();
@@ -533,17 +533,17 @@ void GLFbPC::drawSquare(float size, float x_factor)
1.0, 1.0,
};
if (x_factor > -99.0) { /* x_factor == -100 => OSD */
if (videoDecoder &&
videoDecoder->pig_x > 0 && videoDecoder->pig_y > 0 &&
videoDecoder->pig_w > 0 && videoDecoder->pig_h > 0) {
if (vdec &&
vdec->pig_x > 0 && vdec->pig_y > 0 &&
vdec->pig_w > 0 && vdec->pig_h > 0) {
/* these calculations even consider cropping and panscan mode
* maybe this could be done with some clever opengl tricks? */
double w2 = (double)mState.width * 0.5l;
double h2 = (double)mState.height * 0.5l;
double x = (double)(videoDecoder->pig_x - w2) / w2 / x_factor / size;
double y = (double)(h2 - videoDecoder->pig_y) / h2 / size;
double w = (double)videoDecoder->pig_w / w2;
double h = (double)videoDecoder->pig_h / h2;
double x = (double)(vdec->pig_x - w2) / w2 / x_factor / size;
double y = (double)(h2 - vdec->pig_y) / h2 / size;
double w = (double)vdec->pig_w / w2;
double h = (double)vdec->pig_h / h2;
x += ((1.0l - x_factor * size) / 2.0l) * w / x_factor / size;
y += ((size - 1.0l) / 2.0l) * h / size;
vertices[0] = x + w; /* top right x */
@@ -585,13 +585,13 @@ void GLFbPC::bltOSDBuffer()
void GLFbPC::bltDisplayBuffer()
{
if (!videoDecoder) /* cannot start yet */
if (!vdec) /* cannot start yet */
return;
static bool warn = true;
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
VDec::SWFramebuffer *buf = vdec->getDecBuf();
if (!buf) {
if (warn)
hal_info("GLFB::%s did not get a buffer...\n", __func__);
lt_info("GLFB::%s did not get a buffer...\n", __func__);
warn = false;
return;
}
@@ -620,10 +620,9 @@ void GLFbPC::bltDisplayBuffer()
* this implementation is pretty naive and not working too well, but
* better this than nothing... :-) */
int64_t apts = 0;
/* 18000 is the magic value for A/V sync in my libao->pulseaudio->intel_hda setup */
int64_t vpts = buf->pts() + 18000;
if (audioDecoder)
apts = audioDecoder->getPts();
int64_t vpts = buf->pts();
if (adec)
apts = adec->getPts();
if (apts != last_apts) {
int rate, dummy1, dummy2;
if (apts < vpts)
@@ -631,7 +630,7 @@ void GLFbPC::bltDisplayBuffer()
else if (sleep_us > 1000)
sleep_us -= 1000;
last_apts = apts;
videoDecoder->getPictureInfo(dummy1, dummy2, rate);
vdec->getPictureInfo(dummy1, dummy2, rate);
if (rate > 0)
rate = 2000000 / rate; /* limit to half the frame rate */
else
@@ -641,6 +640,6 @@ void GLFbPC::bltDisplayBuffer()
else if (sleep_us < 1)
sleep_us = 1;
}
hal_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num);
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
}

View File

@@ -7,12 +7,8 @@
* License: GPL v2 or later
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <hardware_caps.h>
#include <sys/utsname.h>
@@ -28,20 +24,18 @@ hw_caps_t *get_hwcaps(void)
memset(&caps, 0, sizeof(hw_caps_t));
initialized = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1; /* for testing */
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.has_HDMI = 1;
caps.display_xres = 8;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 0;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_vformat = 0;
strcpy(caps.boxvendor, "Generic");
strcpy(caps.boxname, "PC");
if (! uname(&u)){
if (! uname(&u))
strncpy(caps.boxarch, u.machine, sizeof(caps.boxarch));
caps.boxarch[sizeof(caps.boxarch)-1] = '\0';
}
else
fprintf(stderr, "%s: uname() failed: %m\n", __func__);

View File

@@ -2,22 +2,21 @@
#include <cstdlib>
#include <unistd.h>
#include "init.h"
#include "init_td.h"
#include "lt_debug.h"
#include "glfb.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
static bool initialized = false;
GLFramebuffer *glfb = NULL;
bool HAL_nodec = false;
void hal_api_init()
void init_td_api()
{
if (!initialized)
hal_debug_init();
hal_info("%s begin, initialized=%d, debug=0x%02x\n", __func__, (int)initialized, debuglevel);
lt_debug_init();
lt_info("%s begin, initialized=%d, debug=0x%02x\n", __func__, (int)initialized, debuglevel);
if (! glfb) {
int x = 1280, y = 720; /* default OSD FB resolution */
/*
@@ -32,9 +31,9 @@ void hal_api_init()
x = atoi(tmp);
y = atoi(p + 1);
}
hal_info("%s: setting GL Framebuffer size to %dx%d\n", __func__, x, y);
lt_info("%s: setting GL Framebuffer size to %dx%d\n", __func__, x, y);
if (!p)
hal_info("%s: export GLFB_RESOLUTION=\"<w>,<h>\" to set another resolution\n", __func__);
lt_info("%s: export GLFB_RESOLUTION=\"<w>,<h>\" to set another resolution\n", __func__);
glfb = new GLFramebuffer(x, y); /* hard coded to PAL resolution for now */
}
@@ -47,9 +46,9 @@ void hal_api_init()
initialized = true;
}
void hal_api_exit()
void shutdown_td_api()
{
hal_info("%s, initialized = %d\n", __func__, (int)initialized);
lt_info("%s, initialized = %d\n", __func__, (int)initialized);
if (glfb)
delete glfb;
glfb = NULL;

View File

@@ -1,6 +1,6 @@
#include <stdio.h>
#include "playback_lib.h"
#include "playback_hal.h"
static const char * FILENAME = "playback-dummy";
@@ -13,33 +13,33 @@ void cPlayback::Close(void)
{
}
bool cPlayback::Start(std::string filename, std::string headers)
bool cPlayback::Start(std::string /*filename*/, std::string /*headers*/)
{
return Start((char*) filename.c_str(),0,0,0,0,0, headers);
return false;
}
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string /*headers*/)
bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, int ac3, unsigned int duration)
{
printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d duration=%i\n",
FILENAME, __func__, filename, vpid, vtype, apid, ac3, duration);
return true;
}
bool cPlayback::SetAPid(int pid, bool /*ac3*/)
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
{
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
return true;
}
bool cPlayback::SelectSubtitles(int pid, std::string charset)
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
{
printf("%s:%s pid %i, charset: %s\n", FILENAME, __func__, pid, charset.c_str());
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
return true;
}
bool cPlayback::SetSpeed(int speed)
{
printf("%s:%s playing %d speed %d\n", FILENAME, __func__, playing, speed);
printf("%s:%s speed %d\n", FILENAME, __func__, speed);
return true;
}
@@ -62,53 +62,16 @@ bool cPlayback::SetPosition(int position, bool)
return true;
}
void cPlayback::FindAllPids(int *, unsigned int *, unsigned int *numpida, std::string *)
void cPlayback::FindAllPids(uint16_t *, unsigned short *, uint16_t *numpida, std::string *)
{
printf("%s:%s\n", FILENAME, __func__);
*numpida = 0;
}
void cPlayback::FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/)
{
*numpids = 0;
}
bool cPlayback::SetSubtitlePid(int /*pid*/)
{
return true;
}
void cPlayback::GetPts(uint64_t &/*pts*/)
{
}
bool cPlayback::SetTeletextPid(int /*pid*/)
{
return true;
}
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
{
*numpids = 0;
}
void cPlayback::SuspendSubtitle(bool /*b*/)
{
}
void cPlayback::RequestAbort()
{
}
int cPlayback::GetTeletextPid(void)
{
return -1;
}
void cPlayback::FindAllSubs(int * /*pids*/, unsigned int * /*supp*/, unsigned int *num, std::string * /*lang*/)
void cPlayback::FindAllSubs(uint16_t *, unsigned short *, uint16_t *numpida, std::string *)
{
printf("%s:%s\n", FILENAME, __func__);
*num = 0;
*numpida = 0;
}
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
@@ -117,12 +80,6 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
titles.clear();
}
void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
{
keys.clear();
values.clear();
}
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current)
{
playlists.clear();
@@ -134,6 +91,10 @@ void cPlayback::SetTitle(int /*title*/)
{
}
void cPlayback::RequestAbort(void)
{
}
uint64_t cPlayback::GetReadCount(void)
{
return 0;

View File

@@ -47,14 +47,16 @@ extern "C" {
#define VDEC_PIXFMT AV_PIX_FMT_BGR24
#endif
#include "video_lib.h"
#include "video_hal.h"
#include "dmx_hal.h"
#include "glfb_priv.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_VIDEO, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_VIDEO, this, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_VIDEO, NULL, args)
#include "video_priv.h"
#include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
VDec *vdec = NULL;
cVideo *videoDecoder = NULL;
extern cDemux *videoDemux;
extern GLFbPC *glfb_priv;
@@ -76,10 +78,15 @@ static const AVRational aspect_ratios[6] = {
cVideo::cVideo(int, void *, void *, unsigned int)
{
hal_debug("%s\n", __func__);
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
lt_debug("%s\n", __func__);
vdec = new VDec();
/* quick hack to export private stuff to other libstb-hal modules */
::vdec = vdec;
}
VDec::VDec()
{
av_register_all();
#endif
if (!HAL_nodec)
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
bufpos = 0;
@@ -98,16 +105,29 @@ cVideo::cVideo(int, void *, void *, unsigned int)
stillpicture = false;
}
VDec::~VDec(void)
{
free(dmxbuf);
}
cVideo::~cVideo(void)
{
Stop();
/* ouch :-( */
videoDecoder = NULL;
// videoDecoder = NULL;
delete vdec;
::vdec = NULL;
}
int cVideo::setAspectRatio(int vformat, int cropping)
{
hal_info("%s(%d, %d)\n", __func__, vformat, cropping);
return vdec->setAspectRatio(vformat, cropping);
}
int VDec::setAspectRatio(int vformat, int cropping)
{
lt_info("%s(%d, %d)\n", __func__, vformat, cropping);
if (vformat >= 0)
display_aspect = (DISPLAY_AR) vformat;
if (cropping >= 0)
@@ -118,6 +138,11 @@ int cVideo::setAspectRatio(int vformat, int cropping)
}
int cVideo::getAspectRatio(void)
{
return vdec->getAspectRatio();
}
int VDec::getAspectRatio(void)
{
buf_m.lock();
int ret = 0;
@@ -146,28 +171,38 @@ int cVideo::getAspectRatio(void)
return ret;
}
int cVideo::setCroppingMode(int)
int cVideo::setCroppingMode(void)
{
return 0;
}
int cVideo::Start(void *, unsigned short, unsigned short, void *)
{
hal_debug("%s running %d >\n", __func__, thread_running);
return vdec->Start();
}
int cVideo::Stop(bool b)
{
return vdec->Stop(b);
}
int VDec::Start()
{
lt_debug("%s running %d >\n", __func__, thread_running);
if (!thread_running && !HAL_nodec)
OpenThreads::Thread::start();
hal_debug("%s running %d <\n", __func__, thread_running);
lt_debug("%s running %d <\n", __func__, thread_running);
return 0;
}
int cVideo::Stop(bool)
int VDec::Stop(bool)
{
hal_debug("%s running %d >\n", __func__, thread_running);
lt_debug("%s running %d >\n", __func__, thread_running);
if (thread_running) {
thread_running = false;
OpenThreads::Thread::join();
}
hal_debug("%s running %d <\n", __func__, thread_running);
lt_debug("%s running %d <\n", __func__, thread_running);
return 0;
}
@@ -177,6 +212,11 @@ int cVideo::setBlank(int)
}
int cVideo::GetVideoSystem()
{
return vdec->GetVideoSystem();
}
int VDec::GetVideoSystem()
{
int current_video_system = VIDEO_STD_1080I50;
@@ -189,6 +229,11 @@ int cVideo::GetVideoSystem()
}
int cVideo::SetVideoSystem(int system, bool)
{
return vdec->SetVideoSystem(system);
}
int VDec::SetVideoSystem(int system)
{
int h;
switch(system)
@@ -210,7 +255,7 @@ int cVideo::SetVideoSystem(int system, bool)
h = 720;
break;
case VIDEO_STD_AUTO:
hal_info("%s: VIDEO_STD_AUTO not implemented\n", __func__);
lt_info("%s: VIDEO_STD_AUTO not implemented\n", __func__);
// fallthrough
case VIDEO_STD_SECAM:
case VIDEO_STD_PAL:
@@ -218,7 +263,7 @@ int cVideo::SetVideoSystem(int system, bool)
h = 576;
break;
default:
hal_info("%s: unhandled value %d\n", __func__, system);
lt_info("%s: unhandled value %d\n", __func__, system);
return 0;
}
// v_std = (VIDEO_STD) system;
@@ -230,7 +275,7 @@ int cVideo::SetVideoSystem(int system, bool)
int cVideo::getPlayState(void)
{
return VIDEO_PLAYING;
return 1;
}
void cVideo::SetVideoMode(analog_mode_t)
@@ -238,9 +283,14 @@ void cVideo::SetVideoMode(analog_mode_t)
}
bool cVideo::ShowPicture(const char *fname)
{
return vdec->ShowPicture(fname);
}
bool VDec::ShowPicture(const char *fname)
{
bool ret = false;
hal_info("%s(%s)\n", __func__, fname);
lt_info("%s(%s)\n", __func__, fname);
if (access(fname, R_OK))
return ret;
still_m.lock();
@@ -250,10 +300,10 @@ bool cVideo::ShowPicture(const char *fname)
buf_out = 0;
still_m.unlock();
unsigned int i = 0;
unsigned int i;
int stream_id = -1;
int got_frame = 0;
int av_ret = 0;
int len;
AVFormatContext *avfc = NULL;
AVCodecContext *c = NULL;
AVCodecParameters *p = NULL;
@@ -262,12 +312,12 @@ bool cVideo::ShowPicture(const char *fname)
AVPacket avpkt;
if (avformat_open_input(&avfc, fname, NULL, NULL) < 0) {
hal_info("%s: Could not open file %s\n", __func__, fname);
lt_info("%s: Could not open file %s\n", __func__, fname);
return ret;
}
if (avformat_find_stream_info(avfc, NULL) < 0) {
hal_info("%s: Could not find file info %s\n", __func__, fname);
lt_info("%s: Could not find file info %s\n", __func__, fname);
goto out_close;
}
for (i = 0; i < avfc->nb_streams; i++) {
@@ -282,50 +332,35 @@ bool cVideo::ShowPicture(const char *fname)
codec = avcodec_find_decoder(p->codec_id);
c = avcodec_alloc_context3(codec);
if (avcodec_open2(c, codec, NULL) < 0) {
hal_info("%s: Could not find/open the codec, id 0x%x\n", __func__, p->codec_id);
lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, p->codec_id);
goto out_close;
}
frame = av_frame_alloc();
rgbframe = av_frame_alloc();
if (!frame || !rgbframe) {
hal_info("%s: Could not allocate video frame\n", __func__);
lt_info("%s: Could not allocate video frame\n", __func__);
goto out_free;
}
av_init_packet(&avpkt);
if (av_read_frame(avfc, &avpkt) < 0) {
hal_info("%s: av_read_frame < 0\n", __func__);
lt_info("%s: av_read_frame < 0\n", __func__);
goto out_free;
}
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100)
av_ret = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (av_ret < 0) {
hal_info("%s: avcodec_decode_video2 %d\n", __func__, av_ret);
len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (len < 0) {
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
av_packet_unref(&avpkt);
goto out_free;
}
if (avpkt.size > av_ret)
hal_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, av_ret);
#else
av_ret = avcodec_send_packet(c, &avpkt);
if (av_ret != 0 && av_ret != AVERROR(EAGAIN)) {
hal_info("%s: avcodec_send_packet %d\n", __func__, av_ret);
av_packet_unref(&avpkt);
goto out_free;
}
av_ret = avcodec_receive_frame(c, frame);
if (av_ret != 0 && av_ret != AVERROR(EAGAIN))
goto out_free;
got_frame = 1;
#endif
if (avpkt.size > len)
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
if (got_frame) {
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
struct SwsContext *convert = sws_getContext(c->width, c->height, c->pix_fmt,
c->width, c->height, VDEC_PIXFMT,
SWS_BICUBIC, 0, 0, 0);
if (!convert)
hal_info("%s: ERROR setting up SWS context\n", __func__);
lt_info("%s: ERROR setting up SWS context\n", __func__);
else {
buf_m.lock();
SWFramebuffer *f = &buffers[buf_in];
@@ -345,7 +380,7 @@ bool cVideo::ShowPicture(const char *fname)
buf_in %= VDEC_MAXBUFS;
buf_num++;
if (buf_num > (VDEC_MAXBUFS - 1)) {
hal_debug("%s: buf_num overflow\n", __func__);
lt_info("%s: buf_num overflow\n", __func__);
buf_out++;
buf_out %= VDEC_MAXBUFS;
buf_num--;
@@ -362,16 +397,16 @@ bool cVideo::ShowPicture(const char *fname)
av_frame_free(&rgbframe);
out_close:
avformat_close_input(&avfc);
hal_debug("%s(%s) end\n", __func__, fname);
lt_debug("%s(%s) end\n", __func__, fname);
return ret;
}
void cVideo::StopPicture()
{
hal_info("%s\n", __func__);
still_m.lock();
stillpicture = false;
still_m.unlock();
lt_info("%s\n", __func__);
vdec->still_m.lock();
vdec->stillpicture = false;
vdec->still_m.unlock();
}
void cVideo::Standby(unsigned int)
@@ -383,7 +418,12 @@ int cVideo::getBlank(void)
return 0;
}
void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/, int /*startx*/, int /*starty*/, int /*endx*/, int /*endy*/)
void cVideo::Pig(int x, int y, int w, int h, int, int)
{
vdec->Pig(x, y, w, h);
}
void VDec::Pig(int x, int y, int w, int h)
{
pig_x = x;
pig_y = y;
@@ -393,6 +433,11 @@ void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/, int /
}
void cVideo::getPictureInfo(int &width, int &height, int &rate)
{
vdec->getPictureInfo(width, height, rate);
}
void VDec::getPictureInfo(int &width, int &height, int &rate)
{
width = dec_w;
height = dec_h;
@@ -429,12 +474,17 @@ void cVideo::SetSyncMode(AVSYNC_TYPE)
};
int cVideo::SetStreamType(VIDEO_FORMAT v)
{
return vdec->SetStreamType(v);
}
int VDec::SetStreamType(VIDEO_FORMAT v)
{
v_format = v;
return 0;
}
cVideo::SWFramebuffer *cVideo::getDecBuf(void)
VDec::SWFramebuffer *VDec::getDecBuf(void)
{
buf_m.lock();
if (buf_num == 0) {
@@ -473,9 +523,9 @@ static int my_read(void *, uint8_t *buf, int buf_size)
return tmp;
}
void cVideo::run(void)
void VDec::run(void)
{
hal_info("====================== start decoder thread ================================\n");
lt_info("====================== start decoder thread ================================\n");
AVCodec *codec;
AVCodecParameters *p = NULL;
AVCodecContext *c= NULL;
@@ -488,7 +538,6 @@ void cVideo::run(void)
time_t warn_r = 0; /* last read error */
time_t warn_d = 0; /* last decode error */
int av_ret = 0;
bufpos = 0;
buf_num = 0;
@@ -511,14 +560,14 @@ void cVideo::run(void)
thread_running = true;
if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) {
hal_info("%s: Could not open input\n", __func__);
lt_info("%s: Could not open input\n", __func__);
goto out;
}
while (avfc->nb_streams < 1)
{
hal_info("%s: nb_streams %d, should be 1 => retry\n", __func__, avfc->nb_streams);
lt_info("%s: nb_streams %d, should be 1 => retry\n", __func__, avfc->nb_streams);
if (av_read_frame(avfc, &avpkt) < 0)
hal_info("%s: av_read_frame < 0\n", __func__);
lt_info("%s: av_read_frame < 0\n", __func__);
av_packet_unref(&avpkt);
if (! thread_running)
goto out;
@@ -526,61 +575,46 @@ void cVideo::run(void)
p = avfc->streams[0]->codecpar;
if (p->codec_type != AVMEDIA_TYPE_VIDEO)
hal_info("%s: no video codec? 0x%x\n", __func__, p->codec_type);
lt_info("%s: no video codec? 0x%x\n", __func__, p->codec_type);
codec = avcodec_find_decoder(p->codec_id);
if (!codec) {
hal_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
goto out;
}
c = avcodec_alloc_context3(codec);
if (avcodec_open2(c, codec, NULL) < 0) {
hal_info("%s: Could not open codec\n", __func__);
lt_info("%s: Could not open codec\n", __func__);
goto out;
}
frame = av_frame_alloc();
rgbframe = av_frame_alloc();
if (!frame || !rgbframe) {
hal_info("%s: Could not allocate video frame\n", __func__);
lt_info("%s: Could not allocate video frame\n", __func__);
goto out2;
}
hal_info("decoding %s\n", avcodec_get_name(c->codec_id));
lt_info("decoding %s\n", avcodec_get_name(c->codec_id));
while (thread_running) {
if (av_read_frame(avfc, &avpkt) < 0) {
if (warn_r - time(NULL) > 4) {
hal_info("%s: av_read_frame < 0\n", __func__);
lt_info("%s: av_read_frame < 0\n", __func__);
warn_r = time(NULL);
}
usleep(10000);
continue;
}
int got_frame = 0;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100)
av_ret = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (av_ret < 0) {
int len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (len < 0) {
if (warn_d - time(NULL) > 4) {
hal_info("%s: avcodec_decode_video2 %d\n", __func__, av_ret);
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
warn_d = time(NULL);
}
av_packet_unref(&avpkt);
continue;
}
if (avpkt.size > av_ret)
hal_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, av_ret);
#else
av_ret = avcodec_send_packet(c, &avpkt);
if (av_ret != 0 && av_ret != AVERROR(EAGAIN)) {
if (warn_d - time(NULL) > 4) {
hal_info("%s: avcodec_send_packet %d\n", __func__, av_ret);
warn_d = time(NULL);
}
av_packet_unref(&avpkt);
continue;
}
av_ret = avcodec_receive_frame(c, frame);
if (!av_ret)
got_frame = 1;
#endif
if (avpkt.size > len)
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
still_m.lock();
if (got_frame && ! stillpicture) {
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
@@ -589,7 +623,7 @@ void cVideo::run(void)
c->width, c->height, VDEC_PIXFMT,
SWS_BICUBIC, 0, 0, 0);
if (!convert)
hal_info("%s: ERROR setting up SWS context\n", __func__);
lt_info("%s: ERROR setting up SWS context\n", __func__);
else {
buf_m.lock();
SWFramebuffer *f = &buffers[buf_in];
@@ -600,7 +634,7 @@ void cVideo::run(void)
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
rgbframe->data, rgbframe->linesize);
if (dec_w != c->width || dec_h != c->height) {
hal_info("%s: pic changed %dx%d -> %dx%d\n", __func__,
lt_info("%s: pic changed %dx%d -> %dx%d\n", __func__,
dec_w, dec_h, c->width, c->height);
dec_w = c->width;
dec_h = c->height;
@@ -608,11 +642,7 @@ void cVideo::run(void)
}
f->width(c->width);
f->height(c->height);
#if (LIBAVUTIL_VERSION_MAJOR < 54)
int64_t vpts = av_frame_get_best_effort_timestamp(frame);
#else
int64_t vpts = frame->best_effort_timestamp;
#endif
/* a/v delay determined experimentally :-) */
#if USE_OPENGL
if (v_format == VIDEO_FORMAT_MPEG2)
@@ -632,7 +662,7 @@ void cVideo::run(void)
buf_in %= VDEC_MAXBUFS;
buf_num++;
if (buf_num > (VDEC_MAXBUFS - 1)) {
hal_debug("%s: buf_num overflow\n", __func__);
lt_info("%s: buf_num overflow\n", __func__);
buf_out++;
buf_out %= VDEC_MAXBUFS;
buf_num--;
@@ -640,15 +670,11 @@ void cVideo::run(void)
dec_r = c->time_base.den/(c->time_base.num * c->ticks_per_frame);
buf_m.unlock();
}
hal_debug("%s: time_base: %d/%d, ticks: %d rate: %d pts 0x%" PRIx64 "\n", __func__,
lt_debug("%s: time_base: %d/%d, ticks: %d rate: %d pts 0x%" PRIx64 "\n", __func__,
c->time_base.num, c->time_base.den, c->ticks_per_frame, dec_r,
#if (LIBAVUTIL_VERSION_MAJOR < 54)
av_frame_get_best_effort_timestamp(frame));
#else
frame->best_effort_timestamp);
#endif
} else
hal_debug("%s: got_frame: %d stillpicture: %d\n", __func__, got_frame, stillpicture);
lt_info("%s: got_frame: %d stillpicture: %d\n", __func__, got_frame, stillpicture);
still_m.unlock();
av_packet_unref(&avpkt);
}
@@ -671,7 +697,7 @@ void cVideo::run(void)
buf_out = 0;
}
still_m.unlock();
hal_info("======================== end decoder thread ================================\n");
lt_info("======================== end decoder thread ================================\n");
}
static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh, AVPixelFormat sfmt)
@@ -681,7 +707,7 @@ static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int
struct SwsContext *scale = NULL;
scale = sws_getCachedContext(scale, sw, sh, sfmt, dw, dh, AV_PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0);
if (!scale) {
hal_info_c("%s: ERROR setting up SWS context\n", __func__);
lt_info_c("%s: ERROR setting up SWS context\n", __func__);
return ret;
}
AVFrame *sframe = av_frame_alloc();
@@ -699,7 +725,7 @@ static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int
else
ret = true;
}else{
hal_info_c("%s: could not alloc sframe (%p) or dframe (%p)\n", __func__, sframe, dframe);
lt_info_c("%s: could not alloc sframe (%p) or dframe (%p)\n", __func__, sframe, dframe);
ret = false;
}
@@ -715,14 +741,18 @@ static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int
sws_freeContext(scale);
scale = NULL;
}
hal_info_c("%s: %s scale %ix%i to %ix%i ,len %i\n",ret?" ":"ERROR",__func__, sw, sh, dw, dh,len);
lt_info_c("%s: %s scale %ix%i to %ix%i ,len %i\n",ret?" ":"ERROR",__func__, sw, sh, dw, dh,len);
return ret;
}
bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
{
hal_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
return vdec->GetScreenImage(data, xres,yres,get_video,get_osd,scale_to_video);
}
bool VDec::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
{
lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
__func__, data, xres, yres, get_video, get_osd, scale_to_video);
SWFramebuffer video;
std::vector<unsigned char> *osd = NULL;
@@ -816,7 +846,7 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
return true;
}
int64_t cVideo::GetPTS(void)
int64_t VDec::GetPTS(void)
{
int64_t pts = 0;
buf_m.lock();
@@ -828,5 +858,5 @@ int64_t cVideo::GetPTS(void)
void cVideo::SetDemux(cDemux *)
{
hal_debug("%s: not implemented yet\n", __func__);
lt_debug("%s: not implemented yet\n", __func__);
}

109
generic-pc/video_priv.h Normal file
View File

@@ -0,0 +1,109 @@
/*
Copyright 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __vdec__
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include "video_hal.h"
extern "C" {
#include <libavutil/rational.h>
}
#define VDEC_MAXBUFS 0x40
class VDec : public OpenThreads::Thread
{
friend class GLFbPC;
friend class cDemux;
friend class cVideo;
private:
/* called from GL thread */
class SWFramebuffer : public std::vector<unsigned char>
{
public:
SWFramebuffer() : mWidth(0), mHeight(0) {}
void width(int w) { mWidth = w; }
void height(int h) { mHeight = h; }
void pts(uint64_t p) { mPts = p; }
void AR(AVRational a) { mAR = a; }
int width() const { return mWidth; }
int height() const { return mHeight; }
int64_t pts() const { return mPts; }
AVRational AR() const { return mAR; }
private:
int mWidth;
int mHeight;
int64_t mPts;
AVRational mAR;
};
int buf_in, buf_out, buf_num;
public:
/* constructor & destructor */
VDec(void);
~VDec(void);
/* aspect ratio */
int getAspectRatio(void);
int setAspectRatio(int aspect, int mode);
void getPictureInfo(int &width, int &height, int &rate);
#if 0
/* cropping mode */
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
/* get play state */
int getPlayState(void);
/* blank on freeze */
int getBlank(void);
int setBlank(int enable);
#endif
int GetVideoSystem();
int SetVideoSystem(int system);
/* change video play state. Parameters are all unused. */
int Start();
int Stop(bool blank = true);
int SetStreamType(VIDEO_FORMAT type);
bool ShowPicture(const char * fname);
void Pig(int x, int y, int w, int h);
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
SWFramebuffer *getDecBuf(void);
int64_t GetPTS(void);
private:
void run();
SWFramebuffer buffers[VDEC_MAXBUFS];
int dec_w, dec_h;
int dec_r;
bool w_h_changed;
bool thread_running;
VIDEO_FORMAT v_format;
OpenThreads::Mutex buf_m;
DISPLAY_AR display_aspect;
DISPLAY_AR_MODE display_crop;
int output_h;
VIDEO_STD v_std;
int pig_x;
int pig_y;
int pig_w;
int pig_h;
bool pig_changed;
OpenThreads::Mutex still_m;
bool stillpicture;
};
#endif

View File

@@ -1,20 +1,99 @@
#include <config.h>
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/audio_lib.h"
#include "../libduckbox/audio_mixer.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/audio_lib.h"
#include "../libspark/audio_mixer.h"
#elif HAVE_ARM_HARDWARE
#include "../libarmbox/audio_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/audio_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/audio_lib.h"
#else
#include "../libgeneric-pc/audio_lib.h"
#endif
#else
#error no valid hardware defined
/*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __audio_hal__
#define __audio_hal__
#include <stdint.h>
#include <cs_types.h>
typedef enum
{
AUDIO_SYNC_WITH_PTS,
AUDIO_NO_SYNC,
AUDIO_SYNC_AUDIO_MASTER
} AUDIO_SYNC_MODE;
typedef enum {
HDMI_ENCODED_OFF,
HDMI_ENCODED_AUTO,
HDMI_ENCODED_FORCED
} HDMI_ENCODED_MODE;
typedef enum
{
AUDIO_FMT_AUTO = 0,
AUDIO_FMT_MPEG,
AUDIO_FMT_MP3,
AUDIO_FMT_DOLBY_DIGITAL,
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
AUDIO_FMT_AAC,
AUDIO_FMT_AAC_PLUS,
AUDIO_FMT_DD_PLUS,
AUDIO_FMT_DTS,
AUDIO_FMT_AVS,
AUDIO_FMT_MLP,
AUDIO_FMT_WMA,
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
} AUDIO_FORMAT;
class cAudio
{
public:
/* construct & destruct */
cAudio(void *, void *, void *);
~cAudio(void);
void *GetHandle() { return NULL; };
/* shut up */
int mute(void);
int unmute(void);
int SetMute(bool enable);
/* volume, min = 0, max = 255 */
int setVolume(unsigned int left, unsigned int right);
int getVolume(void) { return volume;}
bool getMuteStatus(void) { return muted; };
/* start and stop audio */
int Start(void);
int Stop(void);
bool Pause(bool Pcm = true);
void SetStreamType(AUDIO_FORMAT type);
void SetSyncMode(AVSYNC_TYPE Mode);
/* select channels */
int setChannel(int channel);
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
int WriteClip(unsigned char * buffer, int size);
int StopClip();
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
bool IsHdmiDDSupported();
void SetHdmiDD(bool enable);
void SetSpdifDD(bool enable);
void ScheduleMute(bool On);
void EnableAnalogOut(bool enable);
private:
bool muted;
int volume;
void *pdata;
};
#endif

View File

@@ -1,16 +1,22 @@
#ifndef __CA_H__
#define __CA_H__
/*
* dummy functions to implement ca_cs.h interface
*/
#ifndef __CA_LIBTRIPLE_H_
#define __CA_LIBTRIPLE_H_
#include <stdint.h>
#include "cs_types.h"
#include <vector>
#include <set>
typedef std::set<int> ca_map_t;
typedef ca_map_t::iterator ca_map_iterator_t;
typedef std::vector<u16> CaIdVector;
typedef std::vector<u16>::iterator CaIdVectorIterator;
typedef std::vector<u16>::const_iterator CaIdVectorConstIterator;
enum CA_INIT_MASK {
CA_INIT_SC = 1,
CA_INIT_SC = 1,
CA_INIT_CI,
CA_INIT_BOTH
};
@@ -18,7 +24,7 @@ enum CA_INIT_MASK {
enum CA_SLOT_TYPE {
CA_SLOT_TYPE_SMARTCARD,
CA_SLOT_TYPE_CI,
CA_SLOT_TYPE_ALL
CA_SLOT_TYPE_ALL,
};
enum CA_MESSAGE_FLAGS {
@@ -61,18 +67,13 @@ enum CA_MESSAGE_MSGID {
CA_MESSAGE_MSG_MMI_CLOSE,
CA_MESSAGE_MSG_INTERNAL,
CA_MESSAGE_MSG_PMT_ARRIVED,
CA_MESSAGE_MSG_CAPMT_ARRIVED,
CA_MESSAGE_MSG_CAT_ARRIVED,
CA_MESSAGE_MSG_ECM_ARRIVED,
CA_MESSAGE_MSG_EMM_ARRIVED,
CA_MESSAGE_MSG_CHANNEL_CHANGE,
CA_MESSAGE_MSG_GUI_READY,
CA_MESSAGE_MSG_EXIT
CA_MESSAGE_MSG_EXIT,
};
typedef std::set<int> ca_map_t;
typedef ca_map_t::iterator ca_map_iterator_t;
typedef struct CA_MESSAGE {
uint32_t MsgId;
enum CA_SLOT_TYPE SlotType;
@@ -94,9 +95,9 @@ public:
uint32_t GetNumberSmartCardSlots(void);
static cCA *GetInstance(void);
bool SendPMT(int Unit, unsigned char *Data, int Len, CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL);
// bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/) { return true; };
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE
/*SlotType*/, unsigned char /*scrambled = 0*/, ca_map_t /*camap = std::set<int>()*/, int /*mode = 0*/, bool /*enabled = false*/) { return true; };
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL) { (void)SlotType; return true; };
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL, unsigned char scrambled = 0, ca_map_t camap ={0}, int mode = 0, bool enable = false) { (void)SlotType;(void)scrambled;(void)camap;(void)mode;(void)enable; return true; };
bool SendMessage(const CA_MESSAGE *Msg);
void SetInitMask(enum CA_INIT_MASK InitMask);
int GetCAIDS(CaIdVector & /*Caids*/) { return 0; };
@@ -110,10 +111,8 @@ public:
void MenuAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint32_t choice);
void InputAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint8_t * Data, int Len);
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
void SetTSClock(u32 /*Speed*/, int /*slot*/) { return; };
bool checkChannelID(u64 /*chanID*/) { return false; };
void setCheckLiveSlot(int /*check*/) { return; };
void SetTSClock(u32 /*Speed*/) { return; };
virtual ~cCA();
};
#endif // __CA_H__
#endif // __CA_LIBTRIPLE_H_

View File

@@ -1,383 +0,0 @@
#ifndef __CA_CI_H__
#define __CA_CI_H__
#include <config.h>
#include <stdint.h>
#include <asm/types.h>
#include <pthread.h>
#include <list>
#include <queue>
#include <vector>
#include <set>
#include "mmi.h"
#include "cs_types.h"
#include "cs_api.h"
/* constants taken from dvb-apps */
#define T_SB 0x80 // sb primitive h<--m
#define T_RCV 0x81 // receive primitive h-->m
#define T_CREATE_T_C 0x82 // create transport connection primitive h-->m
#define T_C_T_C_REPLY 0x83 // ctc reply primitive h<--m
#define T_DELETE_T_C 0x84 // delete tc primitive h<->m
#define T_D_T_C_REPLY 0x85 // dtc reply primitive h<->m
#define T_REQUEST_T_C 0x86 // request transport connection primitive h<--m
#define T_NEW_T_C 0x87 // new tc / reply to t_request primitive h-->m
#define T_T_C_ERROR 0x77 // error creating tc primitive h-->m
#define T_DATA_LAST 0xA0 // convey data from higher constructed h<->m
#define T_DATA_MORE 0xA1 // convey data from higher constructed h<->m
/* max multi decrypt per ci-cam */
#define CI_MAX_MULTI 5
enum CA_INIT_MASK {
CA_INIT_SC = 1,
CA_INIT_CI,
CA_INIT_BOTH
};
enum CA_SLOT_TYPE {
CA_SLOT_TYPE_SMARTCARD,
CA_SLOT_TYPE_CI,
CA_SLOT_TYPE_ALL
};
enum CA_MESSAGE_FLAGS {
CA_MESSAGE_EMPTY = (1 << 0),
CA_MESSAGE_HAS_PARAM1_DATA = (1 << 1), /// Free after use!
CA_MESSAGE_HAS_PARAM1_INT = (1 << 2),
CA_MESSAGE_HAS_PARAM1_PTR = (1 << 3),
CA_MESSAGE_HAS_PARAM2_INT = (1 << 4),
CA_MESSAGE_HAS_PARAM2_PTR = (1 << 5),
CA_MESSAGE_HAS_PARAM2_DATA = (1 << 6),
CA_MESSAGE_HAS_PARAM3_DATA = (1 << 7), /// Free after use!
CA_MESSAGE_HAS_PARAM3_INT = (1 << 8),
CA_MESSAGE_HAS_PARAM3_PTR = (1 << 9),
CA_MESSAGE_HAS_PARAM4_INT = (1 << 10),
CA_MESSAGE_HAS_PARAM4_PTR = (1 << 11),
CA_MESSAGE_HAS_PARAM4_DATA = (1 << 12),
CA_MESSAGE_HAS_PARAM5_INT = (1 << 13),
CA_MESSAGE_HAS_PARAM5_PTR = (1 << 14),
CA_MESSAGE_HAS_PARAM5_DATA = (1 << 15),
CA_MESSAGE_HAS_PARAM6_INT = (1 << 16),
CA_MESSAGE_HAS_PARAM6_PTR = (1 << 17),
CA_MESSAGE_HAS_PARAM6_DATA = (1 << 18),
CA_MESSAGE_HAS_PARAM1_LONG = (1 << 19),
CA_MESSAGE_HAS_PARAM2_LONG = (1 << 20),
CA_MESSAGE_HAS_PARAM3_LONG = (1 << 21),
CA_MESSAGE_HAS_PARAM4_LONG = (1 << 22)
};
enum CA_MESSAGE_MSGID {
CA_MESSAGE_MSG_INSERTED,
CA_MESSAGE_MSG_REMOVED,
CA_MESSAGE_MSG_INIT_OK,
CA_MESSAGE_MSG_INIT_FAILED,
CA_MESSAGE_MSG_MMI_MENU,
CA_MESSAGE_MSG_MMI_MENU_ENTER,
CA_MESSAGE_MSG_MMI_MENU_ANSWER,
CA_MESSAGE_MSG_MMI_LIST,
CA_MESSAGE_MSG_MMI_TEXT,
CA_MESSAGE_MSG_MMI_REQ_INPUT,
CA_MESSAGE_MSG_MMI_CLOSE,
CA_MESSAGE_MSG_INTERNAL,
CA_MESSAGE_MSG_PMT_ARRIVED,
CA_MESSAGE_MSG_CAPMT_ARRIVED,
CA_MESSAGE_MSG_CAT_ARRIVED,
CA_MESSAGE_MSG_ECM_ARRIVED,
CA_MESSAGE_MSG_EMM_ARRIVED,
CA_MESSAGE_MSG_CHANNEL_CHANGE,
CA_MESSAGE_MSG_GUI_READY,
CA_MESSAGE_MSG_EXIT
};
typedef struct CA_MESSAGE {
uint32_t MsgId;
enum CA_SLOT_TYPE SlotType;
int Slot;
uint32_t Flags;
union {
uint8_t *Data[4];
uint32_t Param[4];
void *Ptr[4];
uint64_t ParamLong[4];
} Msg;
} CA_MESSAGE;
typedef std::set<int> ca_map_t;
typedef ca_map_t::iterator ca_map_iterator_t;
typedef std::vector<u16> bSIDVector;
typedef std::vector<u16> CaIdVector;
typedef std::vector<u16>::iterator CaIdVectorIterator;
typedef std::vector<u16>::const_iterator CaIdVectorConstIterator;
#define CA_MESSAGE_SIZE sizeof(CA_MESSAGE)
#define CA_MESSAGE_ENTRIES 256
#define CA_MESSAGE_ENTRIES_CI 128
#define CA_MESSAGE_ENTRIES_SC 64
#ifndef CS_CA_PDATA
#define CS_CA_PDATA void
#endif
typedef enum {
TUNER_A,
TUNER_B,
TUNER_C,
TUNER_D
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
, TUNER_E
, TUNER_F
, TUNER_G
, TUNER_H
, TUNER_I
, TUNER_J
, TUNER_K
, TUNER_L
, TUNER_M
, TUNER_N
, TUNER_O
, TUNER_P
#if BOXMODEL_VUULTIMO4K
, TUNER_Q
, TUNER_R
, TUNER_S
, TUNER_T
, TUNER_U
, TUNER_V
, TUNER_W
, TUNER_X
#endif
#endif
} source_t;
typedef enum {
eDataTimeout,
eDataError,
eDataReady,
eDataWrite,
eDataStatusChanged
} eData;
typedef enum {
eStatusNone,
eStatusWait,
eStatusReset
} eStatus;
struct queueData
{
__u8 prio;
unsigned char *data;
unsigned int len;
queueData(unsigned char *_data, unsigned int _len, __u8 _prio = 0)
:prio(_prio), data(_data), len(_len)
{
}
bool operator < ( const struct queueData &a ) const
{
return prio < a.prio;
}
};
class eDVBCIMMISession;
class eDVBCIApplicationManagerSession;
class eDVBCICAManagerSession;
class eDVBCIContentControlManagerSession;
typedef struct
{
pthread_t slot_thread;
unsigned int slot;
int fd;
int connection_id;
eStatus status;
int receivedLen;
unsigned char* receivedData;
void* pClass;
bool pollConnection;
bool camIsReady;
eDVBCIMMISession* mmiSession;
eDVBCIApplicationManagerSession* appSession;
eDVBCICAManagerSession* camgrSession;
eDVBCIContentControlManagerSession* ccmgrSession;
bool hasAppManager;
bool hasMMIManager;
bool hasCAManager;
bool hasCCManager;
bool hasDateTime;
bool mmiOpened;
bool init;
bool ccmgr_ready;
char ci_dev[32];
char name[512];
bool newPids;
bool newCapmt;
bool multi;
bool recordUse[CI_MAX_MULTI];
bool liveUse[CI_MAX_MULTI];
u16 SID[CI_MAX_MULTI];
u64 TP;
int ci_use_count;
u32 pmtlen;
u8 source;
u8 camask;
unsigned char pmtdata[1024 * 4];
int counter;
CaIdVector cam_caids;
std::priority_queue<queueData> sendqueue;
std::vector<u16> pids;
bSIDVector bsids;
unsigned char lastKey[32];
unsigned char scrambled;
u8 lastParity;
bool DataLast;
bool DataRCV;
bool SidBlackListed;
/* private data */
void *private_data;
} eDVBCISlot;
eData sendData(eDVBCISlot *slot, unsigned char* data, int len);
typedef std::list<eDVBCISlot*>::iterator SlotIt;
/// CA module class
class cCA {
private:
/// Static instance of the CA module
// static cCA *inst;
/// Private constructor (singleton method)
cCA(void);
/// Private data for the CA module
CS_CA_PDATA *privateData;
/// set inputs with tuner letter in tsmux
void setInputs();
/// write ci info file to /tmp
void write_ci_info(int slot, CaIdVector caids);
/// delete ci info file
void del_ci_info(int slot);
/// extract audio / video pids from capmt
void extractPids(eDVBCISlot* slot);
/// ci module is detected
void ci_inserted(eDVBCISlot* slot);
/// ci module is removed
void ci_removed(eDVBCISlot* slot);
/// decode the tpdu tag
void process_tpdu(eDVBCISlot* slot, unsigned char tpdu_tag, __u8* data, int asn_data_length, int con_id);
/// set flag of running ci record to false
bool StopRecordCI( u64 TP, u16 SID, u8 source, u32 calen);
/// set flag of running ci live-tv to false
bool StopLiveCI( u64 TP, u16 SID, u8 source, u32 calen);
/// find an unused ci slot for use with service
SlotIt FindFreeSlot(u64 tpid, u8 source, u16 sid, ca_map_t camap, u8 scrambled);
/// get slot iterator by slot number
SlotIt GetSlot(unsigned int slot);
/// send buffered capmt to ci modul
bool SendCaPMT(eDVBCISlot* slot);
/// send a dummy capmt to ci for deactivating
bool SendNullPMT(eDVBCISlot* slot);
/// set ci source
void setSource(eDVBCISlot* slot);
/// set demux source
void setInputSource(eDVBCISlot* slot, bool ci);
/// check if data in queue
bool checkQueueSize(eDVBCISlot* slot);
enum CA_INIT_MASK initMask;
int num_slots;
bool init;
void SendPMT();
pthread_mutex_t ciMutex;
std::list<eDVBCISlot*> slot_data;
pthread_t slot_thread;
public:
/// sh4 unused
bool Init(void);
/// init ci and start the loop
cCA(int Slots);
/// Returns the number of CI slots
uint32_t GetNumberCISlots(void);
/// Returns the number of Smartcard slots
uint32_t GetNumberSmartCardSlots(void);
/// Singleton
static cCA *GetInstance(void);
/// Send PMT to a individual or to all available modules (DEPRECATED)
bool SendPMT(int Unit, unsigned char *Data, int Len, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL);
/// Sends a message to the CA thread
bool SendMessage(const CA_MESSAGE *Msg);
/// Sets which modules to initialize. It is only
/// possible to change this once!
/// sh4 unused
void SetInitMask(enum CA_INIT_MASK InitMask);
/// Sets the frequency (in Hz) of the TS stream input (only valid for CI)
/// sh4 unused
void SetTSClock(u32 Speed, int slot = 0);
#if BOXMODEL_VUPLUS_ALL
/// dvb wait delay for ci response
void SetCIDelay(int Delay);
/// relevant pids routing
void SetCIRelevantPidsRouting(int RPR, int slot = 0);
#endif
/// Start the CA module
/// sh4 unused
bool Start(void);
/// Stops the CA module
/// sh4 unused
void Stop(void);
/// Notify that the GUI is ready to receive messages
/// (CA messages coming from a module)
/// sh4 unused
void Ready(bool Set);
/// Resets a module (if possible)
/// sh4 unused
void ModuleReset(enum CA_SLOT_TYPE, uint32_t Slot);
/// Checks if a module is present
bool ModulePresent(enum CA_SLOT_TYPE, uint32_t Slot);
/// Returns the module name in array Name
void ModuleName(enum CA_SLOT_TYPE, uint32_t Slot, char *Name);
/// Notify the module we want to enter menu
void MenuEnter(enum CA_SLOT_TYPE, uint32_t Slot);
/// Notify the module with our answer (choice nr)
void MenuAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint32_t choice);
/// Notify the module with our answer (binary)
void InputAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint8_t * Data, int Len);
/// Notify the module we closed the menu
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
/// Get the supported CAIDs
int GetCAIDS(CaIdVector &Caids);
/// Send a CA-PMT object and Raw unparsed PMT to the CA layer
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL,
unsigned char scrambled = 0, ca_map_t camap = std::set<int>(), int mode = 0, bool enabled = false);
/// sh4 unused
bool SendDateTime(void);
/// the main loop
void slot_pollthread(void *c);
/// check if current channel uses any ci module
bool checkChannelID(u64 chanID);
/// set checking for live-tv use ci to true
void setCheckLiveSlot(int check);
/// as the name says
bool CheckCerts(void);
/// Virtual destructor
virtual ~cCA();
};
#endif // __CA_CI_H__

1
include/ca_cs.h Normal file
View File

@@ -0,0 +1 @@
#include "ca.h"

View File

@@ -1,11 +0,0 @@
#if HAVE_DUCKBOX_HARDWARE \
|| HAVE_MIPS_HARDWARE \
|| (HAVE_ARM_HARDWARE \
&& !BOXMODEL_HD60 \
&& !BOXMODEL_OSMIO4K \
&& !BOXMODEL_OSMIO4KPLUS \
)
#include "ca_ci.h"
#else
#include "ca.h"
#endif

View File

@@ -1,44 +1,67 @@
/* compatibility header for tripledragon. I'm lazy, so I just left it
as "cs_api.h" so that I don't need too many ifdefs in the code */
#ifndef __CS_API_H__
#define __CS_API_H__
#include "init.h"
#include <config.h>
#ifndef __CS_API_H_
#define __CS_API_H_
#include "init_td.h"
typedef void (*cs_messenger) (unsigned int msg, unsigned int data);
#if 0
enum CS_LOG_MODULE {
CS_LOG_CI = 0,
CS_LOG_HDMI_CEC,
CS_LOG_HDMI,
CS_LOG_VIDEO,
CS_LOG_VIDEO_DRM,
CS_LOG_AUDIO,
CS_LOG_DEMUX,
CS_LOG_DENC,
CS_LOG_PVR_RECORD,
CS_LOG_PVR_PLAY,
CS_LOG_POWER_CTRL,
CS_LOG_POWER_CLK,
CS_LOG_MEM,
CS_LOG_API,
};
#endif
inline void cs_api_init()
{
hal_api_init();
init_td_api();
};
inline void cs_api_exit()
{
hal_api_exit();
shutdown_td_api();
};
#define cs_malloc_uncached malloc
#define cs_free_uncached free
// Callback function helpers
#if HAVE_DUCKBOX_HARDWARE \
|| HAVE_MIPS_HARDWARE \
|| (HAVE_ARM_HARDWARE \
&& !BOXMODEL_HD60 \
&& !BOXMODEL_OSMIO4K \
&& !BOXMODEL_OSMIO4KPLUS \
)
void cs_register_messenger(cs_messenger messenger);
#else
static inline void cs_register_messenger(cs_messenger) { return; };
#endif
static inline void cs_deregister_messenger(void) { return; };
//cs_messenger cs_get_messenger(void);
#if 0
// Logging functions
void cs_log_enable(void);
void cs_log_disable(void);
void cs_log_message(const char *prefix, const char *fmt, ...);
void cs_log_module_enable(enum CS_LOG_MODULE module);
void cs_log_module_disable(enum CS_LOG_MODULE module);
void cs_log_module_message(enum CS_LOG_MODULE module, const char *fmt, ...);
// TS Routing
unsigned int cs_get_ts_output(void);
int cs_set_ts_output(unsigned int port);
// Serial nr and revision accessors
unsigned long long cs_get_serial(void);
#endif
/* compat... HD1 seems to be version 6. everything newer ist > 6... */
static inline unsigned int cs_get_revision(void) { return 1; };
static inline unsigned int cs_get_chip_type(void) { return 0; };
extern int cnxt_debug;
#endif // __CS_API_H__
#endif //__CS_API_H_

View File

@@ -1,320 +0,0 @@
#ifndef __CS_FRONTPANEL_H__
#define __CS_FRONTPANEL_H__
#define VFDDISPLAYCHARS 0xc0425a00
#define VFDWRITECGRAM 0x40425a01
#define VFDBRIGHTNESS 0xc0425a03
#define VFDPWRLED 0xc0425a04
#define VFDDRIVERINIT 0xc0425a08
#define VFDICONDISPLAYONOFF 0xc0425a0a
#define VFDDISPLAYWRITEONOFF 0xc0425a05
#define VFDCLEARICONS 0xc0425af6
#define VFDSETRF 0xc0425af7
#define VFDSETFAN 0xc0425af8
#define VFDGETWAKEUPMODE 0xc0425af9
#define VFDGETTIME 0xc0425afa
#define VFDSETTIME 0xc0425afb
#define VFDSTANDBY 0xc0425afc
#define VFDREBOOT 0xc0425afd
#define VFDSETLED 0xc0425afe
#define VFDSETMODE 0xc0425aff
#define VFDGETWAKEUPTIME 0xc0425b00
#define VFDGETVERSION 0xc0425b01
#define VFDSETDISPLAYTIME 0xc0425b02
#define VFDSETTIMEMODE 0xc0425b03
#define VFDDISPLAYCLR 0xc0425b00
typedef enum {
#if defined(BOXMODEL_OCTAGON1008)
ICON_DOLBY = 0x10,
ICON_DTS,
ICON_VIDEO,
ICON_AUDIO,
ICON_LINK,
ICON_HDD,
ICON_DISC,
ICON_DVB,
ICON_DVD,
ICON_TIME,
ICON_TIMER,
ICON_CARD,
ICON_1,
ICON_2,
ICON_KEY,
ICON_16_9,
ICON_USB,
ICON_CRYPTED,
ICON_PLAY,
ICON_REWIND,
ICON_PAUSE,
ICON_FF,
ICON_REC,
ICON_ARROW,
ICON_COLON1,
ICON_COLON2,
ICON_COLON3,
ICON_MAX,
FP_ICON_USB = ICON_USB,
FP_ICON_HD = ICON_16_9,
FP_ICON_HDD = ICON_HDD,
FP_ICON_LOCK = ICON_CRYPTED,
FP_ICON_BT,
FP_ICON_MP3,
FP_ICON_MUSIC,
FP_ICON_DD = ICON_DOLBY,
FP_ICON_MAIL,
FP_ICON_MUTE = ICON_TIME,
FP_ICON_PLAY = ICON_PLAY,
FP_ICON_PAUSE = ICON_PAUSE,
FP_ICON_FF = ICON_FF,
FP_ICON_FR = ICON_REWIND,
FP_ICON_REC = ICON_REC,
FP_ICON_CLOCK = ICON_TIMER,
FP_ICON_RADIO = ICON_AUDIO,
FP_ICON_TV = ICON_VIDEO,
FP_ICON_DOWNLOAD = ICON_LINK,
FP_ICON_CAM1 = ICON_REC,
#elif defined(BOXMODEL_FORTIS_HDBOX)
ICON_USB = 0x10,
ICON_STANDBY,
ICON_SAT,
ICON_REC,
ICON_TIMESHIFT,
ICON_TIMER,
ICON_HD,
ICON_SCRAMBLED,
ICON_DOLBY,
ICON_MUTE,
ICON_TUNER1,
ICON_TUNER2,
ICON_MP3,
ICON_REPEAT,
ICON_Play,
ICON_TER,
ICON_FILE,
ICON_480i,
ICON_480p,
ICON_576i,
ICON_576p,
ICON_720p,
ICON_1080i,
ICON_1080p,
ICON_Circ0,
ICON_Circ1,
ICON_Circ2,
ICON_Circ3,
ICON_Circ4,
ICON_Circ5,
ICON_Circ6,
ICON_Circ7,
ICON_Circ8,
ICON_COLON1,
ICON_COLON2,
ICON_COLON3,
ICON_COLON4,
ICON_TV,
ICON_RADIO,
ICON_MAX,
FP_ICON_USB = ICON_USB,
FP_ICON_REC = ICON_REC,
FP_ICON_CAM1 = ICON_REC,
FP_ICON_TIMESHIFT = ICON_TIMESHIFT,
FP_ICON_CLOCK = ICON_TIMER,
FP_ICON_HD = ICON_HD,
FP_ICON_LOCK = ICON_SCRAMBLED,
FP_ICON_DD = ICON_DOLBY,
FP_ICON_MUTE = ICON_MUTE,
FP_ICON_BT = 0,
FP_ICON_MP3 = ICON_MP3,
FP_ICON_PLAY = ICON_Play,
FP_ICON_PAUSE = 0,
FP_ICON_HDD = 0,
FP_ICON_MAIL = 0,
FP_ICON_FF = 0,
FP_ICON_FR = 0,
FP_ICON_RADIO = ICON_RADIO,
FP_ICON_TV = ICON_TV,
FP_ICON_MUSIC = ICON_RADIO,
FP_ICON_MAX = ICON_MAX
#elif defined(BOXMODEL_UFS910) || defined(BOXMODEL_UFS922) || defined(BOXMODEL_UFS912) || defined(BOXMODEL_UFS913)
FP_ICON_USB = 0x10,
FP_ICON_HD,
FP_ICON_HDD,
FP_ICON_LOCK,
FP_ICON_BT,
FP_ICON_MP3,
FP_ICON_MUSIC,
FP_ICON_DD,
FP_ICON_MAIL,
FP_ICON_MUTE,
FP_ICON_PLAY,
FP_ICON_PAUSE,
FP_ICON_FF,
FP_ICON_FR,
FP_ICON_REC,
FP_ICON_CLOCK,
FP_ICON_MAX,
FP_ICON_CAM1 = FP_ICON_REC,
FP_ICON_TV = 0,
FP_ICON_RADIO = FP_ICON_MUSIC,
FP_ICON_RECORD = FP_ICON_REC,
FP_ICON_DOWNLOAD = 0,
FP_ICON_TIMESHIFT = 0
#elif defined(BOXMODEL_IPBOX9900) || defined(BOXMODEL_IPBOX99)
ICON_STANDBY,
ICON_SAT,
ICON_REC,
ICON_TIMESHIFT,
ICON_TIMER,
ICON_HD,
ICON_SCRAMBLED,
ICON_MUTE,
ICON_TUNER1,
ICON_TUNER2,
ICON_MP3,
ICON_REPEAT,
ICON_PLAY,
ICON_PAUSE,
ICON_TER,
ICON_FILE,
ICON_480I,
ICON_480P,
ICON_576I,
ICON_576P,
ICON_720P,
ICON_1080I,
ICON_1080P,
ICON_TV,
ICON_RADIO,
ICON_MAX,
FP_ICON_480P = ICON_480P,
FP_ICON_480I = ICON_480I,
FP_ICON_576P = ICON_576P,
FP_ICON_576I = ICON_576I,
FP_ICON_PLAY = ICON_PLAY,
FP_ICON_PAUSE = ICON_PAUSE,
FP_ICON_1080P = 0x0A,
FP_ICON_1080I = 0x09,
FP_ICON_720P = 0x08,
FP_ICON_POWER = 0x00,
FP_ICON_HD = 0x05,
FP_ICON_RADIO = 0x0D,
FP_ICON_MP3 = FP_ICON_RADIO,
FP_ICON_MUSIC = FP_ICON_RADIO,
FP_ICON_DD = 0x04,
FP_ICON_REC = 0x03,
FP_ICON_FF = 0,
FP_ICON_FR = 0,
FP_ICON_USB = 0,
FP_ICON_HDD = 0,
FP_ICON_MUTE = 0,
FP_ICON_CLOCK = 0,
FP_ICON_CAM1 = 0,
FP_ICON_LOCK = 0,
FP_ICON_DOWNLOAD = 0,
FP_ICON_TIMESHIFT = FP_ICON_REC,
FP_ICON_TV = 0,
FP_ICON_MAIL = 0,
FP_ICON_BT = 0,
#else
FP_ICON_USB = 0x10,
FP_ICON_HD,
FP_ICON_HDD,
FP_ICON_LOCK,
FP_ICON_BT,
FP_ICON_MP3,
FP_ICON_MUSIC,
FP_ICON_DD,
FP_ICON_MAIL,
FP_ICON_MUTE,
FP_ICON_PLAY,
FP_ICON_PAUSE,
FP_ICON_FF,
FP_ICON_FR,
FP_ICON_REC,
FP_ICON_CLOCK,
FP_ICON_CAM1 = FP_ICON_REC,
FP_ICON_TV = FP_ICON_MUSIC,
FP_ICON_RADIO = FP_ICON_MUSIC,
FP_ICON_RECORD = FP_ICON_REC,
FP_ICON_DOWNLOAD,
FP_ICON_TIMESHIFT,
#endif
#if !defined(BOXMODEL_UFS910) && !defined(BOXMODEL_UFS922) && !defined(BOXMODEL_UFS912) && !defined(BOXMODEL_UFS913) && !defined(BOXMODEL_FORTIS_HDBOX)
FP_ICON_MAX
#endif
} fp_icon;
typedef enum {
FP_FLAG_NONE = 0x00,
FP_FLAG_SCROLL_ON = 0x01, /* switch scrolling on */
FP_FLAG_SCROLL_LTR = 0x02, /* scroll from left to rightinstead of default right to left direction (i.e. for arabic text) */
FP_FLAG_SCROLL_SIO = 0x04, /* start/stop scrolling with empty screen (scroll in/out) */
FP_FLAG_SCROLL_DELAY = 0x08, /* delayed scroll start */
FP_FLAG_ALIGN_LEFT = 0x10, /* align the text in display from the left (default) */
FP_FLAG_ALIGN_RIGHT = 0x20, /* align the text in display from the right (arabic) */
FP_FLAG_UPDATE_SCROLL_POS = 0x40, /* update the current position for scrolling */
} fp_flag;
typedef struct {
unsigned char brightness;
unsigned char flags;
unsigned char current_hour;
unsigned char current_minute;
unsigned char timer_minutes_hi;
unsigned char timer_minutes_lo;
} fp_standby_data_t;
typedef enum {
FP_LED_1_ON = 0x81,
FP_LED_2_ON = 0x82,
FP_LED_3_ON = 0x83,
FP_LED_1_OFF = 0x01,
FP_LED_2_OFF = 0x02,
FP_LED_3_OFF = 0x03,
} fp_led_ctrl_t;
typedef struct {
unsigned char source;
unsigned char time_minutes_hi;
unsigned char time_minutes_lo;
} fp_wakeup_data_t;
typedef enum {
FP_WAKEUP_SOURCE_TIMER = 0x01,
FP_WAKEUP_SOURCE_BUTTON = 0x02,
FP_WAKEUP_SOURCE_REMOTE = 0x04,
FP_WAKEUP_SOURCE_PWLOST = 0x7F,
FP_WAKEUP_SOURCE_POWER = 0xFF
} fp_wakeup_source;
typedef struct {
unsigned short addr;
unsigned short cmd;
} fp_standby_cmd_data_t;
typedef enum {
FP_DISPLAY_TEXT_NONE = 0,
FP_DISPLAY_TEXT_LIMITED,
FP_DISPLAY_TEXT_ALL,
} fp_display_text_type_t;
typedef enum {
FP_DISPLAY_TYPE_NONE = 0,
FP_DISPLAY_TYPE_VFD,
FP_DISPLAY_TYPE_OLED,
FP_DISPLAY_TYPE_LED_SEGMENT
} fp_display_type_t;
typedef struct {
fp_display_type_t display_type;
unsigned short xres, yres;
unsigned int segment_count;
fp_display_text_type_t text_support;
bool number_support;
} fp_display_caps_t;
#endif // __CS_FRONTPANEL_H__

View File

@@ -1,8 +1,8 @@
/* pretty useless, but we don't need to work around this if
* we just copy it over... */
#ifndef __CS_TYPES_H__
#define __CS_TYPES_H__
#ifndef __CS_TYPES_H_
#define __CS_TYPES_H_
typedef enum
{
@@ -20,4 +20,4 @@ typedef signed int s32;
typedef signed short s16;
typedef signed char s8;
#endif // __CS_TYPES_H__
#endif // __CS_TYPES_H_

1
include/dmx_cs.h Normal file
View File

@@ -0,0 +1 @@
#include "dmx_hal.h"

View File

@@ -15,10 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DMX_HAL_H__
#define __DMX_HAL_H__
#ifndef __dmx_hal__
#define __dmx_hal__
#include <config.h>
#include <cstdlib>
#include <vector>
#include <inttypes.h>
@@ -37,38 +36,7 @@ extern "C" {
#include <cs_types.h>
#if BOXMODEL_VUULTIMO4K
#define MAX_DMX_UNITS 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define MAX_DMX_UNITS 16
#else
#define MAX_DMX_UNITS 4
#endif
#endif
#ifndef DMX_SET_SOURCE
/**
* DMX_SET_SOURCE and dmx_source enum removed on 4.14 kernel
* From Github.com/OpenPLI/enigma2 commit 7996dbb
**/
enum dmx_source
{
DMX_SOURCE_FRONT0 = 0,
DMX_SOURCE_FRONT1,
DMX_SOURCE_FRONT2,
DMX_SOURCE_FRONT3,
#if BOXMODEL_VUPLUS_ARM
DMX_SOURCE_DVR0 = 32,
#else
DMX_SOURCE_DVR0 = 16,
#endif
DMX_SOURCE_DVR1,
DMX_SOURCE_DVR2,
DMX_SOURCE_DVR3
};
#define DMX_SET_SOURCE _IOW('o', 49, enum dmx_source)
#endif
typedef enum
{
@@ -92,38 +60,38 @@ class cRecord;
class cPlayback;
class cDemux
{
friend class cRecord;
friend class cPlayback;
public:
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
void Close(void);
bool Start(bool record = false);
bool Stop(void);
int Read(unsigned char *buff, int len, int Timeout = 0);
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
bool pesFilter(const unsigned short pid);
void SetSyncMode(AVSYNC_TYPE mode);
void * getBuffer();
void * getChannel();
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
bool addPid(unsigned short pid);
void getSTC(int64_t * STC);
int getUnit(void);
static bool SetSource(int unit, int source);
static int GetSource(int unit);
int getFD(void) { return fd; }; /* needed by cPlayback class */
cDemux(int num = 0);
~cDemux();
private:
void removePid(unsigned short Pid); /* needed by cRecord class */
int num;
int fd;
int buffersize;
uint16_t pid;
uint8_t flt;
std::vector<pes_pids> pesfds;
DMX_CHANNEL_TYPE dmx_type;
void *pdata;
friend class cRecord;
friend class cPlayback;
public:
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
void Close(void);
bool Start(bool record = false);
bool Stop(void);
int Read(unsigned char *buff, int len, int Timeout = 0);
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
bool pesFilter(const unsigned short pid);
void SetSyncMode(AVSYNC_TYPE mode);
void * getBuffer();
void * getChannel();
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
bool addPid(unsigned short pid);
void getSTC(int64_t * STC);
int getUnit(void);
static bool SetSource(int unit, int source);
static int GetSource(int unit);
cDemux(int num = 0);
~cDemux();
int getFD(void) { return fd; }; /* needed by cPlayback class */
private:
void removePid(unsigned short Pid); /* needed by cRecord class */
int num;
int fd;
int buffersize;
uint16_t pid;
uint8_t flt;
std::vector<pes_pids> pesfds;
DMX_CHANNEL_TYPE dmx_type;
void *pdata;
};
#endif // __DMX_HAL_H__
#endif //__dmx_hal__

View File

@@ -16,9 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GLFB_H__
#define __GLFB_H__
#ifndef __glfb__
#define __glfb__
#include <OpenThreads/Thread>
#include <vector>
#include <linux/fb.h> /* for screeninfo etc. */
@@ -40,5 +39,4 @@ private:
void blit_osd();
void *pdata; /* not yet used */
};
#endif // __GLFB_H__
#endif

View File

@@ -15,7 +15,6 @@ extern "C" {
typedef enum
{
HW_DISPLAY_NONE,
HW_DISPLAY_LED_ONLY,
HW_DISPLAY_LED_NUM, /* simple 7 segment LED display */
HW_DISPLAY_LINE_TEXT, /* 1 line text display */
HW_DISPLAY_GFX
@@ -29,7 +28,6 @@ typedef struct hw_caps
int has_SCART;
int has_SCART_input;
int has_YUV_cinch;
int can_cpufreq;
int can_shutdown;
int can_cec;
int can_ar_14_9; /* video drivers have 14:9 aspect ratio mode */
@@ -38,17 +36,13 @@ typedef struct hw_caps
display_type_t display_type;
int display_xres; /* x resolution or chars per line */
int display_yres;
int display_can_set_brightness;
int display_can_deepstandby;
int display_can_set_brightness;
int display_has_statusline;
int display_has_colon;
int has_button_timer;
int has_button_vformat;
char boxvendor[64];
char boxname[64];
char boxarch[64];
int boxtype;
int has_CI;
} hw_caps_t;
hw_caps_t *get_hwcaps(void);
@@ -56,5 +50,4 @@ hw_caps_t *get_hwcaps(void);
#ifdef __cplusplus
}
#endif
#endif // __HARDWARE_CAPS_H__
#endif

View File

@@ -1,7 +0,0 @@
#ifndef __INIT_H__
#define __INIT_H__
void hal_api_init();
void hal_api_exit();
#endif // __INIT_H__

2
include/init_cs.h Normal file
View File

@@ -0,0 +1,2 @@
#warning using init_cs.h from libstb-hal
#include "init_td.h"

5
include/init_td.h Normal file
View File

@@ -0,0 +1,5 @@
#ifndef __INIT_TD_H
#define __INIT_TD_H
void init_td_api();
void shutdown_td_api();
#endif

View File

@@ -1,34 +1,11 @@
#ifndef __MMI_H__
#define __MMI_H__
#ifndef __MMI_H_
#define __MMI_H_
#define MAX_MMI_ITEMS 40
#define MAX_MMI_TEXT_LEN 255
#define MAX_MMI_CHOICE_TEXT_LEN 255
typedef enum {
MMI_TOP_MENU_SUBS = 1,
MMI_TOP_MENU_EVENTS,
MMI_TOP_MENU_TOKENS,
MMI_TOP_MENU_PIN,
MMI_TOP_MENU_MATURE,
MMI_TOP_MENU_ABOUT
} MMI_MENU_CURRENT;
typedef enum {
MMI_MENU_LEVEL_MAIN = 0,
MMI_MENU_LEVEL_MATURE,
MMI_MENU_LEVEL_ASK_PIN_MATURE
} MMI_MENU_LEVEL;
typedef enum {
MMI_PIN_LEVEL_ASK_OLD = 0,
MMI_PIN_LEVEL_CHECK_CURRENT,
MMI_PIN_LEVEL_ASK_REPEAT,
MMI_PIN_LEVEL_CHECK_AND_CHANGE
} MMI_PIN_LEVEL;
typedef struct {
int slot;
int choice_nb;
char title[MAX_MMI_TEXT_LEN];
char subtitle[MAX_MMI_TEXT_LEN];
@@ -37,15 +14,14 @@ typedef struct {
} MMI_MENU_LIST_INFO;
typedef struct {
int slot;
int blind;
int answerlen;
char enquiryText[MAX_MMI_TEXT_LEN];
} MMI_ENQUIRY_INFO;
/* compat */
#define enguiryText enquiryText
#define enguiryText enquiryText
#define MMI_ENGUIRY_INFO MMI_ENQUIRY_INFO
#endif // __MMI_H__
#endif // __MMI_H_

1
include/playback.h Normal file
View File

@@ -0,0 +1 @@
#include "playback_hal.h"

View File

@@ -1,30 +1,82 @@
#include <config.h>
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/playback_libeplayer3.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/playback_libeplayer3.h"
#elif HAVE_ARM_HARDWARE
#if ENABLE_GSTREAMER_10
#include "../libarmbox/playback_gst.h"
#else
#if BOXMODEL_HISILICON
#include "../libarmbox/playback_hisilicon.h"
#else
#include "../libarmbox/playback_libeplayer3.h"
#endif
#endif
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/playback_libeplayer3.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/playback_lib.h"
#else
#if ENABLE_GSTREAMER
#include "../libgeneric-pc/playback_gst.h"
#else
#include "../libgeneric-pc/playback_lib.h"
#endif
#endif
#else
#error no valid hardware defined
/*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __playback_hal__
#define __playback_hal__
#include <string>
#include <stdint.h>
#include <vector>
extern "C" {
#include <libavformat/avformat.h>
}
/*
* This is actually the max number that could be returned by
* FindAllPids() / FindAllSubs().
* not yet implemented, most archs return max. 10 PIDs.
*/
#define MAX_PLAYBACK_PIDS 40
typedef enum {
PLAYMODE_TS = 0,
PLAYMODE_FILE,
} playmode_t;
class PBPrivate;
class cPlayback
{
public:
bool Open(playmode_t PlayMode);
void Close(void);
bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid, int ac3, unsigned int duration);
bool Start(std::string filename, std::string headers = "");
bool Stop(void);
bool SetAPid(unsigned short pid, int audio_flag);
bool SetSpeed(int speed);
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration);
bool SetPosition(int position, bool absolute = false);
void FindAllPids(uint16_t *pids, unsigned short *aud_flags, uint16_t *num, std::string *language);
void FindAllPids(int *apids, unsigned int *ac3flags, uint32_t *numpida, std::string *language){FindAllPids((uint16_t*)apids, (unsigned short*)ac3flags, (uint16_t*) numpida, language);}
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *num, std::string *language);
bool SelectSubtitles(int pid, std::string charset = "");
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void RequestAbort();
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current);
void SetTitle(int title);
uint64_t GetReadCount(void);
void FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *){*numpids = 0;}
void FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/){*numpids = 0;}
int GetSubtitlePid(void){return 0;}
bool SetTeletextPid(int /*pid*/){return true;}
int GetAPid(){return 0;}
void GetMetadata(std::vector<std::string> /*&keys*/, std::vector<std::string> /*&values*/){}
void GetPts(uint64_t &/*pts*/){}
bool SetSubtitlePid(int /*pid*/){return false;}
AVFormatContext *GetAVFormatContext(){return NULL;}
void ReleaseAVFormatContext(){}
//
cPlayback(int num = 0);
~cPlayback();
private:
PBPrivate *pd;
};
#endif

View File

@@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PWRMNGR_H__
#define __PWRMNGR_H__
#ifndef __pwrmngr_hal__
#define __pwrmngr_hal__
class cCpuFreqManager
{
@@ -44,4 +44,4 @@ public:
bool SetStandby(bool Active, bool Passive);
};
#endif // __PWRMNGR_H__
#endif

View File

@@ -1,18 +1,41 @@
#include <config.h>
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/record_lib.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/record_lib.h"
#elif HAVE_ARM_HARDWARE
#include "../libarmbox/record_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/record_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/record_lib.h"
#else
#include "../libgeneric-pc/record_lib.h"
#endif
#else
#error no valid hardware defined
/*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __record_hal__
#define __record_hal__
#define REC_STATUS_OK 0
#define REC_STATUS_SLOW 1
#define REC_STATUS_OVERFLOW 2
class RecData;
class cRecord
{
public:
cRecord(int num = 0);
~cRecord();
bool Open();
bool Start(int fd, unsigned short vpid, unsigned short *apids, int numapids, uint64_t ch = 0);
bool Stop(void);
bool AddPid(unsigned short pid);
int GetStatus();
void ResetStatus();
bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids);
private:
RecData *pd;
};
#endif

1
include/video_cs.h Normal file
View File

@@ -0,0 +1 @@
#include "video_hal.h"

View File

@@ -1,24 +1,213 @@
#include <config.h>
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/video_lib.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/video_lib.h"
#elif HAVE_ARM_HARDWARE
#include "../libarmbox/video_lib.h"
#include "../libarmbox/hdmi_cec.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/video_lib.h"
#include "../libmipsbox/hdmi_cec.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/video_lib.h"
#else
#include "../libgeneric-pc/video_lib.h"
#endif
#else
#error no valid hardware defined
#endif
/*
Copyright 2010-2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _VIDEO_LIB_H
#define _VIDEO_LIB_H
#include <vector>
#include <cs_types.h>
typedef enum {
ANALOG_SD_RGB_CINCH = 0x00,
ANALOG_SD_YPRPB_CINCH,
ANALOG_HD_RGB_CINCH,
ANALOG_HD_YPRPB_CINCH,
ANALOG_SD_RGB_SCART = 0x10,
ANALOG_SD_YPRPB_SCART,
ANALOG_HD_RGB_SCART,
ANALOG_HD_YPRPB_SCART,
ANALOG_SCART_MASK = 0x10
} analog_mode_t;
typedef enum {
VIDEO_FORMAT_MPEG2 = 0,
VIDEO_FORMAT_MPEG4, /* H264 */
VIDEO_FORMAT_VC1,
VIDEO_FORMAT_JPEG,
VIDEO_FORMAT_GIF,
VIDEO_FORMAT_PNG,
VIDEO_FORMAT_DIVX,/* DIVX 3.11 */
VIDEO_FORMAT_MPEG4PART2,/* MPEG4 SVH, MPEG4 SP, MPEG4 ASP, DIVX4,5,6 */
VIDEO_FORMAT_REALVIDEO8,
VIDEO_FORMAT_REALVIDEO9,
VIDEO_FORMAT_ON2_VP6,
VIDEO_FORMAT_ON2_VP8,
VIDEO_FORMAT_SORENSON_SPARK,
VIDEO_FORMAT_H263,
VIDEO_FORMAT_H263_ENCODER,
VIDEO_FORMAT_H264_ENCODER,
VIDEO_FORMAT_MPEG4PART2_ENCODER,
VIDEO_FORMAT_AVS,
VIDEO_FORMAT_VIP656,
VIDEO_FORMAT_UNSUPPORTED
} VIDEO_FORMAT;
typedef enum {
VIDEO_SD = 0,
VIDEO_HD,
VIDEO_120x60i,
VIDEO_320x240i,
VIDEO_1440x800i,
VIDEO_360x288i
} VIDEO_DEFINITION;
typedef enum {
VIDEO_FRAME_RATE_23_976 = 0,
VIDEO_FRAME_RATE_24,
VIDEO_FRAME_RATE_25,
VIDEO_FRAME_RATE_29_97,
VIDEO_FRAME_RATE_30,
VIDEO_FRAME_RATE_50,
VIDEO_FRAME_RATE_59_94,
VIDEO_FRAME_RATE_60
} VIDEO_FRAME_RATE;
typedef enum {
DISPLAY_AR_1_1,
DISPLAY_AR_4_3,
DISPLAY_AR_14_9,
DISPLAY_AR_16_9,
DISPLAY_AR_20_9,
DISPLAY_AR_RAW,
} DISPLAY_AR;
typedef enum {
DISPLAY_AR_MODE_PANSCAN = 0,
DISPLAY_AR_MODE_LETTERBOX,
DISPLAY_AR_MODE_NONE,
DISPLAY_AR_MODE_PANSCAN2
} DISPLAY_AR_MODE;
typedef enum {
VIDEO_DB_DR_NEITHER = 0,
VIDEO_DB_ON,
VIDEO_DB_DR_BOTH
} VIDEO_DB_DR;
typedef enum {
VIDEO_PLAY_STILL = 0,
VIDEO_PLAY_CLIP,
VIDEO_PLAY_TRICK,
VIDEO_PLAY_MOTION,
VIDEO_PLAY_MOTION_NO_SYNC
} VIDEO_PLAY_MODE;
typedef enum {
VIDEO_STD_NTSC,
VIDEO_STD_SECAM,
VIDEO_STD_PAL,
VIDEO_STD_480P,
VIDEO_STD_576P,
VIDEO_STD_720P60,
VIDEO_STD_1080I60,
VIDEO_STD_720P50,
VIDEO_STD_1080I50,
VIDEO_STD_1080P30,
VIDEO_STD_1080P24,
VIDEO_STD_1080P25,
VIDEO_STD_1080P50,
VIDEO_STD_1080P60,
VIDEO_STD_AUTO,
VIDEO_STD_MAX
} VIDEO_STD;
/* not used, for dummy functions */
typedef enum {
VIDEO_HDMI_CEC_MODE_OFF = 0,
VIDEO_HDMI_CEC_MODE_TUNER,
VIDEO_HDMI_CEC_MODE_RECORDER
} VIDEO_HDMI_CEC_MODE;
typedef enum
{
VIDEO_CONTROL_BRIGHTNESS = 0,
VIDEO_CONTROL_CONTRAST,
VIDEO_CONTROL_SATURATION,
VIDEO_CONTROL_HUE,
VIDEO_CONTROL_SHARPNESS,
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
} VIDEO_CONTROL;
class cDemux;
class cPlayback;
class VDec;
class cVideo
{
friend class cPlayback;
friend class cDemux;
public:
/* constructor & destructor */
cVideo(int mode, void *, void *, unsigned int unit = 0);
~cVideo(void);
void * GetTVEnc() { return NULL; };
void * GetTVEncSD() { return NULL; };
/* aspect ratio */
int getAspectRatio(void);
void getPictureInfo(int &width, int &height, int &rate);
int setAspectRatio(int aspect, int mode);
/* cropping mode */
int setCroppingMode(void);
/* get play state */
int getPlayState(void);
/* blank on freeze */
int getBlank(void);
int setBlank(int enable);
/* change video play state. Parameters are all unused. */
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
int Stop(bool blank = true);
bool Pause(void);
int GetVideoSystem();
/* set video_system */
int SetVideoSystem(int video_system, bool remember = true);
int SetStreamType(VIDEO_FORMAT type);
void SetSyncMode(AVSYNC_TYPE mode);
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
void SetCECAutoView(bool) { return; };
void SetCECAutoStandby(bool) { return; };
bool ShowPicture(const char * fname);
void StopPicture();
void Standby(unsigned int bOn);
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600);
void SetControl(int, int) { return; };
void setContrast(int val);
void SetVideoMode(analog_mode_t mode);
void SetDBDR(int) { return; };
void SetAudioHandle(void *) { return; };
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
int OpenVBI(int) { return 0; };
int CloseVBI(void) { return 0; };
int StartVBI(unsigned short) { return 0; };
int StopVBI(void) { return 0; };
void SetDemux(cDemux *dmx);
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
private:
VDec *vdec;
void *pdata;
};
#if STB_HAL_VIDEO_HAS_GETSCREENIMAGE
#define SCREENSHOT 1
#endif

View File

@@ -1,50 +0,0 @@
noinst_LTLIBRARIES = libarmbox.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = \
-lOpenThreads \
@AVFORMAT_LIBS@ \
@AVUTIL_LIBS@ \
@AVCODEC_LIBS@ \
@SWRESAMPLE_LIBS@ \
-lpthread -lass -lrt
libarmbox_la_SOURCES = \
hardware_caps.c \
dmx.cpp \
video.cpp \
audio.cpp \
init.cpp \
record.cpp \
hdmi_cec.cpp
if ENABLE_GSTREAMER_10
libarmbox_la_SOURCES += \
playback_gst.cpp
AM_LDFLAGS += \
-lgstreamer-1.0 \
-lgsttag-1.0 \
-lgstmpegts-1.0
else
if BOXMODEL_HISILICON
libarmbox_la_SOURCES += \
playback_hisilicon.cpp
else
libarmbox_la_SOURCES += \
playback_libeplayer3.cpp
AM_CPPFLAGS += \
-I$(top_srcdir)/libeplayer3/include
endif
AM_LDFLAGS += \
-lass
endif
AM_CPPFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS

View File

@@ -1,448 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/dvb/audio.h>
#include <proc_tools.h>
#include "audio_lib.h"
#include "hal_debug.h"
#include <config.h>
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_AUDIO, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_AUDIO, this, args)
#include <linux/soundcard.h>
cAudio * audioDecoder = NULL;
cAudio::cAudio(void *, void *, void *)
{
fd = -1;
clipfd = -1;
mixer_fd = -1;
openDevice();
Muted = false;
}
cAudio::~cAudio(void)
{
closeDevice();
}
void cAudio::openDevice(void)
{
if (fd < 0)
{
if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0)
hal_info("openDevice: open failed (%m)\n");
fcntl(fd, F_SETFD, FD_CLOEXEC);
//do_mute(true, false);
}
else
hal_info("openDevice: already open (fd = %d)\n", fd);
}
void cAudio::closeDevice(void)
{
if (fd > -1) {
close(fd);
fd = -1;
}
if (clipfd > -1) {
close(clipfd);
clipfd = -1;
}
if (mixer_fd > -1) {
close(mixer_fd);
mixer_fd = -1;
}
}
int cAudio::do_mute(bool enable, bool remember)
{
hal_debug("%s(%d, %d)\n", __FUNCTION__, enable, remember);
char str[4];
if (remember)
Muted = enable;
sprintf(str, "%d", Muted);
proc_put("/proc/stb/audio/j1_mute", str, strlen(str));
if (fd > 0)
{
if (ioctl(fd, AUDIO_SET_MUTE, enable) < 0)
perror("AUDIO_SET_MUTE");
}
return 0;
}
int map_volume(const int volume)
{
unsigned char vol = volume;
if (vol > 100)
vol = 100;
// convert to -1dB steps
vol = 63 - vol * 63 / 100;
// now range is 63..0, where 0 is loudest
#if BOXMODEL_VUPLUS_ALL
if (vol == 63)
vol = 255;
#endif
return vol;
}
int cAudio::setVolume(unsigned int left, unsigned int right)
{
hal_info("cAudio::%s(%d, %d)\n", __func__, left, right);
volume = (left + right) / 2;
int v = map_volume(volume);
left = map_volume(volume);
right = map_volume(volume);
audio_mixer_t mixer;
mixer.volume_left = left;
mixer.volume_right = right;
if (fd > 0)
{
if (ioctl(fd, AUDIO_SET_MIXER, &mixer) < 0)
perror("AUDIO_SET_MIXER");
}
char str[4];
sprintf(str, "%d", v);
proc_put("/proc/stb/avs/0/volume", str, strlen(str));
return 0;
}
int cAudio::Start(void)
{
int ret;
ret = ioctl(fd, AUDIO_PLAY);
#if BOXMODEL_HISILICON
ioctl(fd, AUDIO_CONTINUE);
#endif
return ret;
}
int cAudio::Stop(void)
{
return ioctl(fd, AUDIO_STOP);
}
bool cAudio::Pause(bool Pcm)
{
ioctl(fd, Pcm ? AUDIO_PAUSE : AUDIO_CONTINUE, 1);
return true;
}
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
{
hal_debug("%s %d\n", __func__, Mode);
ioctl(fd, AUDIO_SET_AV_SYNC, Mode);
}
#define AUDIO_STREAMTYPE_AC3 0
#define AUDIO_STREAMTYPE_MPEG 1
#define AUDIO_STREAMTYPE_DTS 2
#define AUDIO_STREAMTYPE_AAC 8
#define AUDIO_STREAMTYPE_AACHE 9
void cAudio::SetStreamType(AUDIO_FORMAT type)
{
int bypass = AUDIO_STREAMTYPE_MPEG;
hal_debug("%s %d\n", __FUNCTION__, type);
StreamType = type;
switch (type)
{
case AUDIO_FMT_DD_PLUS:
case AUDIO_FMT_DOLBY_DIGITAL:
bypass = AUDIO_STREAMTYPE_AC3;
break;
case AUDIO_FMT_AAC:
bypass = AUDIO_STREAMTYPE_AAC;
break;
case AUDIO_FMT_AAC_PLUS:
bypass = AUDIO_STREAMTYPE_AACHE;
break;
case AUDIO_FMT_DTS:
bypass = AUDIO_STREAMTYPE_DTS;
break;
default:
break;
}
// Normaly the encoding should be set using AUDIO_SET_ENCODING
// But as we implemented the behavior to bypass (cause of e2) this is correct here
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
hal_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
}
int cAudio::setChannel(int channel)
{
hal_debug("%s %d\n", __FUNCTION__, channel);
return 0;
}
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
{
int fmt;
unsigned int devmask, stereo, usable;
const char *dsp_dev = getenv("DSP_DEVICE");
const char *mix_dev = getenv("MIX_DEVICE");
hal_info("cAudio::%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian);
if (clipfd > -1) {
hal_info("%s: clipfd already opened (%d)\n", __func__, clipfd);
return -1;
}
mixer_num = -1;
mixer_fd = -1;
/* a different DSP device can be given with DSP_DEVICE and MIX_DEVICE
* if this device cannot be opened, we fall back to the internal OSS device
* Example:
* modprobe snd-usb-audio
* export DSP_DEVICE=/dev/sound/dsp2
* export MIX_DEVICE=/dev/sound/mixer2
* neutrino
*/
if ((!dsp_dev) || (access(dsp_dev, W_OK))) {
if (dsp_dev)
hal_info("%s: DSP_DEVICE is set (%s) but cannot be opened,"
" fall back to /dev/dsp\n", __func__, dsp_dev);
dsp_dev = "/dev/dsp";
}
if ((!mix_dev) || (access(mix_dev, W_OK))) {
if (mix_dev)
hal_info("%s: MIX_DEVICE is set (%s) but cannot be opened,"
" fall back to /dev/mixer\n", __func__, dsp_dev);
mix_dev = "/dev/mixer";
}
hal_info("cAudio::%s: dsp_dev %s mix_dev %s\n", __func__, dsp_dev, mix_dev); /* NULL mix_dev is ok */
/* the tdoss dsp driver seems to work only on the second open(). really. */
clipfd = open(dsp_dev, O_WRONLY);
if (clipfd < 0) {
hal_info("%s open %s: %m\n", dsp_dev, __FUNCTION__);
return -1;
}
fcntl(clipfd, F_SETFD, FD_CLOEXEC);
/* no idea if we ever get little_endian == 0 */
if (little_endian)
fmt = AFMT_S16_BE;
else
fmt = AFMT_S16_LE;
if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt))
perror("SNDCTL_DSP_SETFMT");
if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch))
perror("SNDCTL_DSP_CHANNELS");
if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate))
perror("SNDCTL_DSP_SPEED");
#if !BOXMODEL_HD51 && !BOXMODEL_BRE2ZE4K && !BOXMODEL_H7
if (ioctl(clipfd, SNDCTL_DSP_RESET))
perror("SNDCTL_DSP_RESET");
#endif
if (!mix_dev)
return 0;
mixer_fd = open(mix_dev, O_RDWR);
if (mixer_fd < 0) {
hal_info("%s: open mixer %s failed (%m)\n", __func__, mix_dev);
/* not a real error */
return 0;
}
if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
hal_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__);
devmask = 0;
}
if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
hal_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
stereo = 0;
}
usable = devmask & stereo;
if (usable == 0) {
hal_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n",
__func__, devmask, stereo);
close(mixer_fd);
mixer_fd = -1;
return 0; /* TODO: should we treat this as error? */
}
/* __builtin_popcount needs GCC, it counts the set bits... */
if (__builtin_popcount (usable) != 1) {
/* TODO: this code is not yet tested as I have only single-mixer devices... */
hal_info("%s: more than one mixer control: devmask %08x stereo %08x\n"
"%s: querying MIX_NUMBER environment variable...\n",
__func__, devmask, stereo, __func__);
const char *tmp = getenv("MIX_NUMBER");
if (tmp)
mixer_num = atoi(tmp);
hal_info("%s: mixer_num is %d -> device %08x\n",
__func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0);
/* no error checking, you'd better know what you are doing... */
} else {
mixer_num = 0;
while (!(usable & 0x01)) {
mixer_num++;
usable >>= 1;
}
}
setVolume(volume, volume);
return 0;
}
int cAudio::WriteClip(unsigned char *buffer, int size)
{
int ret, __attribute__ ((unused)) count = 1;
// hal_debug("cAudio::%s\n", __FUNCTION__);
if (clipfd < 0) {
hal_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
#if BOXMODEL_HD51 || BOXMODEL_BRE2ZE4K || BOXMODEL_H7
again:
#endif
ret = write(clipfd, buffer, size);
if (ret < 0) {
hal_info("%s: write error (%m)\n", __FUNCTION__);
return ret;
}
#if BOXMODEL_HD51 || BOXMODEL_BRE2ZE4K || BOXMODEL_H7
if (ret != size) {
hal_info("cAudio::%s: difference > to write (%d) != written (%d) try (%d) > reset dsp and restart write\n", __FUNCTION__, size, ret, count);
if (ioctl(clipfd, SNDCTL_DSP_RESET))
perror("SNDCTL_DSP_RESET");
count++;
if (count < 3)
goto again;
}
#endif
return ret;
};
int cAudio::StopClip()
{
hal_info("cAudio::%s\n", __FUNCTION__);
if (clipfd < 0) {
hal_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
#if BOXMODEL_VUPLUS_ARM
ioctl(clipfd, SNDCTL_DSP_RESET);
#endif
close(clipfd);
clipfd = -1;
if (mixer_fd > -1) {
close(mixer_fd);
mixer_fd = -1;
}
setVolume(volume, volume);
return 0;
};
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
{
hal_debug("%s\n", __FUNCTION__);
type = 0;
layer = 0;
freq = 0;
bitrate = 0;
mode = 0;
#if 0
unsigned int atype;
static const int freq_mpg[] = {44100, 48000, 32000, 0};
static const int freq_ac3[] = {48000, 44100, 32000, 0};
scratchl2 i;
if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0)
perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP");
if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0)
perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS");
type = atype;
#if 0
/* this does not work, some of the values are negative?? */
AMPEGStatus A;
memcpy(&A, &i.word00, sizeof(i.word00));
layer = A.audio_mpeg_layer;
mode = A.audio_mpeg_mode;
bitrate = A.audio_mpeg_bitrate;
switch(A.audio_mpeg_frequency)
#endif
/* layer and bitrate are not used anyway... */
layer = 0; //(i.word00 >> 17) & 3;
bitrate = 0; //(i.word00 >> 12) & 3;
switch (type)
{
case 0: /* MPEG */
mode = (i.word00 >> 6) & 3;
freq = freq_mpg[(i.word00 >> 10) & 3];
break;
case 1: /* AC3 */
mode = (i.word00 >> 28) & 7;
freq = freq_ac3[(i.word00 >> 16) & 3];
break;
default:
mode = 0;
freq = 0;
}
//fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode);
#endif
};
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
{
hal_debug("%s\n", __FUNCTION__);
};
void cAudio::SetHdmiDD(bool enable)
{
const char *opt[] = { "downmix", "passthrough" };
hal_debug("%s %d\n", __func__, enable);
proc_put("/proc/stb/audio/ac3", opt[enable], strlen(opt[enable]));
}
void cAudio::SetSpdifDD(bool enable)
{
//using this function for dts passthrough
const char *opt[] = { "downmix", "passthrough" };
hal_debug("%s %d\n", __func__, enable);
proc_put("/proc/stb/audio/dts", opt[enable], strlen(opt[enable]));
}
void cAudio::ScheduleMute(bool On)
{
hal_debug("%s %d\n", __FUNCTION__, On);
}
void cAudio::EnableAnalogOut(bool enable)
{
hal_debug("%s %d\n", __FUNCTION__, enable);
}
#define AUDIO_BYPASS_ON 0
#define AUDIO_BYPASS_OFF 1
void cAudio::setBypassMode(bool disable)
{
int mode = disable ? AUDIO_BYPASS_OFF : AUDIO_BYPASS_ON;
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
hal_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
}

View File

@@ -1,101 +0,0 @@
/* public header file */
#ifndef __AUDIO_LIB_H__
#define __AUDIO_LIB_H__
#include "cs_types.h"
typedef enum
{
AUDIO_SYNC_WITH_PTS,
AUDIO_NO_SYNC,
AUDIO_SYNC_AUDIO_MASTER
} AUDIO_SYNC_MODE;
typedef enum {
HDMI_ENCODED_OFF,
HDMI_ENCODED_AUTO,
HDMI_ENCODED_FORCED
} HDMI_ENCODED_MODE;
typedef enum
{
AUDIO_FMT_AUTO = 0,
AUDIO_FMT_MPEG,
AUDIO_FMT_MP3,
AUDIO_FMT_DOLBY_DIGITAL,
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
AUDIO_FMT_AAC,
AUDIO_FMT_AAC_PLUS,
AUDIO_FMT_DD_PLUS,
AUDIO_FMT_DTS,
AUDIO_FMT_AVS,
AUDIO_FMT_MLP,
AUDIO_FMT_WMA,
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
} AUDIO_FORMAT;
class mixerVolume;
class cAudio
{
friend class cPlayback;
private:
int fd;
bool Muted;
int clipfd; /* for pcm playback */
int mixer_fd; /* if we are using the OSS mixer */
int mixer_num; /* oss mixer to use, if any */
AUDIO_FORMAT StreamType;
AUDIO_SYNC_MODE SyncMode;
bool started;
int volume;
int do_mute(bool enable, bool remember);
void setBypassMode(bool disable);
public:
/* construct & destruct */
cAudio(void *, void *, void *);
~cAudio(void);
void openDevice(void);
void closeDevice(void);
void *GetHandle() { return NULL; };
/* shut up */
int mute(bool remember = true) { return do_mute(true, remember); };
int unmute(bool remember = true) { return do_mute(false, remember); };
/* volume, min = 0, max = 255 */
int setVolume(unsigned int left, unsigned int right);
int getVolume(void) { return volume;}
bool getMuteStatus(void) { return Muted; };
/* start and stop audio */
int Start(void);
int Stop(void);
bool Pause(bool Pcm = true);
void SetStreamType(AUDIO_FORMAT type);
AUDIO_FORMAT GetStreamType(void) { return StreamType; }
void SetSyncMode(AVSYNC_TYPE Mode);
/* select channels */
int setChannel(int channel);
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
int WriteClip(unsigned char * buffer, int size);
int StopClip();
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
bool IsHdmiDDSupported() { return true; };
void SetHdmiDD(bool enable);
void SetSpdifDD(bool enable);
void ScheduleMute(bool On);
void EnableAnalogOut(bool enable);
};
#endif // __AUDIO_LIB_H__

View File

@@ -1,646 +0,0 @@
/*
* cDemux implementation for arm receivers (tested on mutant hd51
* hardware)
*
* derived from libtriple/dmx_td.cpp
*
* (C) 2010-2013 Stefan Seyfried
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <inttypes.h>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <string>
#include <sys/ioctl.h>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>
#include "dmx_hal.h"
#include "hal_debug.h"
#include "video_lib.h"
/* needed for getSTC... */
extern cVideo *videoDecoder;
#define hal_debug(args...) _hal_debug(HAL_DEBUG_DEMUX, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_DEMUX, this, args)
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_DEMUX, NULL, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_DEMUX, NULL, args)
#define hal_info_z(args...) _hal_info(HAL_DEBUG_DEMUX, thiz, args)
#define hal_debug_z(args...) _hal_debug(HAL_DEBUG_DEMUX, thiz, args)
#define dmx_err(_errfmt, _errstr, _revents) do { \
hal_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
} while(0);
cDemux *videoDemux = NULL;
cDemux *audioDemux = NULL;
//cDemux *pcrDemux = NULL;
static const char *DMX_T[] = {
"DMX_INVALID",
"DMX_VIDEO",
"DMX_AUDIO",
"DMX_PES",
"DMX_PSI",
"DMX_PIP",
"DMX_TP",
"DMX_PCR"
};
/* this is the number of different cDemux() units, not the number of
* /dev/dvb/.../demuxX devices! */
#if BOXMODEL_VUULTIMO4K
#define NUM_DEMUX 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define NUM_DEMUX 16
#else
#define NUM_DEMUX 4
#endif
#endif
/* the current source of each cDemux unit */
#if BOXMODEL_VUULTIMO4K
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#else
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0 };
#endif
#endif
/* map the device numbers. */
#if BOXMODEL_VUULTIMO4K
#define NUM_DEMUXDEV 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define NUM_DEMUXDEV 16
#else
#define NUM_DEMUXDEV 8
#endif
#endif
static const char *devname[NUM_DEMUXDEV] = {
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux1",
"/dev/dvb/adapter0/demux2",
"/dev/dvb/adapter0/demux3",
"/dev/dvb/adapter0/demux4",
"/dev/dvb/adapter0/demux5",
"/dev/dvb/adapter0/demux6",
"/dev/dvb/adapter0/demux7"
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
, "/dev/dvb/adapter0/demux8"
, "/dev/dvb/adapter0/demux9"
, "/dev/dvb/adapter0/demux10"
, "/dev/dvb/adapter0/demux11"
, "/dev/dvb/adapter0/demux12"
, "/dev/dvb/adapter0/demux13"
, "/dev/dvb/adapter0/demux14"
, "/dev/dvb/adapter0/demux15"
#if BOXMODEL_VUULTIMO4K
, "/dev/dvb/adapter0/demux16"
, "/dev/dvb/adapter0/demux17"
, "/dev/dvb/adapter0/demux18"
, "/dev/dvb/adapter0/demux19"
, "/dev/dvb/adapter0/demux20"
, "/dev/dvb/adapter0/demux21"
, "/dev/dvb/adapter0/demux22"
, "/dev/dvb/adapter0/demux23"
#endif
#endif
};
/* did we already DMX_SET_SOURCE on that demux device? */
#if BOXMODEL_VUULTIMO4K
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
#else
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false };
#endif
#endif
typedef struct dmx_pdata {
int last_source;
OpenThreads::Mutex *mutex;
} dmx_pdata;
#define P ((dmx_pdata *)pdata)
cDemux::cDemux(int n)
{
if (n < 0 || n >= NUM_DEMUX)
{
hal_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
num = 0;
}
else
num = n;
fd = -1;
pdata = (void *)calloc(1, sizeof(dmx_pdata));
P->last_source = -1;
P->mutex = new OpenThreads::Mutex;
dmx_type = DMX_INVALID;
}
cDemux::~cDemux()
{
hal_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
Close();
/* wait until Read() has released the mutex */
(*P->mutex).lock();
(*P->mutex).unlock();
free(P->mutex);
free(pdata);
pdata = NULL;
}
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
{
if (fd > -1)
hal_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
dmx_type = pes_type;
buffersize = uBufferSize;
/* return code is unchecked anyway... */
return true;
}
static bool _open(cDemux *thiz, int num, int &fd, int &last_source, DMX_CHANNEL_TYPE dmx_type, int buffersize)
{
int flags = O_RDWR|O_CLOEXEC;
int devnum = dmx_source[num];
if (last_source == devnum) {
hal_debug_z("%s #%d: source (%d) did not change\n", __func__, num, last_source);
if (fd > -1)
return true;
}
if (fd > -1) {
/* we changed source -> close and reopen the fd */
hal_debug_z("%s #%d: FD ALREADY OPENED fd = %d lastsource %d devnum %d\n",
__func__, num, fd, last_source, devnum);
close(fd);
}
if (dmx_type != DMX_PSI_CHANNEL)
flags |= O_NONBLOCK;
fd = open(devname[devnum], flags);
if (fd < 0)
{
hal_info_z("%s %s: %m\n", __FUNCTION__, devname[devnum]);
return false;
}
hal_debug_z("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
num, DMX_T[dmx_type], dmx_type, buffersize, fd);
/* this would actually need locking, but the worst that weill happen is, that
* we'll DMX_SET_SOURCE twice per device, so don't bother... */
if (!init[devnum])
{
/* this should not change anything... */
int n = DMX_SOURCE_FRONT0 + devnum;
hal_info_z("%s: setting %s to source %d\n", __func__, devname[devnum], n);
if (ioctl(fd, DMX_SET_SOURCE, &n) < 0)
hal_info_z("%s DMX_SET_SOURCE failed!\n", __func__);
else
init[devnum] = true;
}
if (buffersize == 0)
buffersize = 0xffff; // may or may not be reasonable --martii
if (buffersize > 0)
{
/* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */
if (ioctl(fd, DMX_SET_BUFFER_SIZE, buffersize) < 0)
hal_info_z("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
}
last_source = devnum;
return true;
}
void cDemux::Close(void)
{
hal_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
return;
}
pesfds.clear();
ioctl(fd, DMX_STOP);
close(fd);
fd = -1;
}
bool cDemux::Start(bool)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_START);
return true;
}
bool cDemux::Stop(void)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_STOP);
return true;
}
int cDemux::Read(unsigned char *buff, int len, int timeout)
{
#if 0
if (len != 4095 && timeout != 10)
fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n",
__FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout);
#endif
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __func__, num);
return -1;
}
/* avoid race in destructor: ~cDemux needs to wait until Read() returns */
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(*P->mutex);
int rc;
int to = timeout;
struct pollfd ufds;
ufds.fd = fd;
ufds.events = POLLIN|POLLPRI|POLLERR;
ufds.revents = 0;
/* hack: if the frontend loses and regains lock, the demuxer often will not
* return from read(), so as a "emergency exit" for e.g. NIT scan, set a (long)
* timeout here */
if (dmx_type == DMX_PSI_CHANNEL && timeout <= 0)
to = 60 * 1000;
if (to > 0)
{
retry:
rc = ::poll(&ufds, 1, to);
if (ufds.fd != fd)
{
/* Close() will set fd to -1, this is normal. Everything else is not. */
hal_info("%s:1 ========== fd has changed, %d->%d ==========\n", __func__, ufds.fd, fd);
return -1;
}
if (!rc)
{
if (timeout == 0) /* we took the emergency exit */
{
dmx_err("timed out for timeout=0!, %s", "", 0);
return -1; /* this timeout is an error */
}
return 0; // timeout
}
else if (rc < 0)
{
dmx_err("poll: %s,", strerror(errno), 0)
//hal_info("%s poll: %m\n", __FUNCTION__);
/* happens, when running under gdb... */
if (errno == EINTR)
goto retry;
return -1;
}
#if 0
if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */
{
dmx_err("received %s,", "POLLERR", ufds.revents);
/* this seems to happen sometimes at recording start, without bad effects */
return 0;
}
#endif
if (ufds.revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */
{
dmx_err("received %s,", "POLLHUP", ufds.revents);
return -1;
}
if (!(ufds.revents & POLLIN)) /* we requested POLLIN but did not get it? */
{
dmx_err("received %s, please report!", "POLLIN", ufds.revents);
return 0;
}
}
if (ufds.fd != fd) /* does this ever happen? and if, is it harmful? */
{ /* read(-1,...) will just return EBADF anyway... */
hal_info("%s:2 ========== fd has changed, %d->%d ==========\n", __func__, ufds.fd, fd);
return -1;
}
rc = ::read(fd, buff, len);
//fprintf(stderr, "fd %d ret: %d\n", fd, rc);
if (rc < 0)
dmx_err("read: %s", strerror(errno), 0);
return rc;
}
bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filter,
const unsigned char * const mask, int len, int timeout,
const unsigned char * const negmask)
{
struct dmx_sct_filter_params s_flt;
memset(&s_flt, 0, sizeof(s_flt));
pid = _pid;
_open(this, num, fd, P->last_source, dmx_type, buffersize);
if (len > DMX_FILTER_SIZE)
{
hal_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
len = DMX_FILTER_SIZE;
}
flt = filter[0];
s_flt.pid = pid;
s_flt.timeout = timeout;
memcpy(s_flt.filter.filter, filter, len);
memcpy(s_flt.filter.mask, mask, len);
if (negmask != NULL)
memcpy(s_flt.filter.mode, negmask, len);
s_flt.flags = DMX_IMMEDIATE_START|DMX_CHECK_CRC;
int to = 0;
switch (filter[0])
{
case 0x00: /* program_association_section */
to = 2000;
break;
case 0x01: /* conditional_access_section */
to = 6000;
break;
case 0x02: /* program_map_section */
to = 1500;
break;
case 0x03: /* transport_stream_description_section */
to = 10000;
break;
/* 0x04 - 0x3F: reserved */
case 0x40: /* network_information_section - actual_network */
to = 10000;
break;
case 0x41: /* network_information_section - other_network */
to = 15000;
break;
case 0x42: /* service_description_section - actual_transport_stream */
to = 10000;
break;
/* 0x43 - 0x45: reserved for future use */
case 0x46: /* service_description_section - other_transport_stream */
to = 10000;
break;
/* 0x47 - 0x49: reserved for future use */
case 0x4A: /* bouquet_association_section */
to = 11000;
break;
/* 0x4B - 0x4D: reserved for future use */
case 0x4E: /* event_information_section - actual_transport_stream, present/following */
to = 2000;
break;
case 0x4F: /* event_information_section - other_transport_stream, present/following */
to = 10000;
break;
/* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */
/* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */
case 0x70: /* time_date_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
s_flt.flags |= DMX_ONESHOT;
//s_flt.pid = 0x0014;
to = 30000;
break;
case 0x71: /* running_status_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x72: /* stuffing_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x73: /* time_offset_section */
s_flt.flags |= DMX_ONESHOT;
//s_flt.pid = 0x0014;
to = 30000;
break;
/* 0x74 - 0x7D: reserved for future use */
case 0x7E: /* discontinuity_information_section */
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
to = 0;
break;
case 0x7F: /* selection_information_section */
to = 0;
break;
/* 0x80 - 0x8F: ca_message_section */
/* 0x90 - 0xFE: user defined */
/* 0xFF: reserved */
default:
//return -1;
break;
}
/* the negmask == NULL is a hack: the users of negmask are PMT-update
* and sectionsd EIT-Version change. And they really want no timeout
* if timeout == 0 instead of "default timeout" */
if (timeout == 0 && negmask == NULL)
s_flt.timeout = to;
hal_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
pid, fd, DMX_T[dmx_type], len, s_flt.timeout, s_flt.flags, s_flt.filter.filter[0]);
#if 0
fprintf(stderr,"filt: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.filter[i]); fprintf(stderr, "\n");
fprintf(stderr,"mask: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.mask [i]); fprintf(stderr, "\n");
fprintf(stderr,"mode: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.mode [i]); fprintf(stderr, "\n");
#endif
ioctl (fd, DMX_STOP);
if (ioctl(fd, DMX_SET_FILTER, &s_flt) < 0)
return false;
return true;
}
bool cDemux::pesFilter(const unsigned short _pid)
{
struct dmx_pes_filter_params p_flt;
pid = _pid;
flt = 0;
/* allow PID 0 for web streaming e.g.
* this check originally is from tuxbox cvs but I'm not sure
* what it is good for...
if (pid <= 0x0001 && dmx_type != DMX_PCR_ONLY_CHANNEL)
return false;
*/
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
return false;
hal_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
_open(this, num, fd, P->last_source, dmx_type, buffersize);
memset(&p_flt, 0, sizeof(p_flt));
p_flt.pid = pid;
p_flt.output = DMX_OUT_DECODER;
p_flt.input = DMX_IN_FRONTEND;
p_flt.flags = 0;
switch (dmx_type)
{
case DMX_PCR_ONLY_CHANNEL:
p_flt.pes_type = DMX_PES_PCR;
break;
case DMX_AUDIO_CHANNEL:
p_flt.pes_type = DMX_PES_AUDIO;
break;
case DMX_VIDEO_CHANNEL:
p_flt.pes_type = DMX_PES_VIDEO;
break;
case DMX_PIP_CHANNEL: /* PIP is a special version of DMX_VIDEO_CHANNEL */
p_flt.pes_type = DMX_PES_VIDEO1;
break;
case DMX_PES_CHANNEL:
p_flt.pes_type = DMX_PES_OTHER;
p_flt.output = DMX_OUT_TAP;
break;
case DMX_TP_CHANNEL:
p_flt.pes_type = DMX_PES_OTHER;
p_flt.output = DMX_OUT_TSDEMUX_TAP;
break;
default:
hal_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
return false;
}
return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0);
}
void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/)
{
hal_debug("%s #%d\n", __FUNCTION__, num);
}
void *cDemux::getBuffer()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
void *cDemux::getChannel()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
bool cDemux::addPid(unsigned short Pid)
{
hal_debug("%s: pid 0x%04hx\n", __func__, Pid);
pes_pids pfd;
int ret;
if (dmx_type != DMX_TP_CHANNEL)
{
hal_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return false;
}
_open(this, num, fd, P->last_source, dmx_type, buffersize);
if (fd == -1)
hal_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
pfd.fd = fd; /* dummy */
pfd.pid = Pid;
pesfds.push_back(pfd);
ret = (ioctl(fd, DMX_ADD_PID, &Pid));
if (ret < 0)
hal_info("%s: DMX_ADD_PID (%m) pid=%hx\n", __func__, Pid);
return (ret != -1);
}
void cDemux::removePid(unsigned short Pid)
{
if (dmx_type != DMX_TP_CHANNEL)
{
hal_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return;
}
for (std::vector<pes_pids>::iterator i = pesfds.begin(); i != pesfds.end(); ++i)
{
if ((*i).pid == Pid) {
hal_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
hal_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
pesfds.erase(i);
return; /* TODO: what if the same PID is there multiple times */
}
}
hal_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
}
void cDemux::getSTC(int64_t * STC)
{
/* apparently I can only get the PTS of the video decoder,
* but that's good enough for dvbsub */
hal_debug("%s #%d\n", __func__, num);
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->GetPTS();
*STC = pts;
}
int cDemux::getUnit(void)
{
hal_debug("%s #%d\n", __FUNCTION__, num);
/* just guessed that this is the right thing to do.
right now this is only used by the CA code which is stubbed out
anyway */
return num;
}
bool cDemux::SetSource(int unit, int source)
{
if (unit >= NUM_DEMUX || unit < 0) {
hal_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
return false;
}
hal_debug_c("%s(%d, %d) => %d to %d\n", __func__, unit, source, dmx_source[unit], source);
if (source < 0 || source >= NUM_DEMUXDEV)
hal_info_c("%s(%d, %d) ERROR: source %d out of range!\n", __func__, unit, source, source);
else
dmx_source[unit] = source;
return true;
}
int cDemux::GetSource(int unit)
{
if (unit >= NUM_DEMUX || unit < 0) {
hal_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
return -1;
}
hal_debug_c("%s(%d) => %d\n", __func__, unit, dmx_source[unit]);
return dmx_source[unit];
}

View File

@@ -1,298 +0,0 @@
/*
* determine the capabilities of the hardware.
* part of libstb-hal
*
* (C) 2010-2012 Stefan Seyfried
*
* License: GPL v2 or later
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <hardware_caps.h>
#define FP_DEV "/dev/dbox/oled0"
static int initialized = 0;
static hw_caps_t caps;
hw_caps_t *get_hwcaps(void)
{
if (initialized)
return &caps;
memset(&caps, 0, sizeof(hw_caps_t));
#if BOXMODEL_VUSOLO4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "SOLO4K");
strcpy(caps.boxarch, "BCM7376");
#endif
#if BOXMODEL_VUDUO4K
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "DUO4K");
strcpy(caps.boxarch, "BCM7278");
#endif
#if BOXMODEL_VUDUO4KSE
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "DUO4KSE");
strcpy(caps.boxarch, "BCM7444S");
#endif
#if BOXMODEL_VUULTIMO4K
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 800;
caps.display_yres = 480;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "ULTIMO4K");
strcpy(caps.boxarch, "BCM7444S");
#endif
#if BOXMODEL_VUZERO4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_type = HW_DISPLAY_LED_ONLY;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "ZERO4K");
strcpy(caps.boxarch, "BCM72604");
#endif
#if BOXMODEL_VUUNO4KSE
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 400;
caps.display_yres = 240;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "UNO4KSE");
strcpy(caps.boxarch, "BCM7252S");
#endif
#if BOXMODEL_VUUNO4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_type = HW_DISPLAY_LED_ONLY;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "UNO4K");
strcpy(caps.boxarch, "BCM7252S");
#endif
#if BOXMODEL_HD51
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 16;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AX-Technologies");
strcpy(caps.boxname, "HD51");
strcpy(caps.boxarch, "BCM7251S");
#endif
#if BOXMODEL_HD60
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AX-Technologies");
strcpy(caps.boxname, "HD60");
strcpy(caps.boxarch, "HI3798M");
#endif
#if BOXMODEL_HD61
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.has_button_timer = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AX-Technologies");
strcpy(caps.boxname, "HD61");
strcpy(caps.boxarch, "HI3798M");
#endif
#if BOXMODEL_BRE2ZE4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "WWIO");
strcpy(caps.boxname, "BRE2ZE4K");
strcpy(caps.boxarch, "BCM7251S");
#endif
#if BOXMODEL_H7
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AirDigital");
strcpy(caps.boxname, "Zgemma H7C/S");
strcpy(caps.boxarch, "BCM7251S");
#endif
#if BOXMODEL_OSMIO4K
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 1;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "Edision");
strcpy(caps.boxname, "OS mio 4K");
strcpy(caps.boxarch, "BCM72604");
#endif
#if BOXMODEL_OSMIO4KPLUS
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 128;
caps.display_yres = 64;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "Edision");
strcpy(caps.boxname, "OS mio+ 4K");
strcpy(caps.boxarch, "BCM72604");
#endif
return &caps;
}

View File

@@ -1,834 +0,0 @@
/*
Copyright (C) 2018-2020 TangoCash
License: GPLv2
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <errno.h>
#include <ctype.h>
#include <array>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <linux/input.h>
#include "linux-uapi-cec.h"
#include "hdmi_cec.h"
#include "hdmi_cec_types.h"
#include "hal_debug.h"
#define RED "\x1B[31m"
#define GREEN "\x1B[32m"
#define NORMAL "\x1B[0m"
#define EPOLL_WAIT_TIMEOUT (-1)
#define EPOLL_MAX_EVENTS (1)
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, this, args)
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
#define fop(cmd, args...) ({ \
int _r; \
if (fd >= 0) { \
if ((_r = ::cmd(fd, args)) < 0) \
hal_info(#cmd"(fd, "#args")\n"); \
else \
hal_debug(#cmd"(fd, "#args")\n");\
} \
else { _r = fd; } \
_r; \
})
#define CEC_FALLBACK_DEVICE "/dev/cec0"
#define CEC_HDMIDEV "/dev/hdmi_cec"
#if BOXMODEL_H7
#define RC_DEVICE "/dev/input/event2"
#else
#define RC_DEVICE "/dev/input/event1"
#endif
hdmi_cec * hdmi_cec::hdmi_cec_instance = NULL;
//hack to get an instance before first call
hdmi_cec * CEC = hdmi_cec::getInstance();
hdmi_cec::hdmi_cec()
{
standby_cec_activ = autoview_cec_activ = standby = muted = false;
hdmiFd = -1;
volume = 0;
fallback = false;
tv_off = true;
deviceType = CEC_LOG_ADDR_TYPE_UNREGISTERED;
}
hdmi_cec::~hdmi_cec()
{
if (hdmiFd >= 0)
{
close(hdmiFd);
hdmiFd = -1;
}
}
hdmi_cec* hdmi_cec::getInstance()
{
if (hdmi_cec_instance == NULL)
{
hdmi_cec_instance = new hdmi_cec();
hal_info_c(GREEN "[CEC] new instance created \n" NORMAL);
}
return hdmi_cec_instance;
}
bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
{
physicalAddress[0] = 0x10;
physicalAddress[1] = 0x00;
logicalAddress = 1;
if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF)
{
Stop();
hal_info(GREEN "[CEC] switch off %s\n" NORMAL, __func__);
return false;
}
else
deviceType = _deviceType;
hal_info(GREEN "[CEC] switch on %s\n" NORMAL, __func__);
#if BOXMODEL_VUPLUS_ALL
if (hdmiFd == -1)
{
hdmiFd = ::open(CEC_HDMIDEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (hdmiFd >= 0)
{
::ioctl(hdmiFd, 0); /* flush old messages */
}
}
#endif
if (hdmiFd == -1)
{
hdmiFd = open(CEC_FALLBACK_DEVICE, O_RDWR | O_CLOEXEC);
if (hdmiFd >= 0)
{
fallback = true;
#if BOXMODEL_VUPLUS_ALL
hal_info(RED "[CEC] fallback on %s\n" NORMAL, __func__);
#endif
__u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
struct cec_caps caps = {};
if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0)
hal_info(RED "[CEC] %s: get caps failed (%m)\n" NORMAL, __func__);
if (caps.capabilities & CEC_CAP_LOG_ADDRS)
{
struct cec_log_addrs laddrs = {};
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_info(RED "[CEC] %s: reset log addr failed (%m)\n" NORMAL, __func__);
memset(&laddrs, 0, sizeof(laddrs));
/*
* NOTE: cec_version, osd_name and deviceType should be made configurable,
* CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
* (saves us some startup speed as well, polling for a free logical address
* takes some time)
*/
laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
strcpy(laddrs.osd_name, "neutrino");
laddrs.vendor_id = CEC_VENDOR_ID_NONE;
switch (deviceType)
{
case CEC_LOG_ADDR_TV:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
break;
case CEC_LOG_ADDR_RECORD_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
break;
case CEC_LOG_ADDR_TUNER_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
break;
case CEC_LOG_ADDR_PLAYBACK_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
break;
case CEC_LOG_ADDR_AUDIOSYSTEM:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
break;
default:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
break;
}
laddrs.num_log_addrs++;
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_info(RED "[CEC] %s: et log addr failed (%m)\n" NORMAL, __func__);
}
if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0)
hal_info(RED "[CEC] %s: monitor failed (%m)\n" NORMAL, __func__);
}
}
if (hdmiFd >= 0)
{
GetCECAddressInfo();
if(autoview_cec_activ)
SetCECState(false);
Start();
return true;
}
return false;
}
void hdmi_cec::GetCECAddressInfo()
{
if (hdmiFd >= 0)
{
bool hasdata = false;
struct addressinfo addressinfo;
if (fallback)
{
__u16 phys_addr;
struct cec_log_addrs laddrs = {};
::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
addressinfo.physical[1] = phys_addr & 0xff;
::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
addressinfo.logical = laddrs.log_addr[0];
switch (laddrs.log_addr_type[0])
{
case CEC_LOG_ADDR_TYPE_TV:
addressinfo.type = CEC_LOG_ADDR_TV;
break;
case CEC_LOG_ADDR_TYPE_RECORD:
addressinfo.type = CEC_LOG_ADDR_RECORD_1;
break;
case CEC_LOG_ADDR_TYPE_TUNER:
addressinfo.type = CEC_LOG_ADDR_TUNER_1;
break;
case CEC_LOG_ADDR_TYPE_PLAYBACK:
addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
break;
case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
break;
case CEC_LOG_ADDR_TYPE_UNREGISTERED:
default:
addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
break;
}
hasdata = true;
}
else
{
if (::ioctl(hdmiFd, 1, &addressinfo) >= 0)
{
hasdata = true;
}
}
if (hasdata)
{
deviceType = addressinfo.type;
logicalAddress = addressinfo.logical;
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
{
hal_info(GREEN "[CEC] %s: detected physical address change: %02X%02X --> %02X%02X\n" NORMAL, __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
ReportPhysicalAddress();
}
}
}
}
void hdmi_cec::ReportPhysicalAddress()
{
struct cec_message txmessage;
txmessage.initiator = logicalAddress;
txmessage.destination = CEC_LOG_ADDR_BROADCAST;
txmessage.data[0] = CEC_MSG_REPORT_PHYSICAL_ADDR;
txmessage.data[1] = physicalAddress[0];
txmessage.data[2] = physicalAddress[1];
txmessage.data[3] = deviceType;
txmessage.length = 4;
SendCECMessage(txmessage);
}
void hdmi_cec::SendCECMessage(struct cec_message &txmessage, int sleeptime)
{
if (hdmiFd >= 0)
{
char str[txmessage.length*6];
for (int i = 0; i < txmessage.length; i++)
{
sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]);
}
hal_info(GREEN "[CEC] send message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n" NORMAL,ToString((cec_logical_address)txmessage.initiator), txmessage.destination == 0xf ? "all" : ToString((cec_logical_address)txmessage.destination), txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
if (fallback)
{
struct cec_msg msg;
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
msg.len = txmessage.length + 1;
ioctl(hdmiFd, CEC_TRANSMIT, &msg);
}
else
{
struct cec_message_fb message;
message.address = txmessage.destination;
message.length = txmessage.length;
memcpy(&message.data, txmessage.data, txmessage.length);
::write(hdmiFd, &message, 2 + message.length);
}
usleep(sleeptime * 10000);
}
}
void hdmi_cec::SetCECAutoStandby(bool state)
{
standby_cec_activ = state;
}
void hdmi_cec::SetCECAutoView(bool state)
{
autoview_cec_activ = state;
}
void hdmi_cec::SetCECState(bool state)
{
struct cec_message message;
standby = state;
if ((standby_cec_activ) && state)
{
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_STANDBY;
message.length = 1;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
}
if ((autoview_cec_activ) && !state)
{
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GET_CEC_VERSION;
message.length = 1;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
#if BOXMODEL_VUPLUS_ALL
int cnt = 0;
while (tv_off && (cnt < 5))
{
#endif
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
message.length = 1;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
#if BOXMODEL_VUPLUS_ALL
cnt++;
}
#endif
message.initiator = logicalAddress;
message.destination = CEC_LOG_ADDR_BROADCAST;
message.data[0] = CEC_MSG_ACTIVE_SOURCE;
message.data[1] = physicalAddress[0];
message.data[2] = physicalAddress[1];
message.length = 3;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_LOG_ADDR_BROADCAST;
message.data[0] = CEC_OPCODE_SET_OSD_NAME;
message.data[1] = 0x6e; //n
message.data[2] = 0x65; //e
message.data[3] = 0x75; //u
message.data[4] = 0x74; //t
message.data[5] = 0x72; //r
message.data[6] = 0x69; //i
message.data[7] = 0x6e; //n
message.data[8] = 0x6f; //o
message.length = 9;
SendCECMessage(message);
request_audio_status();
}
}
long hdmi_cec::translateKey(unsigned char code)
{
long key = 0;
switch (code)
{
case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL:
key = KEY_MENU;
break;
case CEC_USER_CONTROL_CODE_NUMBER0:
key = KEY_0;
break;
case CEC_USER_CONTROL_CODE_NUMBER1:
key = KEY_1;
break;
case CEC_USER_CONTROL_CODE_NUMBER2:
key = KEY_2;
break;
case CEC_USER_CONTROL_CODE_NUMBER3:
key = KEY_3;
break;
case CEC_USER_CONTROL_CODE_NUMBER4:
key = KEY_4;
break;
case CEC_USER_CONTROL_CODE_NUMBER5:
key = KEY_5;
break;
case CEC_USER_CONTROL_CODE_NUMBER6:
key = KEY_6;
break;
case CEC_USER_CONTROL_CODE_NUMBER7:
key = KEY_7;
break;
case CEC_USER_CONTROL_CODE_NUMBER8:
key = KEY_8;
break;
case CEC_USER_CONTROL_CODE_NUMBER9:
key = KEY_9;
break;
case CEC_USER_CONTROL_CODE_CHANNEL_UP:
key = KEY_CHANNELUP;
break;
case CEC_USER_CONTROL_CODE_CHANNEL_DOWN:
key = KEY_CHANNELDOWN;
break;
case CEC_USER_CONTROL_CODE_PLAY:
key = KEY_PLAY;
break;
case CEC_USER_CONTROL_CODE_STOP:
key = KEY_STOP;
break;
case CEC_USER_CONTROL_CODE_PAUSE:
key = KEY_PAUSE;
break;
case CEC_USER_CONTROL_CODE_RECORD:
key = KEY_RECORD;
break;
case CEC_USER_CONTROL_CODE_REWIND:
key = KEY_REWIND;
break;
case CEC_USER_CONTROL_CODE_FAST_FORWARD:
key = KEY_FASTFORWARD;
break;
case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE:
key = KEY_INFO;
break;
case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING:
key = KEY_PROGRAM;
break;
case CEC_USER_CONTROL_CODE_PLAY_FUNCTION:
key = KEY_PLAY;
break;
case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION:
key = KEY_PLAYPAUSE;
break;
case CEC_USER_CONTROL_CODE_RECORD_FUNCTION:
key = KEY_RECORD;
break;
case CEC_USER_CONTROL_CODE_STOP_FUNCTION:
key = KEY_STOP;
break;
case CEC_USER_CONTROL_CODE_SELECT:
key = KEY_OK;
break;
case CEC_USER_CONTROL_CODE_LEFT:
key = KEY_LEFT;
break;
case CEC_USER_CONTROL_CODE_RIGHT:
key = KEY_RIGHT;
break;
case CEC_USER_CONTROL_CODE_UP:
key = KEY_UP;
break;
case CEC_USER_CONTROL_CODE_DOWN:
key = KEY_DOWN;
break;
case CEC_USER_CONTROL_CODE_EXIT:
key = KEY_EXIT;
break;
case CEC_USER_CONTROL_CODE_F2_RED:
key = KEY_RED;
break;
case CEC_USER_CONTROL_CODE_F3_GREEN:
key = KEY_GREEN;
break;
case CEC_USER_CONTROL_CODE_F4_YELLOW:
key = KEY_YELLOW;
break;
case CEC_USER_CONTROL_CODE_F1_BLUE:
key = KEY_BLUE;
break;
default:
key = KEY_MENU;
break;
}
return key;
}
bool hdmi_cec::Start()
{
if (running)
return false;
if (hdmiFd == -1)
return false;
running = true;
OpenThreads::Thread::setSchedulePriority(THREAD_PRIORITY_MIN);
return (OpenThreads::Thread::start() == 0);
}
bool hdmi_cec::Stop()
{
if (!running)
return false;
running = false;
OpenThreads::Thread::cancel();
if (hdmiFd >= 0)
{
close(hdmiFd);
hdmiFd = -1;
}
return (OpenThreads::Thread::join() == 0);
}
void hdmi_cec::run()
{
OpenThreads::Thread::setCancelModeAsynchronous();
int n;
int epollfd = epoll_create1(0);
struct epoll_event event;
event.data.fd = hdmiFd;
event.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_ADD, hdmiFd, &event);
std::array<struct epoll_event, EPOLL_MAX_EVENTS> events;
while (running)
{
n = epoll_wait(epollfd, events.data(), EPOLL_MAX_EVENTS, EPOLL_WAIT_TIMEOUT);
for (int i = 0; i < n; ++i)
{
if (events[i].events & EPOLLIN)
Receive(events[i].events);
}
}
}
void hdmi_cec::Receive(int what)
{
if (what & EPOLLIN)
{
bool hasdata = false;
struct cec_message rxmessage;
struct cec_message txmessage;
if (fallback)
{
struct cec_msg msg;
if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0)
{
rxmessage.length = msg.len - 1;
rxmessage.initiator = cec_msg_initiator(&msg);
rxmessage.destination = cec_msg_destination(&msg);
rxmessage.opcode = cec_msg_opcode(&msg);
memcpy(&rxmessage.data, &msg.msg[1], rxmessage.length);
hasdata = true;
}
}
else
{
struct cec_message_fb rx_message;
if (::read(hdmiFd, &rx_message, 2) == 2)
{
if (::read(hdmiFd, &rx_message.data, rx_message.length) == rx_message.length)
{
rxmessage.length = rx_message.length;
rxmessage.initiator = rx_message.address;
rxmessage.destination = logicalAddress;
rxmessage.opcode = rx_message.data[0];
memcpy(&rxmessage.data, rx_message.data, rx_message.length);
hasdata = true;
}
}
}
if (hasdata)
{
bool keypressed = false;
static unsigned char pressedkey = 0;
char str[rxmessage.length*6];
for (int i = 0; i < rxmessage.length; i++)
{
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
}
hal_info(GREEN "[CEC] received message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n" NORMAL,ToString((cec_logical_address)rxmessage.initiator), rxmessage.destination == 0xf ? "all" : ToString((cec_logical_address)rxmessage.destination), rxmessage.initiator, rxmessage.destination, ToString((cec_opcode)rxmessage.opcode), str);
switch (rxmessage.opcode)
{
//case CEC_OPCODE_ACTIVE_SOURCE:
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
{
txmessage.destination = CEC_LOG_ADDR_BROADCAST; //rxmessage.initiator;
txmessage.initiator = logicalAddress; //rxmessage.destination;
txmessage.data[0] = CEC_MSG_ACTIVE_SOURCE;
txmessage.data[1] = physicalAddress[0];
txmessage.data[2] = physicalAddress[1];
txmessage.length = 3;
if (!standby)
SendCECMessage(txmessage);
}
case CEC_OPCODE_REPORT_AUDIO_STATUS:
{
muted = ((rxmessage.data[1] & 0x80) == 0x80);
volume = ((rxmessage.data[1] & 0x7F) / 127.0) * 100.0;
if (muted)
hal_info(GREEN "[CEC] %s volume muted\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator));
else
hal_info(GREEN "[CEC] %s volume %d \n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), volume);
break;
}
case CEC_OPCODE_DEVICE_VENDOR_ID:
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
{
uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) +
((uint64_t)rxmessage.data[2] << 8) +
(uint64_t)rxmessage.data[3];
hal_info(GREEN "[CEC] decoded message '%s' (%s)\n" NORMAL, ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId));
break;
}
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
{
txmessage.destination = rxmessage.initiator;
txmessage.initiator = rxmessage.destination;
txmessage.data[0] = GetResponseOpcode((cec_opcode)rxmessage.opcode);
txmessage.data[1] = standby ? CEC_POWER_STATUS_STANDBY : CEC_POWER_STATUS_ON;
txmessage.length = 2;
SendCECMessage(txmessage);
break;
}
case CEC_OPCODE_REPORT_POWER_STATUS:
{
if ((rxmessage.data[1] == CEC_POWER_STATUS_ON) || (rxmessage.data[1] == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON))
{
hal_info(GREEN "[CEC] %s reporting state on (%d)\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]);
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = false;
} else {
hal_info(GREEN "[CEC] %s reporting state off (%d)\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]);
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = true;
}
break;
}
case CEC_OPCODE_STANDBY:
{
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = true;
break;
}
case CEC_OPCODE_USER_CONTROL_PRESSED: /* key pressed */
{
keypressed = true;
pressedkey = rxmessage.data[1];
} // fall through
case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */
{
long code = translateKey(pressedkey);
hal_info(GREEN "[CEC] decoded key %s (%ld)\n" NORMAL,ToString((cec_user_control_code)pressedkey), code);
handleCode(code,keypressed);
break;
}
}
}
}
}
void hdmi_cec::handleCode(long code, bool keypressed)
{
int evd = open(RC_DEVICE, O_RDWR);
if (evd < 0)
{
hal_info(RED "[CEC] opening " RC_DEVICE " failed" NORMAL);
return;
}
if (keypressed)
{
if (rc_send(evd, code, CEC_KEY_PRESSED) < 0)
{
hal_info(RED "[CEC] writing 'KEY_PRESSED' event failed" NORMAL);
close(evd);
return;
}
rc_sync(evd);
}
else
{
if (rc_send(evd, code, CEC_KEY_RELEASED) < 0)
{
hal_info(RED "[CEC] writing 'KEY_RELEASED' event failed" NORMAL);
close(evd);
return;
}
rc_sync(evd);
}
close(evd);
}
int hdmi_cec::rc_send(int fd, unsigned int code, unsigned int value)
{
struct input_event ev;
ev.type = EV_KEY;
ev.code = code;
ev.value = value;
return write(fd, &ev, sizeof(ev));
}
void hdmi_cec::rc_sync(int fd)
{
struct input_event ev;
gettimeofday(&ev.time, NULL);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(fd, &ev, sizeof(ev));
}
void hdmi_cec::send_key(unsigned char key, unsigned char destination)
{
struct cec_message txmessage;
txmessage.destination = destination;
txmessage.initiator = logicalAddress;
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_PRESSED;
txmessage.data[1] = key;
txmessage.length = 2;
SendCECMessage(txmessage, 1);
txmessage.destination = destination;
txmessage.initiator = logicalAddress;
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_RELEASE;
txmessage.length = 1;
SendCECMessage(txmessage, 0);
}
void hdmi_cec::request_audio_status()
{
struct cec_message txmessage;
txmessage.destination = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
txmessage.initiator = logicalAddress;
txmessage.data[0] = CEC_OPCODE_GIVE_AUDIO_STATUS;
txmessage.length = 1;
SendCECMessage(txmessage, 0);
}
void hdmi_cec::vol_up()
{
send_key(CEC_USER_CONTROL_CODE_VOLUME_UP, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
request_audio_status();
}
void hdmi_cec::vol_down()
{
send_key(CEC_USER_CONTROL_CODE_VOLUME_DOWN, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
request_audio_status();
}
void hdmi_cec::toggle_mute()
{
send_key(CEC_USER_CONTROL_CODE_MUTE, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
request_audio_status();
}

View File

@@ -1,108 +0,0 @@
#ifndef __HDMI_CEC_H__
#define __HDMI_CEC_H__
/*
Copyright (C) 2018-2020 TangoCash
License: GPLv2
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
#include "video_lib.h"
struct cec_message
{
unsigned char initiator;
unsigned char destination;
unsigned char opcode;
unsigned char data[256];
unsigned char length;
} __attribute__((packed));
struct cec_message_fb
{
unsigned char address;
unsigned char length;
unsigned char data[256];
} __attribute__((packed));
struct addressinfo
{
unsigned char logical;
unsigned char physical[2];
unsigned char type;
};
enum
{
CEC_KEY_RELEASED = 0,
CEC_KEY_PRESSED,
CEC_KEY_AUTOREPEAT
};
class hdmi_cec : public OpenThreads::Thread
{
private:
hdmi_cec();
static hdmi_cec *hdmi_cec_instance;
void run();
bool Start();
bool Stop();
void Receive(int what);
unsigned char physicalAddress[2];
bool autoview_cec_activ;
unsigned char deviceType, logicalAddress;
int hdmiFd;
long translateKey(unsigned char code);
void handleCode(long code, bool keypressed);
int rc_send(int fd, unsigned int code, unsigned int value);
void rc_sync(int fd);
bool standby;
void send_key(unsigned char key, unsigned char destination);
void request_audio_status();
bool muted;
int volume;
bool fallback;
bool tv_off;
protected:
bool running;
public:
~hdmi_cec();
static hdmi_cec* getInstance();
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
void SetCECAutoView(bool);
void SetCECAutoStandby(bool);
void GetCECAddressInfo();
void SendCECMessage(struct cec_message &message, int sleeptime = 10);
void SetCECState(bool state);
void ReportPhysicalAddress();
bool standby_cec_activ;
void vol_up();
void vol_down();
void toggle_mute();
int GetVolume()
{
return volume;
};
bool isMuted()
{
return muted;
};
};
#endif // __HDMI_CEC_H__

View File

@@ -1,713 +0,0 @@
#ifndef __HDMI_CEC_TYPES_H__
#define __HDMI_CEC_TYPES_H__
typedef enum cec_vendor_id
{
CEC_VENDOR_TOSHIBA = 0x000039,
CEC_VENDOR_SAMSUNG = 0x0000F0,
CEC_VENDOR_DENON = 0x0005CD,
CEC_VENDOR_MARANTZ = 0x000678,
CEC_VENDOR_LOEWE = 0x000982,
CEC_VENDOR_ONKYO = 0x0009B0,
CEC_VENDOR_MEDION = 0x000CB8,
CEC_VENDOR_TOSHIBA2 = 0x000CE7,
CEC_VENDOR_PULSE_EIGHT = 0x001582,
CEC_VENDOR_HARMAN_KARDON2 = 0x001950,
CEC_VENDOR_GOOGLE = 0x001A11,
CEC_VENDOR_AKAI = 0x0020C7,
CEC_VENDOR_AOC = 0x002467,
CEC_VENDOR_PANASONIC = 0x008045,
CEC_VENDOR_PHILIPS = 0x00903E,
CEC_VENDOR_DAEWOO = 0x009053,
CEC_VENDOR_YAMAHA = 0x00A0DE,
CEC_VENDOR_GRUNDIG = 0x00D0D5,
CEC_VENDOR_PIONEER = 0x00E036,
CEC_VENDOR_LG = 0x00E091,
CEC_VENDOR_SHARP = 0x08001F,
CEC_VENDOR_SONY = 0x080046,
CEC_VENDOR_BROADCOM = 0x18C086,
CEC_VENDOR_SHARP2 = 0x534850,
CEC_VENDOR_VIZIO = 0x6B746D,
CEC_VENDOR_BENQ = 0x8065E9,
CEC_VENDOR_HARMAN_KARDON = 0x9C645E,
CEC_VENDOR_UNKNOWN = 0
} cec_vendor_id;
typedef enum cec_user_control_code
{
CEC_USER_CONTROL_CODE_SELECT = 0x00,
CEC_USER_CONTROL_CODE_UP = 0x01,
CEC_USER_CONTROL_CODE_DOWN = 0x02,
CEC_USER_CONTROL_CODE_LEFT = 0x03,
CEC_USER_CONTROL_CODE_RIGHT = 0x04,
CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05,
CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06,
CEC_USER_CONTROL_CODE_LEFT_UP = 0x07,
CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08,
CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09,
CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A,
CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B,
CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C,
CEC_USER_CONTROL_CODE_EXIT = 0x0D,
// reserved: 0x0E, 0x0F
CEC_USER_CONTROL_CODE_TOP_MENU = 0x10,
CEC_USER_CONTROL_CODE_DVD_MENU = 0x11,
// reserved: 0x12 ... 0x1C
CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE = 0x1D,
CEC_USER_CONTROL_CODE_NUMBER11 = 0x1E,
CEC_USER_CONTROL_CODE_NUMBER12 = 0x1F,
CEC_USER_CONTROL_CODE_NUMBER0 = 0x20,
CEC_USER_CONTROL_CODE_NUMBER1 = 0x21,
CEC_USER_CONTROL_CODE_NUMBER2 = 0x22,
CEC_USER_CONTROL_CODE_NUMBER3 = 0x23,
CEC_USER_CONTROL_CODE_NUMBER4 = 0x24,
CEC_USER_CONTROL_CODE_NUMBER5 = 0x25,
CEC_USER_CONTROL_CODE_NUMBER6 = 0x26,
CEC_USER_CONTROL_CODE_NUMBER7 = 0x27,
CEC_USER_CONTROL_CODE_NUMBER8 = 0x28,
CEC_USER_CONTROL_CODE_NUMBER9 = 0x29,
CEC_USER_CONTROL_CODE_DOT = 0x2A,
CEC_USER_CONTROL_CODE_ENTER = 0x2B,
CEC_USER_CONTROL_CODE_CLEAR = 0x2C,
CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F,
CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30,
CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31,
CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32,
CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33,
CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34,
CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35,
CEC_USER_CONTROL_CODE_HELP = 0x36,
CEC_USER_CONTROL_CODE_PAGE_UP = 0x37,
CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38,
// reserved: 0x39 ... 0x3F
CEC_USER_CONTROL_CODE_POWER = 0x40,
CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41,
CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42,
CEC_USER_CONTROL_CODE_MUTE = 0x43,
CEC_USER_CONTROL_CODE_PLAY = 0x44,
CEC_USER_CONTROL_CODE_STOP = 0x45,
CEC_USER_CONTROL_CODE_PAUSE = 0x46,
CEC_USER_CONTROL_CODE_RECORD = 0x47,
CEC_USER_CONTROL_CODE_REWIND = 0x48,
CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49,
CEC_USER_CONTROL_CODE_EJECT = 0x4A,
CEC_USER_CONTROL_CODE_FORWARD = 0x4B,
CEC_USER_CONTROL_CODE_BACKWARD = 0x4C,
CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D,
CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E,
// reserved: 0x4F
CEC_USER_CONTROL_CODE_ANGLE = 0x50,
CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51,
CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52,
CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53,
CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54,
CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55,
CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE = 0x56,
CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION = 0x57,
// reserved: 0x58 ... 0x5F
CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60,
CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61,
CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62,
CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63,
CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64,
CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65,
CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66,
CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67,
CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68,
CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69,
CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A,
CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B,
CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C,
CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D,
// reserved: 0x6E ... 0x70
CEC_USER_CONTROL_CODE_F1_BLUE = 0x71,
CEC_USER_CONTROL_CODE_F2_RED = 0X72,
CEC_USER_CONTROL_CODE_F3_GREEN = 0x73,
CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74,
CEC_USER_CONTROL_CODE_F5 = 0x75,
CEC_USER_CONTROL_CODE_DATA = 0x76,
// reserved: 0x77 ... 0xFF
CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, // return (Samsung)
CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, // channels list (Samsung)
CEC_USER_CONTROL_CODE_MAX = 0x96,
CEC_USER_CONTROL_CODE_UNKNOWN = 0xFF
} cec_user_control_code;
typedef enum cec_opcode
{
CEC_OPCODE_ACTIVE_SOURCE = 0x82,
CEC_OPCODE_IMAGE_VIEW_ON = 0x04,
CEC_OPCODE_TEXT_VIEW_ON = 0x0D,
CEC_OPCODE_INACTIVE_SOURCE = 0x9D,
CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85,
CEC_OPCODE_ROUTING_CHANGE = 0x80,
CEC_OPCODE_ROUTING_INFORMATION = 0x81,
CEC_OPCODE_SET_STREAM_PATH = 0x86,
CEC_OPCODE_STANDBY = 0x36,
CEC_OPCODE_RECORD_OFF = 0x0B,
CEC_OPCODE_RECORD_ON = 0x09,
CEC_OPCODE_RECORD_STATUS = 0x0A,
CEC_OPCODE_RECORD_TV_SCREEN = 0x0F,
CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33,
CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99,
CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1,
CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34,
CEC_OPCODE_SET_DIGITAL_TIMER = 0x97,
CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2,
CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67,
CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43,
CEC_OPCODE_TIMER_STATUS = 0x35,
CEC_OPCODE_CEC_VERSION = 0x9E,
CEC_OPCODE_GET_CEC_VERSION = 0x9F,
CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83,
CEC_OPCODE_GET_MENU_LANGUAGE = 0x91,
CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84,
CEC_OPCODE_SET_MENU_LANGUAGE = 0x32,
CEC_OPCODE_DECK_CONTROL = 0x42,
CEC_OPCODE_DECK_STATUS = 0x1B,
CEC_OPCODE_GIVE_DECK_STATUS = 0x1A,
CEC_OPCODE_PLAY = 0x41,
CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08,
CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92,
CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93,
CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07,
CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06,
CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05,
CEC_OPCODE_DEVICE_VENDOR_ID = 0x87,
CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C,
CEC_OPCODE_VENDOR_COMMAND = 0x89,
CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0,
CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B,
CEC_OPCODE_SET_OSD_STRING = 0x64,
CEC_OPCODE_GIVE_OSD_NAME = 0x46,
CEC_OPCODE_SET_OSD_NAME = 0x47,
CEC_OPCODE_MENU_REQUEST = 0x8D,
CEC_OPCODE_MENU_STATUS = 0x8E,
CEC_OPCODE_USER_CONTROL_PRESSED = 0x44,
CEC_OPCODE_USER_CONTROL_RELEASE = 0x45,
CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F,
CEC_OPCODE_REPORT_POWER_STATUS = 0x90,
CEC_OPCODE_FEATURE_ABORT = 0x00,
CEC_OPCODE_ABORT = 0xFF,
CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71,
CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A,
CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
CEC_OPCODE_SET_AUDIO_RATE = 0x9A,
/* CEC 1.4 */
CEC_OPCODE_START_ARC = 0xC0,
CEC_OPCODE_REPORT_ARC_STARTED = 0xC1,
CEC_OPCODE_REPORT_ARC_ENDED = 0xC2,
CEC_OPCODE_REQUEST_ARC_START = 0xC3,
CEC_OPCODE_REQUEST_ARC_END = 0xC4,
CEC_OPCODE_END_ARC = 0xC5,
CEC_OPCODE_CDC = 0xF8,
/* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
CEC_OPCODE_NONE = 0xFD
} cec_opcode;
typedef enum cec_logical_address
{
CECDEVICE_UNKNOWN = -1, //not a valid logical address
CECDEVICE_TV = 0,
CECDEVICE_RECORDINGDEVICE1 = 1,
CECDEVICE_RECORDINGDEVICE2 = 2,
CECDEVICE_TUNER1 = 3,
CECDEVICE_PLAYBACKDEVICE1 = 4,
CECDEVICE_AUDIOSYSTEM = 5,
CECDEVICE_TUNER2 = 6,
CECDEVICE_TUNER3 = 7,
CECDEVICE_PLAYBACKDEVICE2 = 8,
CECDEVICE_RECORDINGDEVICE3 = 9,
CECDEVICE_TUNER4 = 10,
CECDEVICE_PLAYBACKDEVICE3 = 11,
CECDEVICE_RESERVED1 = 12,
CECDEVICE_RESERVED2 = 13,
CECDEVICE_FREEUSE = 14,
CECDEVICE_UNREGISTERED = 15,
CECDEVICE_BROADCAST = 15
} cec_logical_address;
typedef enum cec_power_status
{
CEC_POWER_STATUS_ON = 0x00,
CEC_POWER_STATUS_STANDBY = 0x01,
CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON = 0x02,
CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY = 0x03,
CEC_POWER_STATUS_UNKNOWN = 0x99
} cec_power_status;
static const char *ToString(const cec_opcode opcode)
{
switch (opcode)
{
case CEC_OPCODE_ACTIVE_SOURCE:
return "active source";
case CEC_OPCODE_IMAGE_VIEW_ON:
return "image view on";
case CEC_OPCODE_TEXT_VIEW_ON:
return "text view on";
case CEC_OPCODE_INACTIVE_SOURCE:
return "inactive source";
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
return "request active source";
case CEC_OPCODE_ROUTING_CHANGE:
return "routing change";
case CEC_OPCODE_ROUTING_INFORMATION:
return "routing information";
case CEC_OPCODE_SET_STREAM_PATH:
return "set stream path";
case CEC_OPCODE_STANDBY:
return "standby";
case CEC_OPCODE_RECORD_OFF:
return "record off";
case CEC_OPCODE_RECORD_ON:
return "record on";
case CEC_OPCODE_RECORD_STATUS:
return "record status";
case CEC_OPCODE_RECORD_TV_SCREEN:
return "record tv screen";
case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
return "clear analogue timer";
case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
return "clear digital timer";
case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
return "clear external timer";
case CEC_OPCODE_SET_ANALOGUE_TIMER:
return "set analogue timer";
case CEC_OPCODE_SET_DIGITAL_TIMER:
return "set digital timer";
case CEC_OPCODE_SET_EXTERNAL_TIMER:
return "set external timer";
case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
return "set timer program title";
case CEC_OPCODE_TIMER_CLEARED_STATUS:
return "timer cleared status";
case CEC_OPCODE_TIMER_STATUS:
return "timer status";
case CEC_OPCODE_CEC_VERSION:
return "cec version";
case CEC_OPCODE_GET_CEC_VERSION:
return "get cec version";
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
return "give physical address";
case CEC_OPCODE_GET_MENU_LANGUAGE:
return "get menu language";
case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
return "report physical address";
case CEC_OPCODE_SET_MENU_LANGUAGE:
return "set menu language";
case CEC_OPCODE_DECK_CONTROL:
return "deck control";
case CEC_OPCODE_DECK_STATUS:
return "deck status";
case CEC_OPCODE_GIVE_DECK_STATUS:
return "give deck status";
case CEC_OPCODE_PLAY:
return "play";
case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
return "give tuner status";
case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
return "select analogue service";
case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
return "set digital service";
case CEC_OPCODE_TUNER_DEVICE_STATUS:
return "tuner device status";
case CEC_OPCODE_TUNER_STEP_DECREMENT:
return "tuner step decrement";
case CEC_OPCODE_TUNER_STEP_INCREMENT:
return "tuner step increment";
case CEC_OPCODE_DEVICE_VENDOR_ID:
return "device vendor id";
case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
return "give device vendor id";
case CEC_OPCODE_VENDOR_COMMAND:
return "vendor command";
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
return "vendor command with id";
case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
return "vendor remote button down";
case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
return "vendor remote button up";
case CEC_OPCODE_SET_OSD_STRING:
return "set osd string";
case CEC_OPCODE_GIVE_OSD_NAME:
return "give osd name";
case CEC_OPCODE_SET_OSD_NAME:
return "set osd name";
case CEC_OPCODE_MENU_REQUEST:
return "menu request";
case CEC_OPCODE_MENU_STATUS:
return "menu status";
case CEC_OPCODE_USER_CONTROL_PRESSED:
return "user control pressed";
case CEC_OPCODE_USER_CONTROL_RELEASE:
return "user control release";
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
return "give device power status";
case CEC_OPCODE_REPORT_POWER_STATUS:
return "report power status";
case CEC_OPCODE_FEATURE_ABORT:
return "feature abort";
case CEC_OPCODE_ABORT:
return "abort";
case CEC_OPCODE_GIVE_AUDIO_STATUS:
return "give audio status";
case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
return "give audio mode status";
case CEC_OPCODE_REPORT_AUDIO_STATUS:
return "report audio status";
case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
return "set system audio mode";
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
return "system audio mode request";
case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
return "system audio mode status";
case CEC_OPCODE_SET_AUDIO_RATE:
return "set audio rate";
case CEC_OPCODE_START_ARC:
return "start ARC";
case CEC_OPCODE_REPORT_ARC_STARTED:
return "report ARC started";
case CEC_OPCODE_REPORT_ARC_ENDED:
return "report ARC ended";
case CEC_OPCODE_REQUEST_ARC_START:
return "request ARC start";
case CEC_OPCODE_REQUEST_ARC_END:
return "request ARC end";
case CEC_OPCODE_END_ARC:
return "end ARC";
case CEC_OPCODE_CDC:
return "CDC";
case CEC_OPCODE_NONE:
return "poll";
default:
return "UNKNOWN";
}
}
static const char *ToString(const cec_vendor_id vendor)
{
switch (vendor)
{
case CEC_VENDOR_SAMSUNG:
return "Samsung";
case CEC_VENDOR_LG:
return "LG";
case CEC_VENDOR_PANASONIC:
return "Panasonic";
case CEC_VENDOR_PIONEER:
return "Pioneer";
case CEC_VENDOR_ONKYO:
return "Onkyo";
case CEC_VENDOR_YAMAHA:
return "Yamaha";
case CEC_VENDOR_PHILIPS:
return "Philips";
case CEC_VENDOR_SONY:
return "Sony";
case CEC_VENDOR_TOSHIBA:
case CEC_VENDOR_TOSHIBA2:
return "Toshiba";
case CEC_VENDOR_AKAI:
return "Akai";
case CEC_VENDOR_AOC:
return "AOC";
case CEC_VENDOR_BENQ:
return "Benq";
case CEC_VENDOR_DAEWOO:
return "Daewoo";
case CEC_VENDOR_GRUNDIG:
return "Grundig";
case CEC_VENDOR_MEDION:
return "Medion";
case CEC_VENDOR_SHARP:
case CEC_VENDOR_SHARP2:
return "Sharp";
case CEC_VENDOR_VIZIO:
return "Vizio";
case CEC_VENDOR_BROADCOM:
return "Broadcom";
case CEC_VENDOR_LOEWE:
return "Loewe";
case CEC_VENDOR_DENON:
return "Denon";
case CEC_VENDOR_MARANTZ:
return "Marantz";
case CEC_VENDOR_HARMAN_KARDON:
case CEC_VENDOR_HARMAN_KARDON2:
return "Harman/Kardon";
case CEC_VENDOR_PULSE_EIGHT:
return "Pulse Eight";
case CEC_VENDOR_GOOGLE:
return "Google";
default:
return "Unknown";
}
}
static const char *ToString(const cec_user_control_code key)
{
switch (key)
{
case CEC_USER_CONTROL_CODE_SELECT:
return "select";
case CEC_USER_CONTROL_CODE_UP:
return "up";
case CEC_USER_CONTROL_CODE_DOWN:
return "down";
case CEC_USER_CONTROL_CODE_LEFT:
return "left";
case CEC_USER_CONTROL_CODE_RIGHT:
return "right";
case CEC_USER_CONTROL_CODE_RIGHT_UP:
return "right+up";
case CEC_USER_CONTROL_CODE_RIGHT_DOWN:
return "right+down";
case CEC_USER_CONTROL_CODE_LEFT_UP:
return "left+up";
case CEC_USER_CONTROL_CODE_LEFT_DOWN:
return "left+down";
case CEC_USER_CONTROL_CODE_ROOT_MENU:
return "root menu";
case CEC_USER_CONTROL_CODE_SETUP_MENU:
return "setup menu";
case CEC_USER_CONTROL_CODE_CONTENTS_MENU:
return "contents menu";
case CEC_USER_CONTROL_CODE_FAVORITE_MENU:
return "favourite menu";
case CEC_USER_CONTROL_CODE_EXIT:
return "exit";
case CEC_USER_CONTROL_CODE_TOP_MENU:
return "top menu";
case CEC_USER_CONTROL_CODE_DVD_MENU:
return "dvd menu";
case CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE:
return "number entry mode";
case CEC_USER_CONTROL_CODE_NUMBER11:
return "11";
case CEC_USER_CONTROL_CODE_NUMBER12:
return "12";
case CEC_USER_CONTROL_CODE_NUMBER0:
return "0";
case CEC_USER_CONTROL_CODE_NUMBER1:
return "1";
case CEC_USER_CONTROL_CODE_NUMBER2:
return "2";
case CEC_USER_CONTROL_CODE_NUMBER3:
return "3";
case CEC_USER_CONTROL_CODE_NUMBER4:
return "4";
case CEC_USER_CONTROL_CODE_NUMBER5:
return "5";
case CEC_USER_CONTROL_CODE_NUMBER6:
return "6";
case CEC_USER_CONTROL_CODE_NUMBER7:
return "7";
case CEC_USER_CONTROL_CODE_NUMBER8:
return "8";
case CEC_USER_CONTROL_CODE_NUMBER9:
return "9";
case CEC_USER_CONTROL_CODE_DOT:
return ".";
case CEC_USER_CONTROL_CODE_ENTER:
return "enter";
case CEC_USER_CONTROL_CODE_CLEAR:
return "clear";
case CEC_USER_CONTROL_CODE_NEXT_FAVORITE:
return "next favourite";
case CEC_USER_CONTROL_CODE_CHANNEL_UP:
return "channel up";
case CEC_USER_CONTROL_CODE_CHANNEL_DOWN:
return "channel down";
case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL:
return "previous channel";
case CEC_USER_CONTROL_CODE_SOUND_SELECT:
return "sound select";
case CEC_USER_CONTROL_CODE_INPUT_SELECT:
return "input select";
case CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION:
return "display information";
case CEC_USER_CONTROL_CODE_HELP:
return "help";
case CEC_USER_CONTROL_CODE_PAGE_UP:
return "page up";
case CEC_USER_CONTROL_CODE_PAGE_DOWN:
return "page down";
case CEC_USER_CONTROL_CODE_POWER:
return "power";
case CEC_USER_CONTROL_CODE_VOLUME_UP:
return "volume up";
case CEC_USER_CONTROL_CODE_VOLUME_DOWN:
return "volume down";
case CEC_USER_CONTROL_CODE_MUTE:
return "mute";
case CEC_USER_CONTROL_CODE_PLAY:
return "play";
case CEC_USER_CONTROL_CODE_STOP:
return "stop";
case CEC_USER_CONTROL_CODE_PAUSE:
return "pause";
case CEC_USER_CONTROL_CODE_RECORD:
return "record";
case CEC_USER_CONTROL_CODE_REWIND:
return "rewind";
case CEC_USER_CONTROL_CODE_FAST_FORWARD:
return "Fast forward";
case CEC_USER_CONTROL_CODE_EJECT:
return "eject";
case CEC_USER_CONTROL_CODE_FORWARD:
return "forward";
case CEC_USER_CONTROL_CODE_BACKWARD:
return "backward";
case CEC_USER_CONTROL_CODE_STOP_RECORD:
return "stop record";
case CEC_USER_CONTROL_CODE_PAUSE_RECORD:
return "pause record";
case CEC_USER_CONTROL_CODE_ANGLE:
return "angle";
case CEC_USER_CONTROL_CODE_SUB_PICTURE:
return "sub picture";
case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND:
return "video on demand";
case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE:
return "electronic program guide";
case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING:
return "timer programming";
case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION:
return "initial configuration";
case CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE:
return "select broadcast type";
case CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION:
return "select sound presentation";
case CEC_USER_CONTROL_CODE_PLAY_FUNCTION:
return "play (function)";
case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION:
return "pause play (function)";
case CEC_USER_CONTROL_CODE_RECORD_FUNCTION:
return "record (function)";
case CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION:
return "pause record (function)";
case CEC_USER_CONTROL_CODE_STOP_FUNCTION:
return "stop (function)";
case CEC_USER_CONTROL_CODE_MUTE_FUNCTION:
return "mute (function)";
case CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION:
return "restore volume";
case CEC_USER_CONTROL_CODE_TUNE_FUNCTION:
return "tune";
case CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION:
return "select media";
case CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION:
return "select AV input";
case CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION:
return "select audio input";
case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION:
return "power toggle";
case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION:
return "power off";
case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION:
return "power on";
case CEC_USER_CONTROL_CODE_F1_BLUE:
return "F1 (blue)";
case CEC_USER_CONTROL_CODE_F2_RED:
return "F2 (red)";
case CEC_USER_CONTROL_CODE_F3_GREEN:
return "F3 (green)";
case CEC_USER_CONTROL_CODE_F4_YELLOW:
return "F4 (yellow)";
case CEC_USER_CONTROL_CODE_F5:
return "F5";
case CEC_USER_CONTROL_CODE_DATA:
return "data";
case CEC_USER_CONTROL_CODE_AN_RETURN:
return "return (Samsung)";
case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST:
return "channels list (Samsung)";
default:
return "unknown";
}
}
static const char *ToString(cec_logical_address la)
{
switch (la & 0xf)
{
case CECDEVICE_TV:
return "TV";
case CECDEVICE_RECORDINGDEVICE1:
return "Recording Device 1";
case CECDEVICE_RECORDINGDEVICE2:
return "Recording Device 2";
case CECDEVICE_TUNER1:
return "Tuner 1";
case CECDEVICE_PLAYBACKDEVICE1:
return "Playback Device 1";
case CECDEVICE_AUDIOSYSTEM:
return "Audio System";
case CECDEVICE_TUNER2:
return "Tuner 2";
case CECDEVICE_TUNER3:
return "Tuner 3";
case CECDEVICE_PLAYBACKDEVICE2:
return "Playback Device 2";
case CECDEVICE_RECORDINGDEVICE3:
return "Recording Device 3";
case CECDEVICE_TUNER4:
return "Tuner 4";
case CECDEVICE_PLAYBACKDEVICE3:
return "Playback Device 3";
case CECDEVICE_RESERVED1:
return "Reserved 1";
case CECDEVICE_RESERVED2:
return "Reserved 2";
case CECDEVICE_FREEUSE:
return "Free use";
case CECDEVICE_UNREGISTERED:
default:
return "Unregistered";
}
}
static cec_opcode GetResponseOpcode(cec_opcode opcode)
{
switch (opcode)
{
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
return CEC_OPCODE_ACTIVE_SOURCE;
case CEC_OPCODE_GET_CEC_VERSION:
return CEC_OPCODE_CEC_VERSION;
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
return CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
case CEC_OPCODE_GET_MENU_LANGUAGE:
return CEC_OPCODE_SET_MENU_LANGUAGE;
case CEC_OPCODE_GIVE_DECK_STATUS:
return CEC_OPCODE_DECK_STATUS;
case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
return CEC_OPCODE_TUNER_DEVICE_STATUS;
case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
return CEC_OPCODE_DEVICE_VENDOR_ID;
case CEC_OPCODE_GIVE_OSD_NAME:
return CEC_OPCODE_SET_OSD_NAME;
case CEC_OPCODE_MENU_REQUEST:
return CEC_OPCODE_MENU_STATUS;
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
return CEC_OPCODE_REPORT_POWER_STATUS;
case CEC_OPCODE_GIVE_AUDIO_STATUS:
return CEC_OPCODE_REPORT_AUDIO_STATUS;
case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
return CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS;
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
return CEC_OPCODE_SET_SYSTEM_AUDIO_MODE;
default:
break;
}
return CEC_OPCODE_NONE;
}
#endif // __HDMI_CEC_TYPES_H__

View File

@@ -1,287 +0,0 @@
#ifndef _hisilicon_h
#define _hisilicon_h
#define HI_FORMAT_MAX_URL_LEN (2048)
#define HI_FORMAT_MAX_FILE_NAME_LEN (512)
#define HI_FORMAT_TITLE_MAX_LEN (512)
#define HI_FORMAT_LANG_LEN (64)
#define HI_FORMAT_MAX_LANGUAGE_NUM (4)
#define HI_FORMAT_SERVICE_DESCRIPT_LEN (64)
typedef uint8_t HI_U8;
typedef uint16_t HI_U16;
typedef uint32_t HI_U32;
typedef int8_t HI_S8;
typedef int16_t HI_S16;
typedef int32_t HI_S32;
typedef uint64_t HI_U64;
typedef int64_t HI_S64;
typedef void HI_VOID;
typedef char HI_CHAR;
typedef enum
{
HI_FALSE = 0,
HI_TRUE = 1,
} HI_BOOL;
typedef enum hiFORMAT_SUBTITLE_TYPE_E
{
HI_FORMAT_SUBTITLE_ASS = 0x0, /**< ASS subtitle */
HI_FORMAT_SUBTITLE_LRC, /**< LRC subtitle */
HI_FORMAT_SUBTITLE_SRT, /**< SRT subtitle */
HI_FORMAT_SUBTITLE_SMI, /**< SMI subtitle */
HI_FORMAT_SUBTITLE_SUB, /**< SUB subtitle */
HI_FORMAT_SUBTITLE_TXT, /**< RAW UTF8 subtitle */
HI_FORMAT_SUBTITLE_HDMV_PGS, /**< pgs subtitle */
HI_FORMAT_SUBTITLE_DVB_SUB, /**< DVB subtitle */
HI_FORMAT_SUBTITLE_DVD_SUB, /**< DVD subtitle */
HI_FORMAT_SUBTITLE_TTML, /**< TTML subtitle */
HI_FORMAT_SUBTITLE_WEBVTT,
HI_FORMAT_SUBTITLE_BUTT
} HI_FORMAT_SUBTITLE_TYPE_E;
typedef enum hiFORMAT_AUDIO_TYPE_E
{
HI_FORMAT_AUDIO_MP2 = 0x000, /**< MPEG audio layer 1, 2.*/
HI_FORMAT_AUDIO_MP3, /**< MPEG audio layer 1, 2, 3.*/
HI_FORMAT_AUDIO_AAC,
HI_FORMAT_AUDIO_AC3,
HI_FORMAT_AUDIO_DTS,
HI_FORMAT_AUDIO_VORBIS,
HI_FORMAT_AUDIO_DVAUDIO,
HI_FORMAT_AUDIO_WMAV1,
HI_FORMAT_AUDIO_WMAV2,
HI_FORMAT_AUDIO_MACE3,
HI_FORMAT_AUDIO_MACE6,
HI_FORMAT_AUDIO_VMDAUDIO,
HI_FORMAT_AUDIO_SONIC,
HI_FORMAT_AUDIO_SONIC_LS,
HI_FORMAT_AUDIO_FLAC,
HI_FORMAT_AUDIO_MP3ADU,
HI_FORMAT_AUDIO_MP3ON4,
HI_FORMAT_AUDIO_SHORTEN,
HI_FORMAT_AUDIO_ALAC,
HI_FORMAT_AUDIO_WESTWOOD_SND1,
HI_FORMAT_AUDIO_GSM,
HI_FORMAT_AUDIO_QDM2,
HI_FORMAT_AUDIO_COOK,
HI_FORMAT_AUDIO_TRUESPEECH,
HI_FORMAT_AUDIO_TTA,
HI_FORMAT_AUDIO_SMACKAUDIO,
HI_FORMAT_AUDIO_QCELP,
HI_FORMAT_AUDIO_WAVPACK,
HI_FORMAT_AUDIO_DSICINAUDIO,
HI_FORMAT_AUDIO_IMC,
HI_FORMAT_AUDIO_MUSEPACK7,
HI_FORMAT_AUDIO_MLP,
HI_FORMAT_AUDIO_GSM_MS, /**< as found in WAV.*/
HI_FORMAT_AUDIO_ATRAC3,
HI_FORMAT_AUDIO_VOXWARE,
HI_FORMAT_AUDIO_APE,
HI_FORMAT_AUDIO_NELLYMOSER,
HI_FORMAT_AUDIO_MUSEPACK8,
HI_FORMAT_AUDIO_SPEEX,
HI_FORMAT_AUDIO_WMAVOICE,
HI_FORMAT_AUDIO_WMAPRO,
HI_FORMAT_AUDIO_WMALOSSLESS,
HI_FORMAT_AUDIO_ATRAC3P,
HI_FORMAT_AUDIO_EAC3,
HI_FORMAT_AUDIO_SIPR,
HI_FORMAT_AUDIO_MP1,
HI_FORMAT_AUDIO_TWINVQ,
HI_FORMAT_AUDIO_TRUEHD,
HI_FORMAT_AUDIO_MP4ALS,
HI_FORMAT_AUDIO_ATRAC1,
HI_FORMAT_AUDIO_BINKAUDIO_RDFT,
HI_FORMAT_AUDIO_BINKAUDIO_DCT,
HI_FORMAT_AUDIO_DRA,
HI_FORMAT_AUDIO_DTS_EXPRESS,
HI_FORMAT_AUDIO_PCM = 0x100, /**< various PCM codecs. */
HI_FORMAT_AUDIO_PCM_BLURAY = 0x121,
HI_FORMAT_AUDIO_ADPCM = 0x130, /**< various ADPCM codecs. */
HI_FORMAT_AUDIO_AMR_NB = 0x160,/**< various AMR codecs. */
HI_FORMAT_AUDIO_AMR_WB,
HI_FORMAT_AUDIO_AMR_AWB,
HI_FORMAT_AUDIO_RA_144 = 0x170, /**< RealAudio codecs. */
HI_FORMAT_AUDIO_RA_288,
HI_FORMAT_AUDIO_DPCM = 0x180, /**< various DPCM codecs. */
HI_FORMAT_AUDIO_G711 = 0x190, /**< various G.7xx codecs. */
HI_FORMAT_AUDIO_G722,
HI_FORMAT_AUDIO_G7231,
HI_FORMAT_AUDIO_G726,
HI_FORMAT_AUDIO_G728,
HI_FORMAT_AUDIO_G729AB,
HI_FORMAT_AUDIO_MULTI = 0x1f0, /**< support multi codecs. */
HI_FORMAT_AUDIO_BUTT = 0x1ff,
} HI_FORMAT_AUDIO_TYPE_E;
typedef enum hiFORMAT_VIDEO_TYPE_E
{
HI_FORMAT_VIDEO_MPEG2 = 0x0, /**< MPEG2*/
HI_FORMAT_VIDEO_MPEG4, /**< MPEG4 DIVX4 DIVX5*/
HI_FORMAT_VIDEO_AVS, /**< AVS*/
HI_FORMAT_VIDEO_H263, /**< H263*/
HI_FORMAT_VIDEO_H264, /**< H264*/
HI_FORMAT_VIDEO_REAL8, /**< REAL*/
HI_FORMAT_VIDEO_REAL9, /**< REAL*/
HI_FORMAT_VIDEO_VC1, /**< VC-1*/
HI_FORMAT_VIDEO_VP6, /**< VP6*/
HI_FORMAT_VIDEO_VP6F, /**< VP6F*/
HI_FORMAT_VIDEO_VP6A, /**< VP6A*/
HI_FORMAT_VIDEO_MJPEG, /**< MJPEG*/
HI_FORMAT_VIDEO_SORENSON, /**< SORENSON SPARK*/
HI_FORMAT_VIDEO_DIVX3, /**< DIVX3, not supported*/
HI_FORMAT_VIDEO_RAW, /**< RAW*/
HI_FORMAT_VIDEO_JPEG, /**< JPEG added for VENC*/
HI_FORMAT_VIDEO_VP8, /**<VP8*/
HI_FORMAT_VIDEO_MSMPEG4V1, /**< MS private MPEG4 */
HI_FORMAT_VIDEO_MSMPEG4V2,
HI_FORMAT_VIDEO_MSVIDEO1, /**< MS video */
HI_FORMAT_VIDEO_WMV1,
HI_FORMAT_VIDEO_WMV2,
HI_FORMAT_VIDEO_RV10,
HI_FORMAT_VIDEO_RV20,
HI_FORMAT_VIDEO_SVQ1, /**< Apple video */
HI_FORMAT_VIDEO_SVQ3, /**< Apple video */
HI_FORMAT_VIDEO_H261,
HI_FORMAT_VIDEO_VP3,
HI_FORMAT_VIDEO_VP5,
HI_FORMAT_VIDEO_CINEPAK,
HI_FORMAT_VIDEO_INDEO2,
HI_FORMAT_VIDEO_INDEO3,
HI_FORMAT_VIDEO_INDEO4,
HI_FORMAT_VIDEO_INDEO5,
HI_FORMAT_VIDEO_MJPEGB,
HI_FORMAT_VIDEO_MVC,
HI_FORMAT_VIDEO_HEVC, /**< HEVC(H265)*/
HI_FORMAT_VIDEO_DV,
HI_FORMAT_VIDEO_HUFFYUV,
HI_FORMAT_VIDEO_DIVX, /**< DIVX,not supported*/
HI_FORMAT_VIDEO_REALMAGICMPEG4, /**< REALMAGIC MPEG4,not supported*/
HI_FORMAT_VIDEO_VP9, /**<VP9*/
HI_FORMAT_VIDEO_WMV3,
HI_FORMAT_VIDEO_AVS2,
HI_FORMAT_VIDEO_BUTT
} HI_FORMAT_VIDEO_TYPE_E;
typedef enum hiFORMAT_SOURCE_TYPE_E
{
HI_FORMAT_SOURCE_LOCAL = 0x0, /**< Local file */
HI_FORMAT_SOURCE_NET_VOD, /**< Net VOD file */
HI_FORMAT_SOURCE_NET_LIVE, /**< Net Live stream */
HI_FORMAT_SOURCE_BUTT
} HI_FORMAT_SOURCE_TYPE_E;
typedef enum hiFORMAT_STREAM_TYPE_E
{
HI_FORMAT_STREAM_ES = 0x0, /**< Element stream (ES) file */
HI_FORMAT_STREAM_TS, /**< TS file */
HI_FORMAT_STREAM_BUTT
} HI_FORMAT_STREAM_TYPE_E;
typedef struct hiFORMAT_AUD_INFO_S
{
HI_S32 s32StreamIndex; /**< Stream index. The invalid value is ::HI_FORMAT_INVALID_STREAM_ID. */
HI_U32 u32Format; /**< Audio encoding format. For details about the value definition, see ::HI_FORMAT_AUDIO_TYPE_E. */
HI_U32 u32Profile; /**< Audio encoding version, such as 0x160(WMAV1) and 0x161 (WMAV2). It is valid only for WMA encoding. */
HI_U32 u32SampleRate; /**< 8000,11025,441000,... */
HI_U16 u16BitPerSample; /**< Number of bits occupied by each audio sampling point such as 8 bits or 16 bits. */
HI_U16 u16Channels; /**< Number of channels, 1 or 2. *//**< CNcomment:ÉùµÀÊý, 1 or 2 */
HI_S32 s32SubStreamID; /**< Sub audio stream ID */
HI_U32 u32BlockAlign; /**< Number of bytes contained in a packet */
HI_U32 u32Bitrate; /**< Audio bit rate, in the unit of bit/s. */
HI_BOOL bBigEndian; /**< Big endian or little endian. It is valid only for the PCM format */
HI_CHAR aszLanguage[HI_FORMAT_LANG_LEN]; /**< Audio stream language */
HI_U32 u32ExtradataSize; /**< Length of the extended data */
HI_U8* pu8Extradata; /**< Extended data */
HI_VOID* pCodecContext; /**< Audio decode context */
HI_U32 u32Role; /**< Role descriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, the descriptor value may be the bitwise '|' result of value define in HI_FORMAT_ROLE_VALUE_E*/
HI_U32 u32Accessibility; /**< Accessbilitydescriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, the descriptor value type is number*/
HI_S64 s64Duration; /**< Duration of audio stream, in the unit of ms. */
HI_U32 u32CodecTag; /**< Codec tag of audio stream format, fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). */
} HI_FORMAT_AUD_INFO_S;
typedef struct hiFORMAT_VID_INFO_S
{
HI_S32 s32StreamIndex; /**< Stream index. The invalid value is ::HI_FORMAT_INVALID_STREAM_ID. */
HI_U32 u32Format; /**< Video encoding format. For details about the value definition, see ::HI_FORMAT_VIDEO_TYPE_E. */
HI_U16 u16RefFrameNum; /**< Number of reference frames. */
HI_U16 u16Profile; /**< Profile level. */
HI_U16 u16Width; /**< Width, in the unit of pixel. */
HI_U16 u16Height; /**< Height, in the unit of pixel. */
HI_U16 u16FpsInteger; /**< Integer part of the frame rate */
HI_U16 u16FpsDecimal; /**< Decimal part of the frame rate */
HI_U32 u32Bitrate; /**< Video bit rate, in the unit of bit/s. */
HI_U32 u32CodecVersion; /**< Version of codec. */
HI_U32 u32Rotate; /**< Video rotation angle, value is 90/180/270, default value is 0 */
HI_U32 u32Reversed;
HI_BOOL bEnableTVP;
HI_U32 u32ExtradataSize; /**< Length of the extended data */
HI_U8* pu8Extradata; /**< Extended data */
HI_VOID* pCodecContext; /**< video decode context */
HI_U32 u32Role; /**< Role descriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, the descriptor value may be the bitwise '|' result of value define in HI_FORMAT_ROLE_VALUE_E*/
HI_U32 u32Accessibility; /**< Accessbilitydescriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, the descriptor value type is number*/
HI_S64 s64Duration; /**< Duration of video stream, in the unit of ms. */
HI_BOOL bNoPts; /**<this stream has no pts info or pts is invalid> */
} HI_FORMAT_VID_INFO_S;
typedef struct hiFORMAT_SUB_INFO_S
{
HI_S32 s32StreamIndex; /**< Stream index. The invalid value is ::HI_FORMAT_INVALID_STREAM_ID. */
HI_U32 u32Format; /**< Subtitle format, For details about the value definition, see::HI_FORMAT_SUBTITLE_TYPE_E */
HI_U32 u32CharSet; /**< Encoding type of the subtitle, the value range is as follows:
1. The default value is 0.
2. The value of the u32CharSet is the identified byte encoding value if the IdentStream byte encoding function (for details about the definition, see hi_charset_common.h) is set.
3. If the ConvStream function (for details about the definition, see hi_charset_common.h) is set and the invoke interface is called to set the encoding type to be converted by implementing HI_FORMAT_INVOKE_SET_SOURCE_CODETYPE, the value of the u32CharSet is the configured encoding type */
HI_BOOL bExtSub; /**< Whether subtitles are external subtitles. When bExtSub is HI_TRUE, the subtitles are external. When bExtSub is HI_FALSE, the subtitles are internal. */
HI_U32 u32StreamNum; /**< contains stream number */
HI_CHAR paszLanguage[HI_FORMAT_MAX_LANGUAGE_NUM][HI_FORMAT_LANG_LEN]; /**< Subtitle language */
HI_U16 u16OriginalFrameWidth; /**< Width of the original image */
HI_U16 u16OriginalFrameHeight; /**< Height of the original image */
HI_U32 u32ExtradataSize; /**< Length of the extended data */
HI_U8* pu8Extradata; /**< Extended data */
HI_VOID* pCodecContext; /**< Audio decode context */
HI_U32 u32Role; /**< Role descriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, the descriptor value may be the bitwise '|' result of value define in HI_FORMAT_ROLE_VALUE_E*/
HI_U32 u32Accessibility; /**< Accessibility descriptor value of mpeg dash. the most 8 bits is scheme value(refer to HI_FORMAT_ROLE_SCHEME_E), the left 24 bits is descriptor value, value type is number*/
HI_CHAR paszFileName[HI_FORMAT_MAX_URL_LEN]; /**< File name of external subtitle. */
} HI_FORMAT_SUB_INFO_S;
typedef struct hiFORMAT_PROGRAM_INFO_S
{
HI_U32 u32VidStreamNum; /**< Number of video streams */
HI_FORMAT_VID_INFO_S* pastVidStream; /**< Video stream information */
HI_U32 u32AudStreamNum; /**< Number of audio streams */
HI_FORMAT_AUD_INFO_S* pastAudStream; /**< Audio stream information */
HI_U32 u32SubStreamNum; /**< Number of subtitles */
HI_FORMAT_SUB_INFO_S* pastSubStream; /**< Subtitle information */
HI_CHAR aszServiceName[HI_FORMAT_SERVICE_DESCRIPT_LEN]; /**< Program service name info */
HI_CHAR aszServiceProvider[HI_FORMAT_SERVICE_DESCRIPT_LEN]; /**< Program service provider info */
HI_S64 s64ProgramDuration;
HI_S64 s64ProgramStartTime;
} HI_FORMAT_PROGRAM_INFO_S;
typedef struct hiFORMAT_FILE_INFO_S
{
HI_FORMAT_SOURCE_TYPE_E eSourceType; /**< File source type */
HI_FORMAT_STREAM_TYPE_E eStreamType; /**< File stream type */
HI_S64 s64FileSize; /**< File size, in the unit of byte. */
HI_S64 s64StartTime; /**< Start time of playing a file, in the unit is ms. */
HI_S64 s64Duration; /**< Total duration of a file, in the unit of ms. */
HI_U32 u32Bitrate; /**< File bit rate, in the unit of bit/s. */
HI_CHAR aszFileFormat[HI_FORMAT_TITLE_MAX_LEN]; /**< File demuxer info .Not used now*/
HI_U32 u32ProgramNum; /**< Actual number of programs */
HI_FORMAT_PROGRAM_INFO_S* pastProgramInfo; /**< Program information */
HI_BOOL bIsDivx; /**< If the stream is DIVX restricted stream,HI_TRUE yes,HI_FALSE no */
HI_BOOL bIsDrmFile;
} HI_FORMAT_FILE_INFO_S;
#endif

View File

@@ -1,54 +0,0 @@
#include <config.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "init.h"
#include "pwrmngr.h"
#include <proc_tools.h>
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
static bool initialized = false;
void hal_api_init()
{
if (!initialized)
hal_debug_init();
hal_info("%s begin, initialized=%d, debug=0x%02x\n", __FUNCTION__, (int)initialized, debuglevel);
if (!initialized)
{
cCpuFreqManager f;
f.SetCpuFreq(0); /* CPUFREQ == 0 is the trigger for leaving standby */
char buffer[64];
sprintf(buffer, "%x", 0);
proc_put("/proc/stb/fb/dst_top", buffer, strlen(buffer));
proc_put("/proc/stb/fb/dst_left", buffer, strlen(buffer));
sprintf(buffer, "%x", 576);
proc_put("/proc/stb/fb/dst_height", buffer, strlen(buffer));
sprintf(buffer, "%x", 720);
proc_put("/proc/stb/fb/dst_width", buffer, strlen(buffer));
sprintf(buffer, "%x", 1);
proc_put("/proc/stb/fb/dst_apply", buffer, strlen(buffer));
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
sprintf(buffer, "%s", "enable");
proc_put("/proc/stb/frontend/fbc/fcc", buffer, strlen(buffer));
#endif
}
initialized = true;
hal_info("%s end\n", __FUNCTION__);
}
void hal_api_exit()
{
hal_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized);
initialized = false;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +0,0 @@
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __PLAYBACK_GST_H__
#define __PLAYBACK_GST_H__
#include <string>
#include <stdint.h>
#include <vector>
#include <config.h>
typedef enum
{
STATE_STOP,
STATE_PLAY,
STATE_PAUSE,
STATE_FF,
STATE_REW,
STATE_SLOW
} playstate_t;
typedef enum
{
PLAYMODE_TS = 0,
PLAYMODE_FILE,
} playmode_t;
struct AVFormatContext;
class cPlayback
{
private:
bool playing, first;
bool decoders_closed;
int mSpeed;
int mAudioStream;
int init_jump;
public:
playstate_t playstate;
cPlayback(int);
bool Open(playmode_t PlayMode);
void Close(void);
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "");
bool Start(std::string filename, std::string headers = "");
bool Play(void);
bool SyncAV(void);
bool Stop(void);
bool SetAPid(int pid, bool ac3);
bool SetSubtitlePid(int pid);
bool SetTeletextPid(int pid);
void trickSeek(int ratio);
bool SetSpeed(int speed);
bool SetSlow(int slow);
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration);
void GetPts(uint64_t &pts);
int GetAPid(void);
int GetVPid(void);
int GetSubtitlePid(void);
bool SetPosition(int position, bool absolute = false);
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language) { FindAllPids((int*) apids, (unsigned int*) ac3flags, (unsigned int*) numpida, language); };
void FindAllSubs(int *pids, unsigned int *supported, unsigned int *numpida, std::string *language);
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language) { FindAllSubs((int*) pids, (unsigned int*) supported, (unsigned int*) numpida, language); };
bool SelectSubtitles(int pid, std::string charset = "");
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages);
void RequestAbort(void);
uint64_t GetReadCount(void);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
std::string extra_headers;
std::string user_agent;
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current);
void SetTitle(int title);
//
~cPlayback();
void getMeta();
};
#endif // __PLAYBACK_GST_H__

File diff suppressed because it is too large Load Diff

View File

@@ -1,184 +0,0 @@
/*
Copyright (C) 2018 TangoCash
License: GPLv2
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __HAL_PLAYBACK_H
#define __HAL_PLAYBACK_H
#include <string>
#include <vector>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
#include "hisilicon.h"
typedef enum
{
PLAYMODE_TS = 0,
PLAYMODE_FILE
} playmode_t;
struct AVFormatContext;
struct errorInfo
{
std::string error_message;
std::string missing_codec;
};
class cPlayback
{
friend class CStreamInfo2;
friend class netlink_event;
private:
int m_video_fd;
int m_audio_fd;
bool enabled;
bool playing, first;
bool no_probe;
bool got_vpts_ts;
int nPlaybackSpeed;
int mAudioStream;
int mSubtitleStream;
int mTeletextStream;
int64_t vpts_ts;
bool Stop(void);
bool decoders_closed;
playmode_t pm;
std::string fn_ts;
std::string fn_xml;
off64_t last_size;
int init_jump;
const char *getVidFormatStr(uint32_t format);
const char *getAudFormatStr(uint32_t format);
const char *getSubFormatStr(uint32_t format);
public:
cPlayback(int num = 0);
~cPlayback();
bool Open(playmode_t PlayMode);
void Close(void);
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "", std::string filename2 = "");
bool Start(std::string filename, std::string headers = "", std::string filename2 = "");
bool SetAPid(int pid, bool ac3 = false);
bool SetVPid(int /*pid*/);
bool SetSubtitlePid(int pid);
bool SetTeletextPid(int pid);
int GetAPid(void)
{
return mAudioStream;
}
int GetVPid(void)
{
return 0;
}
int GetSubtitlePid(void)
{
return mSubtitleStream;
}
int GetTeletextPid(void);
bool SetSpeed(int speed);
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration);
void GetPts(uint64_t &pts);
bool SetPosition(int position, bool absolute = false);
void FindAllPids(short unsigned int *apids, short unsigned int *ac3flags, short unsigned int *numpida, std::string *language);
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
void FindAllTeletextsubtitlePids(int */*pids*/, unsigned int *numpidt, std::string */*tlanguage*/, int */*mags*/, int */*pages*/);
void FindAllSubs(short unsigned int *pids, short unsigned int *supported, short unsigned int *numpida, std::string *language);
bool SelectSubtitles(int pid, std::string charset = "");
void RequestAbort(void);
bool IsPlaying(void);
uint64_t GetReadCount(void);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current);
void SetTitle(int title);
};
class netlink_event : public OpenThreads::Thread
{
friend class cPlayback;
protected:
bool running;
private:
netlink_event();
~netlink_event();
static netlink_event *netlink_event_instance;
cPlayback *player;
int m_player_state;
enum
{
stIdle, stRunning, stStopped,
};
struct streamid
{
uint16_t programid;
uint16_t videostreamid;
uint16_t audiostreamid;
uint16_t subtitlestreamid;
} streamid;
int m_state;
bool m_paused;
bool m_buffering;
HI_FORMAT_FILE_INFO_S fileinfo;
struct nlmsghdr *nlh;
int m_bufferpercentage;
uint32_t m_seekable;
uint32_t m_download_progress;
int netlink_socket;
int receive_netlink_message();
errorInfo m_errorInfo;
void run();
void Receive();
public:
static netlink_event* getInstance();
uint64_t getDuration()
{
return fileinfo.s64Duration;
};
bool Start(cPlayback *player);
bool Stop();
};
#if 0 // for later use, maybe
class video_event : public OpenThreads::Thread
{
friend class cPlayback;
protected:
bool running;
private:
int m_video_fd;
void run();
void Receive();
public:
bool Start(int video_fd);
bool Stop();
};
#endif
#endif

View File

@@ -1,889 +0,0 @@
#define __USE_FILE_OFFSET64 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sstream>
#include <audio_lib.h>
#include <video_lib.h>
extern "C" {
#include <common.h>
extern OutputHandler_t OutputHandler;
extern PlaybackHandler_t PlaybackHandler;
extern ContainerHandler_t ContainerHandler;
extern ManagerHandler_t ManagerHandler;
extern int32_t ffmpeg_av_dict_set( const char *key, const char *value, int32_t flags);
}
#include "playback_libeplayer3.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_PLAYBACK, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_PLAYBACK, this, args)
static Context_t *player = NULL;
extern cAudio *audioDecoder;
extern cVideo *videoDecoder;
OpenThreads::Mutex cPlayback::mutex;
//Used by Fileplay
bool cPlayback::Open(playmode_t PlayMode)
{
const char *aPLAYMODE[] =
{
"PLAYMODE_TS",
"PLAYMODE_FILE"
};
if (PlayMode != PLAYMODE_TS)
{
audioDecoder->closeDevice();
videoDecoder->closeDevice();
decoders_closed = true;
}
pm = PlayMode;
got_vpts_ts = false;
vpts_ts = 0;
fn_ts = "";
fn_xml = "";
last_size = 0;
nPlaybackSpeed = 0;
init_jump = -1;
avft = avformat_alloc_context();
if (!player)
{
player = (Context_t *) malloc(sizeof(Context_t));
}
if (player)
{
player->playback = &PlaybackHandler;
player->output = &OutputHandler;
player->container = &ContainerHandler;
player->manager = &ManagerHandler;
hal_info("%s - player output name: %s PlayMode: %s\n", __func__, player->output->Name, aPLAYMODE[PlayMode]);
}
//Registration of output devices
if (player && player->output)
{
player->output->Command(player, OUTPUT_ADD, (void *)"audio");
player->output->Command(player, OUTPUT_ADD, (void *)"video");
player->output->Command(player, OUTPUT_ADD, (void *)"subtitle");
}
return 0;
}
void cPlayback::Close(void)
{
hal_info("%s\n", __func__);
//Dagobert: movieplayer does not call stop, it calls close ;)
mutex.lock();
if(playing)
Stop();
mutex.unlock();
if (decoders_closed)
{
audioDecoder->openDevice();
videoDecoder->openDevice();
decoders_closed = false;
}
}
bool cPlayback::Start(std::string filename, std::string headers, std::string filename2)
{
return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers,filename2);
}
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers, std::string filename2)
{
bool ret = false;
bool isHTTP = false;
no_probe = false;
hal_info("%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d\n", __func__, filename, vpid, vtype, apid, ac3);
init_jump = -1;
//create playback path
mAudioStream = 0;
mSubtitleStream = -1;
mTeletextStream = -1;
std::string file;
if (*filename == '/')
file = "file://";
file += filename;
if ((file.find(":31339/id=") != std::string::npos) || (file.find(":10000") != std::string::npos) || (file.find(":8001/") != std::string::npos)) // for LocalTV and Entertain-TV streaming
no_probe = true;
if (file.substr(0, 7) == "file://")
{
if (file.substr(file.length() - 3) == ".ts")
{
fn_ts = file.substr(7);
fn_xml = file.substr(7, file.length() - 9);
fn_xml += "xml";
no_probe = true;
}
}
else
isHTTP = true;
if(isHTTP && headers.empty())
{
size_t pos = file.find('#');
if (pos != std::string::npos)
{
headers = file.substr(pos + 1);
pos = headers.find("User-Agent=");
if (pos != std::string::npos)
headers.replace(pos+10, 1, ": ");
}
}
if(!headers.empty()){
const char hkey[] = "headers";
ffmpeg_av_dict_set(hkey, headers.c_str(), 0);
}
std::string szSecondFile;
char *file2 = NULL;
if(!filename2.empty()){
szSecondFile = filename2;
file2 = (char *) szSecondFile.c_str();
}
PlayFiles_t playbackFiles = { (char *) file.c_str(), file2, NULL, NULL, 0, 0, 0, 0};
if (player->playback->Command(player, PLAYBACK_OPEN, &playbackFiles) == 0)
{
if (pm == PLAYMODE_TS)
{
struct stat64 s;
if (!stat64(file.c_str(), &s))
last_size = s.st_size;
ret = true;
videoDecoder->Stop(false);
audioDecoder->Stop();
}
else
{
//AUDIO
if (player && player->manager && player->manager->audio)
{
char ** TrackList = NULL;
player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("AudioTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i += 2)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
}
//SUB
if (player && player->manager && player->manager->subtitle)
{
char ** TrackList = NULL;
player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("SubtitleTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
}
/*
//Teletext
if (player && player->manager && player->manager->teletext)
{
char ** TrackList = NULL;
player->manager->teletext->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("TeletextTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i += 2)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
}
*/
//Chapters
if (player && player->manager && player->manager->chapter)
{
char ** TrackList = NULL;
player->manager->chapter->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("Chapter List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i += 2)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
}
playing = true;
first = true;
player->output->Command(player, OUTPUT_OPEN, NULL);
ret = (player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0);
if (ret && !isHTTP)
playing = ret = (player->playback->Command(player, PLAYBACK_PAUSE, NULL) == 0);
}
}
return ret;
}
bool cPlayback::Stop(void)
{
hal_info("%s playing %d\n", __func__, playing);
if (player && player->playback)
player->playback->Command(player, PLAYBACK_STOP, NULL);
if (player && player->output)
player->output->Command(player, OUTPUT_CLOSE, NULL);
if (player && player->output)
{
player->output->Command(player, OUTPUT_DEL, (void *)"audio");
player->output->Command(player, OUTPUT_DEL, (void *)"video");
player->output->Command(player, OUTPUT_DEL, (void *)"subtitle");
}
if (player && player->playback)
player->playback->Command(player, PLAYBACK_CLOSE, NULL);
playing = false;
return true;
}
bool cPlayback::SetAPid(int pid, bool /* ac3 */)
{
hal_info("%s\n", __func__);
int i = pid;
if (pid != mAudioStream)
{
if (player && player->playback)
player->playback->Command(player, PLAYBACK_SWITCH_AUDIO, (void *)&i);
mAudioStream = pid;
}
return true;
}
bool cPlayback::SetVPid(int /*pid*/)
{
hal_info("%s\n", __func__);
return true;
}
bool cPlayback::SetSubtitlePid(int pid)
{
hal_info("%s\n", __func__);
int i = pid;
if (pid != mSubtitleStream)
{
if (player && player->playback)
player->playback->Command(player, PLAYBACK_SWITCH_SUBTITLE, (void *)&i);
mSubtitleStream = pid;
}
return true;
}
bool cPlayback::SetTeletextPid(int pid)
{
hal_info("%s\n", __func__);
//int i = pid;
if (pid != mTeletextStream)
{
//if (player && player->playback)
// player->playback->Command(player, PLAYBACK_SWITCH_TELETEXT, (void*)&i);
mTeletextStream = pid;
}
return true;
}
bool cPlayback::SetSpeed(int speed)
{
hal_info("%s playing %d speed %d\n", __func__, playing, speed);
if (!decoders_closed)
{
audioDecoder->closeDevice();
videoDecoder->closeDevice();
decoders_closed = true;
usleep(500000);
if (player && player->output && player->playback)
{
player->output->Command(player, OUTPUT_OPEN, NULL);
if (player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0)
playing = true;
}
}
if (!playing)
return false;
if (player && player->playback)
{
int result = 0;
if(nPlaybackSpeed == 0 && speed > 1)
{
result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
}
nPlaybackSpeed = speed;
if (speed > 1)
{
/* direction switch ? */
if (player->playback->BackWard)
{
int r = 0;
result = player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&r);
printf("result = %d\n", result);
}
result = player->playback->Command(player, PLAYBACK_FASTFORWARD, (void *)&speed);
}
else if (speed < 0)
{
/* direction switch ? */
if (player->playback->isForwarding)
{
result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
printf("result = %d\n", result);
}
result = player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&speed);
}
else if (speed == 0)
{
/* konfetti: hmmm accessing the member isn't very proper */
if ((player->playback->isForwarding) || (!player->playback->BackWard))
player->playback->Command(player, PLAYBACK_PAUSE, NULL);
else
{
int _speed = 0; /* means end of reverse playback */
player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&_speed);
}
}
else
{
result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
}
if (init_jump > -1)
{
SetPosition(init_jump, true);
init_jump = -1;
}
if (result != 0)
{
printf("returning false\n");
return false;
}
}
return true;
}
bool cPlayback::GetSpeed(int &speed) const
{
hal_debug("%s\n", __func__);
speed = nPlaybackSpeed;
return true;
}
void cPlayback::GetPts(uint64_t &pts)
{
if (player && player->playback)
player->playback->Command(player, PLAYBACK_PTS, (void *)&pts);
}
// in milliseconds
bool cPlayback::GetPosition(int &position, int &duration)
{
bool got_duration = false;
hal_debug("%s %d %d\n", __func__, position, duration);
/* hack: if the file is growing (timeshift), then determine its length
* by comparing the mtime with the mtime of the xml file */
if (pm == PLAYMODE_TS)
{
struct stat64 s;
if (!stat64(fn_ts.c_str(), &s))
{
if (!playing || last_size != s.st_size)
{
last_size = s.st_size;
time_t curr_time = s.st_mtime;
if (!stat64(fn_xml.c_str(), &s))
{
duration = (curr_time - s.st_mtime) * 1000;
if (!playing)
return true;
got_duration = true;
}
}
}
}
if (!playing)
return false;
if (player && player->playback && !player->playback->isPlaying)
{
hal_info("%s !!!!EOF!!!! < -1\n", __func__);
position = duration + 1000;
return false;
}
int64_t vpts = 0;
if (player && player->playback)
player->playback->Command(player, PLAYBACK_PTS, &vpts);
if (vpts <= 0)
{
//printf("ERROR: vpts==0");
}
else
{
/* workaround for crazy vpts value during timeshift */
if (!got_vpts_ts && pm == PLAYMODE_TS)
{
vpts_ts = vpts;
got_vpts_ts = true;
}
if (got_vpts_ts)
vpts -= vpts_ts;
/* end workaround */
/* len is in nanoseconds. we have 90 000 pts per second. */
position = vpts / 90;
}
if (got_duration)
return true;
int64_t length = 0;
if (player && player->playback)
player->playback->Command(player, PLAYBACK_LENGTH, &length);
if (length <= 0)
{
duration = duration + 1000;
}
else
{
duration = length * 1000;
}
return true;
}
bool cPlayback::SetPosition(int position, bool absolute)
{
hal_info("%s %d\n", __func__, position);
if (playing && first)
{
/* the calling sequence is:
* Start() - paused
* SetPosition() - which fails if not running
* SetSpeed() - to start playing
* so let's remember the initial jump position and later jump to it
*/
init_jump = position;
first = false;
return false;
}
int64_t pos = (position / 1000.0);
if (player && player->playback)
player->playback->Command(player, absolute ? PLAYBACK_SEEK_ABS : PLAYBACK_SEEK, (void *)&pos);
return true;
}
void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language)
{
hal_info("%s\n", __func__);
const int max_numpida = 40;//MAX_PLAYBACK_PIDS defined in neutrino movieplayer.h
*numpida = 0;
if (player && player->playback && player->playback->isPlaying && player->manager && player->manager->audio)
{
char **TrackList = NULL;
player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("AudioTrack List\n");
int i = 0, j = 0;
for (i = 0, j = 0; TrackList[i] != NULL; i += 2, j++)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
if (j < max_numpida)
{
int _pid = 0;
std::string _lang ;
std::istringstream iss(TrackList[i]) ;
iss >> _pid;
iss >> _lang;
if (_pid && !_lang.empty())
{
apids[j] = _pid;
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
if (!strncmp("A_MPEG/L3", TrackList[i + 1], 9))
ac3flags[j] = 3;
if (!strncmp("A_MP3", TrackList[i + 1], 5))
ac3flags[j] = 4;
else if (!strncmp("A_AC3", TrackList[i + 1], 5))
ac3flags[j] = 1;
else if (!strncmp("A_EAC3", TrackList[i + 1], 6))
ac3flags[j] = 7;
else if (!strncmp("A_DTS", TrackList[i + 1], 5))
ac3flags[j] = 6;
else if (!strncmp("A_AAC", TrackList[i + 1], 5))
ac3flags[j] = 5;
else if (!strncmp("A_PCM", TrackList[i + 1], 5))
ac3flags[j] = 0; //todo
else if (!strncmp("A_VORBIS", TrackList[i + 1], 8))
ac3flags[j] = 0; //todo
else if (!strncmp("A_FLAC", TrackList[i + 1], 6))
ac3flags[j] = 0; //todo
else
ac3flags[j] = 0; //todo
std::string _language = "";
_language += _lang;
_language += " - ";
_language += "(";
_language += TrackList[i + 1];
_language += ")";
language[j] = _language;
}
}
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
*numpida = j;
}
}
}
void cPlayback::FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language)
{
hal_info("%s\n", __func__);
int max_numpids = *numpids;
*numpids = 0;
if (player && player->manager && player->manager->subtitle)
{
char **TrackList = NULL;
player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("SubtitleTrack List\n");
int i = 0, j = 0;
for (i = 0, j = 0; TrackList[i] != NULL; i += 2, j++)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
if (j < max_numpids)
{
int _pid = 0;
std::string _lang ;
std::istringstream iss(TrackList[i]) ;
iss >> _pid;
iss >> _lang;
if (_pid && !_lang.empty())
{
pids[j] = _pid;
language[j] = _lang;
}
}
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
*numpids = j;
}
}
}
void cPlayback::FindAllTeletextsubtitlePids(int */*pids*/, unsigned int *numpids, std::string */*language*/, int */*mags*/, int */*pages*/)
{
hal_info("%s\n", __func__);
//int max_numpids = *numpids;
*numpids = 0;
/* if (player && player->manager && player->manager->teletext)
{
char **TrackList = NULL;
player->manager->teletext->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("Teletext List\n");
int i = 0, j = 0;
for (i = 0, j = 0; TrackList[i] != NULL; i += 2)
{
int type = 0;
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
if (j < max_numpids)
{
int _pid;
if (2 != sscanf(TrackList[i], "%d %*s %d %*d %*d", &_pid, &type))
continue;
if (type != 2 && type != 5) // return subtitles only
continue;
pids[j] = _pid;
language[j] = std::string(TrackList[i]);
j++;
}
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
*numpids = j;
}
} */
}
int cPlayback::GetTeletextPid(void)
{
hal_info("%s\n", __func__);
int pid = -1;
/* if (player && player->manager && player->manager->teletext)
{
char **TrackList = NULL;
player->manager->teletext->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("Teletext List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i += 2)
{
int type = 0;
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
if (pid < 0)
{
if (2 != sscanf(TrackList[i], "%*d %d %*s %d %*d %*d", &pid, &type))
continue;
if (type != 1)
pid = -1;
}
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
} */
printf("teletext pid id %d (0x%x)\n", pid, pid);
return pid;
}
/* dummy functions for subtitles */
void cPlayback::FindAllSubs(int * /*pids*/, unsigned int * /*supp*/, unsigned int *num, std::string * /*lang*/)
{
*num = 0;
}
bool cPlayback::SelectSubtitles(int /*pid*/, std::string /*charset*/)
{
return false;
}
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
{
positions.clear();
titles.clear();
if (player && player->manager && player->manager->chapter)
{
char **TrackList = NULL;
player->manager->chapter->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL)
{
printf("%s: Chapter List\n", __func__);
int i = 0;
for (i = 0; TrackList[i] != NULL; i += 2)
{
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
int pos = atoi(TrackList[i]);
std::string title(TrackList[i + 1]);
positions.push_back(pos);
titles.push_back(title);
free(TrackList[i]);
free(TrackList[i + 1]);
}
free(TrackList);
}
}
}
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current)
{
playlists.clear();
titles.clear();
current = 0;
}
void cPlayback::SetTitle(int /*title*/)
{
}
void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
{
keys.clear();
values.clear();
char **metadata = NULL;
if (player && player->playback)
{
player->playback->Command(player, PLAYBACK_METADATA, &metadata);
if (metadata)
{
for (char **m = metadata; *m;)
{
keys.push_back(*m);
free(*m++);
values.push_back(*m);
free(*m++);
}
free(metadata);
}
}
}
cPlayback::cPlayback(int num __attribute__((unused)))
{
hal_info("%s\n", __func__);
playing = false;
decoders_closed = false;
first = false;
player = NULL;
}
cPlayback::~cPlayback()
{
hal_info("%s\n", __func__);
RequestAbort();
mutex.lock();
if (player)
{
free(player);
player = NULL;
}
mutex.unlock();
}
void cPlayback::RequestAbort()
{
if (player && player->playback)
{
hal_info("%s\n", __func__);
mutex.lock();
if (player && player->playback && player->playback->isPlaying)
{
Stop();
player->playback->abortRequested = 1;
}
else if(player->playback->isHttp && !player->playback->isPlaying &&!player->playback->abortRequested)
{
player->playback->abortRequested = 1;
}
mutex.unlock();
}
}
bool cPlayback::IsPlaying()
{
if (player && player->playback)
return player->playback->isPlaying;
return false;
}
uint64_t cPlayback::GetReadCount()
{
if (player && player->playback)
{
return player->playback->readCount;
}
return 0;
}
AVFormatContext *cPlayback::GetAVFormatContext()
{
if (player && player->container && player->container->selectedContainer)
{
player->container->selectedContainer->Command(player, CONTAINER_GET_AVFCONTEXT, avft);
}
return avft;
}
void cPlayback::ReleaseAVFormatContext()
{
avft->streams = NULL;
avft->nb_streams = NULL;
}
#if 0
bool cPlayback::IsPlaying(void) const
{
hal_info("%s\n", __func__);
/* konfetti: there is no event/callback mechanism in libeplayer2
* so in case of ending playback we have no information on a
* terminated stream currently (or did I oversee it?).
* So let's ask the player the state.
*/
if (playing)
{
return player->playback->isPlaying;
}
return playing;
}
#endif

View File

@@ -1,92 +0,0 @@
#ifndef __PLAYBACK_LIBEPLAYER3_H__
#define __PLAYBACK_LIBEPLAYER3_H__
#include <string>
#include <vector>
#include <OpenThreads/Mutex>
typedef enum
{
PLAYMODE_TS = 0,
PLAYMODE_FILE
} playmode_t;
struct AVFormatContext;
class cPlayback
{
friend class CStreamInfo2;
private:
static OpenThreads::Mutex mutex;
bool enabled;
bool playing, first;
bool no_probe;
bool got_vpts_ts;
int nPlaybackSpeed;
int mAudioStream;
int mSubtitleStream;
int mTeletextStream;
int64_t vpts_ts;
bool Stop(void);
bool decoders_closed;
playmode_t pm;
std::string fn_ts;
std::string fn_xml;
off64_t last_size;
int init_jump;
AVFormatContext *avft;
public:
cPlayback(int num = 0);
~cPlayback();
bool Open(playmode_t PlayMode);
void Close(void);
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "", std::string filename2 = "");
bool Start(std::string filename, std::string headers = "", std::string filename2 = "");
bool SetAPid(int pid, bool ac3 = false);
bool SetVPid(int /*pid*/);
bool SetSubtitlePid(int pid);
bool SetTeletextPid(int pid);
int GetAPid(void) { return mAudioStream; }
int GetVPid(void) { return 0; }
int GetSubtitlePid(void) { return mSubtitleStream; }
int GetTeletextPid(void);
bool SetSpeed(int speed);
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration);
void GetPts(uint64_t &pts);
bool SetPosition(int position, bool absolute = false);
void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language);
void FindAllSubs(int *pids, unsigned int *supported, unsigned int *numpida, std::string *language);
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language) { FindAllSubs((int*) pids, (unsigned int*) supported, (unsigned int*) numpida, language); };
bool SelectSubtitles(int pid, std::string charset = "");
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
void FindAllTeletextsubtitlePids(int */*pids*/, unsigned int *numpidt, std::string */*tlanguage*/, int */*mags*/, int */*pages*/);
void RequestAbort(void);
bool IsPlaying(void);
uint64_t GetReadCount(void);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current);
void SetTitle(int title);
#if 0
// Functions that are not used by movieplayer.cpp:
bool GetOffset(off64_t &offset);
bool IsPlaying(void) const;
bool IsEnabled(void) const;
void *GetHandle(void);
void *GetDmHandle(void);
int GetCurrPlaybackSpeed(void) const;
void PlaybackNotify(int Event, void *pData, void *pTag);
void DMNotify(int Event, void *pTsBuf, void *Tag);
#endif
};
#endif // __PLAYBACK_LIBEPLAYER3_H__

View File

@@ -1,403 +0,0 @@
/*
* (C)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <inttypes.h>
#include <cstdio>
#include <cstring>
#include <pthread.h>
#include <aio.h>
#include "record_lib.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_RECORD, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_RECORD, this, args)
/* helper function to call the cpp thread loop */
void *execute_record_thread(void *c)
{
cRecord *obj = (cRecord *)c;
obj->RecordThread();
return NULL;
}
void *execute_writer_thread(void *c)
{
cRecord *obj = (cRecord *)c;
obj->WriterThread();
return NULL;
}
cRecord::cRecord(int num, int bs_dmx, int bs)
{
hal_info("%s %d\n", __func__, num);
dmx = NULL;
record_thread_running = false;
file_fd = -1;
exit_flag = RECORD_STOPPED;
dmx_num = num;
bufsize = bs;
bufsize_dmx = bs_dmx;
failureCallback = NULL;
failureData = NULL;
}
cRecord::~cRecord()
{
hal_info("%s: calling ::Stop()\n", __func__);
Stop();
hal_info("%s: end\n", __func__);
}
bool cRecord::Open(void)
{
hal_info("%s\n", __func__);
exit_flag = RECORD_STOPPED;
return true;
}
#if 0
// unused
void cRecord::Close(void)
{
hal_info("%s: \n", __func__);
}
#endif
bool cRecord::Start(int fd, unsigned short vpid, unsigned short *apids, int numpids, uint64_t)
{
hal_info("%s: fd %d, vpid 0x%03x\n", __func__, fd, vpid);
int i;
if (!dmx)
dmx = new cDemux(dmx_num);
dmx->Open(DMX_TP_CHANNEL, NULL, bufsize_dmx);
dmx->pesFilter(vpid);
for (i = 0; i < numpids; i++)
dmx->addPid(apids[i]);
file_fd = fd;
exit_flag = RECORD_RUNNING;
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
perror("posix_fadvise");
i = pthread_create(&record_thread, 0, execute_record_thread, this);
if (i != 0)
{
exit_flag = RECORD_FAILED_READ;
errno = i;
hal_info("%s: error creating thread! (%m)\n", __func__);
delete dmx;
dmx = NULL;
return false;
}
record_thread_running = true;
return true;
}
bool cRecord::Stop(void)
{
hal_info("%s\n", __func__);
if (exit_flag != RECORD_RUNNING)
hal_info("%s: status not RUNNING? (%d)\n", __func__, exit_flag);
exit_flag = RECORD_STOPPED;
if (record_thread_running)
pthread_join(record_thread, NULL);
record_thread_running = false;
/* We should probably do that from the destructor... */
if (!dmx)
hal_info("%s: dmx == NULL?\n", __func__);
else
delete dmx;
dmx = NULL;
if (file_fd != -1)
close(file_fd);
else
hal_info("%s: file_fd not open??\n", __func__);
file_fd = -1;
return true;
}
bool cRecord::ChangePids(unsigned short /*vpid*/, unsigned short *apids, int numapids)
{
std::vector<pes_pids> pids;
int j;
bool found;
unsigned short pid;
hal_info("%s\n", __func__);
if (!dmx) {
hal_info("%s: DMX = NULL\n", __func__);
return false;
}
pids = dmx->pesfds;
/* the first PID is the video pid, so start with the second PID... */
for (std::vector<pes_pids>::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) {
found = false;
pid = (*i).pid;
for (j = 0; j < numapids; j++) {
if (pid == apids[j]) {
found = true;
break;
}
}
if (!found)
dmx->removePid(pid);
}
for (j = 0; j < numapids; j++) {
found = false;
for (std::vector<pes_pids>::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) {
if ((*i).pid == apids[j]) {
found = true;
break;
}
}
if (!found)
dmx->addPid(apids[j]);
}
return true;
}
bool cRecord::AddPid(unsigned short pid)
{
std::vector<pes_pids> pids;
hal_info("%s: \n", __func__);
if (!dmx) {
hal_info("%s: DMX = NULL\n", __func__);
return false;
}
pids = dmx->pesfds;
for (std::vector<pes_pids>::const_iterator i = pids.begin(); i != pids.end(); ++i) {
if ((*i).pid == pid)
return true; /* or is it an error to try to add the same PID twice? */
}
return dmx->addPid(pid);
}
void cRecord::WriterThread()
{
char threadname[17];
strncpy(threadname, "WriterThread", sizeof(threadname));
threadname[16] = 0;
prctl (PR_SET_NAME, (unsigned long)&threadname);
unsigned int chunk = 0;
while (!sem_wait(&sem)) {
if (!io_len[chunk]) // empty, assume end of recording
return;
unsigned char *p_buf = io_buf[chunk];
size_t p_len = io_len[chunk];
while (p_len) {
ssize_t written = write(file_fd, p_buf, p_len);
if (written < 0)
break;
p_len -= written;
p_buf += written;
}
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
perror("posix_fadvise");
chunk++;
chunk %= RECORD_WRITER_CHUNKS;
}
}
void cRecord::RecordThread()
{
hal_info("%s: begin\n", __func__);
char threadname[17];
strncpy(threadname, "RecordThread", sizeof(threadname));
threadname[16] = 0;
prctl (PR_SET_NAME, (unsigned long)&threadname);
int readsize = bufsize / 16;
int buf_pos = 0;
int count = 0;
int queued = 0;
uint8_t *buf;
struct aiocb a;
buf = (uint8_t *)malloc(bufsize);
hal_info("BUFSIZE=0x%x READSIZE=0x%x\n", bufsize, readsize);
if (!buf)
{
exit_flag = RECORD_FAILED_MEMORY;
hal_info("%s: unable to allocate buffer! (out of memory)\n", __func__);
if (failureCallback)
failureCallback(failureData);
hal_info("%s: end\n", __func__);
pthread_exit(NULL);
}
int val = fcntl(file_fd, F_GETFL);
if (fcntl(file_fd, F_SETFL, val|O_APPEND))
hal_info("%s: O_APPEND? (%m)\n", __func__);
memset(&a, 0, sizeof(a));
a.aio_fildes = file_fd;
a.aio_sigevent.sigev_notify = SIGEV_NONE;
dmx->Start();
int overflow_count = 0;
bool overflow = false;
int r = 0;
while (exit_flag == RECORD_RUNNING)
{
if (buf_pos < bufsize)
{
if (overflow_count) {
hal_info("%s: Overflow cleared after %d iterations\n", __func__, overflow_count);
overflow_count = 0;
}
int toread = bufsize - buf_pos;
if (toread > readsize)
toread = readsize;
ssize_t s = dmx->Read(buf + buf_pos, toread, 50);
hal_debug("%s: buf_pos %6d s %6d / %6d\n", __func__,
buf_pos, (int)s, bufsize - buf_pos);
if (s < 0)
{
if (errno != EAGAIN && (errno != EOVERFLOW || !overflow))
{
hal_info("%s: read failed: %m\n", __func__);
exit_flag = RECORD_FAILED_READ;
state = REC_STATUS_OVERFLOW;
break;
}
}
else
{
overflow = false;
buf_pos += s;
if (count > 100)
{
if (buf_pos < bufsize / 2)
continue;
}
else
{
count += 1;
}
}
}
else
{
if (!overflow)
overflow_count = 0;
overflow = true;
if (!(overflow_count % 10))
hal_info("%s: buffer full! Overflow? (%d)\n", __func__, ++overflow_count);
state = REC_STATUS_SLOW;
}
r = aio_error(&a);
if (r == EINPROGRESS)
{
hal_debug("%s: aio in progress, free: %d\n", __func__, bufsize - buf_pos);
continue;
}
// not calling aio_return causes a memory leak --martii
r = aio_return(&a);
if (r < 0)
{
exit_flag = RECORD_FAILED_FILE;
hal_debug("%s: aio_return = %d (%m)\n", __func__, r);
break;
}
else
hal_debug("%s: aio_return = %d, free: %d\n", __func__, r, bufsize - buf_pos);
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
perror("posix_fadvise");
if (queued)
{
memmove(buf, buf + queued, buf_pos - queued);
buf_pos -= queued;
}
queued = buf_pos;
a.aio_buf = buf;
a.aio_nbytes = queued;
r = aio_write(&a);
if (r)
{
hal_info("%s: aio_write %d (%m)\n", __func__, r);
exit_flag = RECORD_FAILED_FILE;
break;
}
}
dmx->Stop();
while (true) /* write out the unwritten buffer content */
{
hal_debug("%s: run-out write, buf_pos %d\n", __func__, buf_pos);
r = aio_error(&a);
if (r == EINPROGRESS)
{
usleep(50000);
continue;
}
r = aio_return(&a);
if (r < 0)
{
exit_flag = RECORD_FAILED_FILE;
hal_info("%s: aio_result: %d (%m)\n", __func__, r);
break;
}
if (!queued)
break;
memmove(buf, buf + queued, buf_pos - queued);
buf_pos -= queued;
queued = buf_pos;
a.aio_buf = buf;
a.aio_nbytes = queued;
r = aio_write(&a);
}
free(buf);
#if 0
// TODO: do we need to notify neutrino about failing recording?
CEventServer eventServer;
eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
stream2file_status2_t s;
s.status = exit_flag;
strncpy(s.filename,basename(myfilename),512);
s.filename[511] = '\0';
strncpy(s.dir,dirname(myfilename),100);
s.dir[99] = '\0';
eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
#endif
if ((exit_flag != RECORD_STOPPED) && failureCallback)
failureCallback(failureData);
hal_info("%s: end\n", __func__);
pthread_exit(NULL);
}
int cRecord::GetStatus()
{
return (exit_flag == RECORD_STOPPED) ? REC_STATUS_STOPPED : REC_STATUS_OK;
}
void cRecord::ResetStatus()
{
return;
}

View File

@@ -1,57 +0,0 @@
#ifndef __RECORD_LIB_H__
#define __RECORD_LIB_H__
#include <semaphore.h>
#include "dmx_hal.h"
#define REC_STATUS_OK 0
#define REC_STATUS_SLOW 1
#define REC_STATUS_OVERFLOW 2
#define REC_STATUS_STOPPED 4
typedef enum {
RECORD_RUNNING,
RECORD_STOPPED,
RECORD_FAILED_READ, /* failed to read from DMX */
RECORD_FAILED_OVERFLOW, /* cannot write fast enough */
RECORD_FAILED_FILE, /* cannot write to file */
RECORD_FAILED_MEMORY /* out of memory */
} record_state_t;
class cRecord
{
private:
int file_fd;
int dmx_num;
cDemux *dmx;
pthread_t record_thread;
bool record_thread_running;
record_state_t exit_flag;
int state;
int bufsize;
int bufsize_dmx;
void (*failureCallback)(void *);
void *failureData;
sem_t sem;
#define RECORD_WRITER_CHUNKS 16
unsigned char *io_buf[RECORD_WRITER_CHUNKS];
size_t io_len[RECORD_WRITER_CHUNKS];
public:
cRecord(int num = 0, int bs_dmx = 2048 * 1024, int bs = 4096 * 1024);
void setFailureCallback(void (*f)(void *), void *d) { failureCallback = f; failureData = d; }
~cRecord();
bool Open();
bool Start(int fd, unsigned short vpid, unsigned short *apids, int numapids, uint64_t ch = 0);
bool Stop(void);
bool AddPid(unsigned short pid);
int GetStatus();
void ResetStatus();
bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids);
void RecordThread();
void WriterThread();
};
#endif // __RECORD_LIB_H__

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
#ifndef __VIDEO_LIB_H__
#define __VIDEO_LIB_H__
#include <linux/dvb/video.h>
#include "cs_types.h"
#include "dmx_hal.h"
typedef struct cs_vs_format_t
{
char format[16];
} cs_vs_format_struct_t;
typedef enum {
ANALOG_SD_RGB_CINCH = 0x00,
ANALOG_SD_YPRPB_CINCH,
ANALOG_HD_RGB_CINCH,
ANALOG_HD_YPRPB_CINCH,
ANALOG_SD_RGB_SCART = 0x10,
ANALOG_SD_YPRPB_SCART,
ANALOG_HD_RGB_SCART,
ANALOG_HD_YPRPB_SCART,
ANALOG_SCART_MASK = 0x10
} analog_mode_t;
typedef enum {
COLORFORMAT_RGB = 0x10, // keep compatible with analog_mode_t
COLORFORMAT_YUV,
COLORFORMAT_CVBS,
COLORFORMAT_SVIDEO,
COLORFORMAT_HDMI_AUTO,
COLORFORMAT_HDMI_RGB,
COLORFORMAT_HDMI_YCBCR444,
COLORFORMAT_HDMI_YCBCR422,
COLORFORMAT_HDMI_YCBCR420
} COLOR_FORMAT;
typedef enum {
VIDEO_FORMAT_MPEG2 = 0,
VIDEO_FORMAT_MPEG4_H264,
VIDEO_FORMAT_VC1,
VIDEO_FORMAT_JPEG,
VIDEO_FORMAT_GIF,
VIDEO_FORMAT_PNG,
VIDEO_FORMAT_MPEG4_H265,
VIDEO_FORMAT_AVS = 16
} VIDEO_FORMAT;
typedef enum {
VIDEO_SD = 0,
VIDEO_HD,
VIDEO_120x60i,
VIDEO_320x240i,
VIDEO_1440x800i,
VIDEO_360x288i
} VIDEO_DEFINITION;
typedef enum {
VIDEO_FRAME_RATE_23_976 = 0,
VIDEO_FRAME_RATE_24,
VIDEO_FRAME_RATE_25,
VIDEO_FRAME_RATE_29_97,
VIDEO_FRAME_RATE_30,
VIDEO_FRAME_RATE_50,
VIDEO_FRAME_RATE_59_94,
VIDEO_FRAME_RATE_60
} VIDEO_FRAME_RATE;
typedef enum {
DISPLAY_AR_1_1,
DISPLAY_AR_4_3,
DISPLAY_AR_14_9,
DISPLAY_AR_16_9,
DISPLAY_AR_20_9,
DISPLAY_AR_RAW
} DISPLAY_AR;
typedef enum {
/* FIX for HD51 mix-up of letterbox / panscan
Standard is 1. PANSCAN 2. LETTERBOX
If next drivers are correct please revert
this and pzapit.cpp */
DISPLAY_AR_MODE_LETTERBOX = 0,
DISPLAY_AR_MODE_PANSCAN,
DISPLAY_AR_MODE_NONE,
DISPLAY_AR_MODE_PANSCAN2
} DISPLAY_AR_MODE;
typedef enum {
VIDEO_DB_DR_NEITHER = 0,
VIDEO_DB_ON,
VIDEO_DB_DR_BOTH
} VIDEO_DB_DR;
typedef enum {
VIDEO_PLAY_STILL = 0,
VIDEO_PLAY_CLIP,
VIDEO_PLAY_TRICK,
VIDEO_PLAY_MOTION,
VIDEO_PLAY_MOTION_NO_SYNC
} VIDEO_PLAY_MODE;
typedef enum {
VIDEO_STD_NTSC,
VIDEO_STD_SECAM,
VIDEO_STD_PAL,
VIDEO_STD_480P,
VIDEO_STD_576P,
VIDEO_STD_720P60,
VIDEO_STD_1080I60,
VIDEO_STD_720P50,
VIDEO_STD_1080I50,
VIDEO_STD_1080P30,
VIDEO_STD_1080P24,
VIDEO_STD_1080P25,
VIDEO_STD_1080P50,
VIDEO_STD_1080P60,
VIDEO_STD_1080P2397,
VIDEO_STD_1080P2997,
VIDEO_STD_2160P24,
VIDEO_STD_2160P25,
VIDEO_STD_2160P30,
VIDEO_STD_2160P50,
VIDEO_STD_AUTO,
VIDEO_STD_MAX = VIDEO_STD_AUTO
} VIDEO_STD;
typedef enum {
VIDEO_HDMI_CEC_MODE_OFF = 0,
VIDEO_HDMI_CEC_MODE_TUNER = 3,
VIDEO_HDMI_CEC_MODE_RECORDER = 1
} VIDEO_HDMI_CEC_MODE;
typedef enum
{
VIDEO_CONTROL_BRIGHTNESS = 0,
VIDEO_CONTROL_CONTRAST,
VIDEO_CONTROL_SATURATION,
VIDEO_CONTROL_HUE,
VIDEO_CONTROL_SHARPNESS,
VIDEO_CONTROL_BLOCK_NOISE_REDUCTION,
VIDEO_CONTROL_MOSQUITO_NOISE_REDUCTION,
VIDEO_CONTROL_DIGITAL_CONTOUR_REMOVAL,
VIDEO_CONTROL_AUTO_FLESH,
VIDEO_CONTROL_GREEN_BOOST,
VIDEO_CONTROL_BLUE_BOOST,
VIDEO_CONTROL_DYNAMIC_CONTRAST,
VIDEO_CONTROL_SCALER_SHARPNESS,
VIDEO_CONTROL_ZAPPING_MODE,
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
} VIDEO_CONTROL;
class cDemux;
class cPlayback;
class cVideo
{
friend class cPlayback;
friend class cDemux;
private:
/* video device */
int fd;
unsigned int devnum;
/* apparently we cannot query the driver's state
=> remember it */
video_play_state_t playstate;
int /*vidDispMode_t*/ croppingMode;
int /*vidOutFmt_t*/ outputformat;
VIDEO_FORMAT StreamType;
VIDEO_DEFINITION VideoDefinition;
DISPLAY_AR DisplayAR;
VIDEO_PLAY_MODE SyncMode;
DISPLAY_AR_MODE ARMode;
VIDEO_DB_DR eDbDr;
DISPLAY_AR PictureAR;
VIDEO_FRAME_RATE FrameRate;
int video_standby;
int brightness;
int contrast;
int saturation;
int hue;
int sharpness;
int block_noise_reduction;
int mosquito_noise_reduction;
int digital_contour_removal;
int auto_flesh;
int green_boost;
int blue_boost;
int dynamic_contrast;
int scaler_sharpness;
int zapping_mode;
/* used internally by dmx */
int64_t GetPTS(void);
public:
/* constructor & destructor */
cVideo(int mode, void *, void *, unsigned int unit = 0);
~cVideo(void);
/* used internally by playback */
void openDevice(void);
void closeDevice(void);
void * GetTVEnc() { return NULL; };
void * GetTVEncSD() { return NULL; };
/* aspect ratio */
int getAspectRatio(void);
void getPictureInfo(int &width, int &height, int &rate);
int setAspectRatio(int aspect, int mode);
/* cropping mode */
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
/* get play state */
int getPlayState(void);
/* blank on freeze */
int getBlank(void);
int setBlank(int enable);
/* change video play state. Parameters are all unused. */
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
int Stop(bool blank = true);
bool Pause(void);
/* get video system infos */
int GetVideoSystem(void);
/* when system = -1 then use current video system */
void GetVideoSystemFormatName(cs_vs_format_t* format, int system);
/* set video_system */
int SetVideoSystem(int video_system, bool remember = true);
int SetStreamType(VIDEO_FORMAT type);
void SetSyncMode(AVSYNC_TYPE mode);
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
void SetCECAutoView(bool);
void SetCECAutoStandby(bool);
bool ShowPicture(const char * fname);
void StopPicture();
void Standby(unsigned int bOn);
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600, int startx = 0, int starty = 0, int endx = 1279, int endy = 719);
void SetControl(int, int);
void setContrast(int val);
void SetVideoMode(analog_mode_t mode);
void SetDBDR(int) { return; };
void SetAudioHandle(void *) { return; };
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
int OpenVBI(int) { return 0; };
int CloseVBI(void) { return 0; };
int StartVBI(unsigned short) { return 0; };
int StopVBI(void) { return 0; };
void SetDemux(cDemux *dmx);
void SetColorFormat(COLOR_FORMAT color_format);
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
};
#endif // __VIDEO_LIB_H__

View File

@@ -1,27 +0,0 @@
noinst_LTLIBRARIES = libduckbox.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libeplayer3-sh4/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = \
@AVFORMAT_LIBS@ \
@AVUTIL_LIBS@ \
@AVCODEC_LIBS@ \
@SWRESAMPLE_LIBS@ \
-lpthread -lasound -lass -lrt
libduckbox_la_SOURCES = \
hardware_caps.c \
dmx.cpp \
video.cpp \
audio.cpp \
audio_mixer.cpp \
init.cpp \
playback_libeplayer3.cpp \
record.cpp
AM_CPPFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS

View File

@@ -1 +0,0 @@
../libspark/audio.cpp

View File

@@ -1 +0,0 @@
../libspark/audio_lib.h

View File

@@ -1 +0,0 @@
../libspark/audio_mixer.cpp

View File

@@ -1 +0,0 @@
../libspark/audio_mixer.h

View File

@@ -1 +0,0 @@
../libspark/dmx.cpp

View File

@@ -1,353 +0,0 @@
/*
* determine the capabilities of the hardware.
* part of libstb-hal
*
* (C) 2010-2012 Stefan Seyfried
*
* License: GPL v2 or later
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <hardware_caps.h>
static int initialized = 0;
static hw_caps_t caps;
hw_caps_t *get_hwcaps(void)
{
if (initialized)
return &caps;
memset(&caps, 0, sizeof(hw_caps_t));
initialized = 1;
char buf[64];
int len = -1;
int fd = open("/proc/stb/info/model", O_RDONLY);
caps.display_can_set_brightness = 0;
caps.display_can_deepstandby = 0;
caps.display_has_statusline = 0;
caps.can_cpufreq = 1;
if (fd != -1) {
len = read(fd, buf, sizeof(buf) - 1);
close(fd);
}
if (len > 0) {
buf[len] = 0;
if (!strncmp(buf, "atevio7500", 10)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 12;
}
else if (!strncmp(buf, "ufs912", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 16;
}
else if (!strncmp(buf, "ufs913", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 16;
}
else if (!strncmp(buf, "ufs922", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 16;
}
else if (!strncmp(buf, "ufs910", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 16;
}
else if (!strncmp(buf, "hdbox", 5)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 12;
}
else if (!strncmp(buf, "octagon1008", 11)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 8;
}
else if (!strncmp(buf, "hs7110", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
}
else if (!strncmp(buf, "hs7810a", 7)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
}
else if (!strncmp(buf, "hs7119", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
}
else if (!strncmp(buf, "hs7819", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
}
else if (!strncmp(buf, "dp7000", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
}
else if (!strncmp(buf, "cuberevo-mini", 14)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 2;
}
else if (!strncmp(buf, "cuberevo-mini2", 14)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 14;
}
else if (!strncmp(buf, "cuberevo-250hd", 4)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 0;
}
else if (!strncmp(buf, "cuberevo-2000hd", 15)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 0;
}
else if (!strncmp(buf, "cuberevo", 8)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 2;
}
else if (!strncmp(buf, "cuberevo-3000hd", 14)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 2;
}
else if (!strncmp(buf, "ipbox9900", 9)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 2;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 2;
}
else if (!strncmp(buf, "ipbox99", 7)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 1;
caps.has_CI = 0;
}
else if (!strncmp(buf, "ipbox55", 7)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 0;
}
else if (!strncmp(buf, "tf7700", 6)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 0;
caps.has_fan = 0;
caps.has_CI = 2;
}
else if (!strncmp(buf, "hl101", 5)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 1;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.has_SCART_input = 1;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 8;
}
else if (!strncmp(buf, "arivalink200", 12)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 0;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 2;
caps.display_can_set_brightness = 0;
}
else if ((!strncasecmp(buf, "nbox", 4)) ||
(!strncasecmp(buf, "adb_box", 7))) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 0;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 1;
caps.has_CI = 2;
caps.display_can_set_brightness = 1;
}
else if ((!strncasecmp(buf, "sagemcom88", 10)) ||
(!strncasecmp(buf, "esi_88", 6)) ||
(!strncasecmp(buf, "esi88", 5)) ||
(!strncasecmp(buf, "dsi87", 5))) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 0;
caps.has_HDMI = 1;
caps.has_SCART = 1;
caps.can_cec = 1;
caps.has_fan = 1;
caps.has_CI = 0;
caps.display_can_set_brightness = 1;
}
else if (!strncasecmp(buf, "dsi87", 5)) {
strcpy(caps.boxvendor, "DUCKBOX");
strcpy(caps.boxname, buf);
caps.can_shutdown = 0;
caps.has_HDMI = 1;
caps.has_SCART = 0;
caps.can_cec = 1;
caps.has_fan = 0;
caps.has_CI = 0;
caps.display_can_set_brightness = 0;
}
else {
strcpy(caps.boxvendor, "unknown");
strcpy(caps.boxname, buf);
}
}
else
strcpy(caps.boxname, "(unknown model)");
strcpy(caps.boxarch,caps.boxname);
return &caps;
}

View File

@@ -1,55 +0,0 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/dvb/dmx.h>
#include "init.h"
#include "pwrmngr.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
static bool initialized = false;
void hal_api_init()
{
if (!initialized)
hal_debug_init();
hal_info("%s begin, initialized=%d, debug=0x%02x\n", __FUNCTION__, (int)initialized, debuglevel);
if (!initialized)
{
/* this is a strange hack: the drivers seem to only work correctly after
* demux0 has been used once. After that, we can use demux1,2,... */
struct dmx_pes_filter_params p;
int dmx = open("/dev/dvb/adapter0/demux0", O_RDWR|O_CLOEXEC);
if (dmx < 0)
hal_info("%s: ERROR open /dev/dvb/adapter0/demux0 (%m)\n", __func__);
else
{
memset(&p, 0, sizeof(p));
p.output = DMX_OUT_DECODER;
p.input = DMX_IN_FRONTEND;
p.flags = DMX_IMMEDIATE_START;
p.pes_type = DMX_PES_VIDEO;
ioctl(dmx, DMX_SET_PES_FILTER, &p);
ioctl(dmx, DMX_STOP);
close(dmx);
}
}
initialized = true;
hal_info("%s end\n", __FUNCTION__);
}
void hal_api_exit()
{
hal_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized);
initialized = false;
}

View File

@@ -1 +0,0 @@
../libspark/playback_libeplayer3.cpp

View File

@@ -1 +0,0 @@
../libspark/playback_libeplayer3.h

View File

@@ -1 +0,0 @@
../libspark/record_lib.h

View File

@@ -1 +0,0 @@
../libspark/video.cpp

View File

@@ -1 +0,0 @@
../libspark/video_lib.h

View File

@@ -1,22 +0,0 @@
noinst_LTLIBRARIES = libdvbci.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = -lpthread -lcrypto -lssl
libdvbci_la_SOURCES = \
dvbci_session.cpp \
dvbci_mmi.cpp \
dvbci_camgr.cpp \
misc.cpp \
descrambler.cpp \
dh_rsa_misc.cpp \
aes_xcbc_mac.cpp \
dvbci_ccmgr.cpp \
dvbci_appmgr.cpp \
dvbci_datetimemgr.cpp \
dvbci_resmgr.cpp

View File

@@ -1,39 +0,0 @@
/* DH */
unsigned char dh_p[256] = { /* prime */
0xd6, 0x27, 0x14, 0x7a, 0x7c, 0x0c, 0x26, 0x63, 0x9d, 0x82, 0xeb, 0x1f, 0x4a, 0x18, 0xff, 0x6c,
0x34, 0xad, 0xea, 0xa6, 0xc0, 0x23, 0xe6, 0x65, 0xfc, 0x8e, 0x32, 0xc3, 0x33, 0xf4, 0x91, 0xa7,
0xcc, 0x88, 0x58, 0xd7, 0xf3, 0xb3, 0x17, 0x5e, 0xb0, 0xa8, 0xeb, 0x5c, 0xd4, 0xd8, 0x3a, 0xae,
0x8e, 0x75, 0xa1, 0x50, 0x5f, 0x5d, 0x67, 0xc5, 0x40, 0xf4, 0xb3, 0x68, 0x35, 0xd1, 0x3a, 0x4c,
0x93, 0x7f, 0xca, 0xce, 0xdd, 0x83, 0x29, 0x01, 0xc8, 0x4b, 0x76, 0x81, 0x56, 0x34, 0x83, 0x31,
0x92, 0x72, 0x65, 0x7b, 0xac, 0xd9, 0xda, 0xa9, 0xd1, 0xd3, 0xe5, 0x77, 0x58, 0x6f, 0x5b, 0x44,
0x3e, 0xaf, 0x7f, 0x6d, 0xf5, 0xcf, 0x0a, 0x80, 0x0d, 0xa5, 0x56, 0x4f, 0x4b, 0x85, 0x41, 0x0f,
0x13, 0x41, 0x06, 0x1f, 0xf3, 0xd9, 0x65, 0x36, 0xae, 0x47, 0x41, 0x1f, 0x1f, 0xe0, 0xde, 0x69,
0xe5, 0x86, 0x2a, 0xa1, 0xf2, 0x48, 0x02, 0x92, 0x68, 0xa6, 0x37, 0x9f, 0x76, 0x4f, 0x7d, 0x94,
0x5d, 0x10, 0xe5, 0xab, 0x5d, 0xb2, 0xf3, 0x12, 0x8c, 0x79, 0x03, 0x92, 0xa6, 0x7f, 0x8a, 0x78,
0xb0, 0xba, 0xc5, 0xb5, 0x31, 0xc5, 0xc8, 0x22, 0x6e, 0x29, 0x02, 0x40, 0xab, 0xe7, 0x5c, 0x23,
0x33, 0x7f, 0xcb, 0x86, 0xc7, 0xb4, 0xfd, 0xaa, 0x44, 0xcd, 0x9c, 0x9f, 0xba, 0xac, 0x3a, 0xcf,
0x7e, 0x31, 0x5f, 0xa8, 0x47, 0xce, 0xca, 0x1c, 0xb4, 0x77, 0xa0, 0xec, 0x9a, 0x46, 0xd4, 0x79,
0x7b, 0x64, 0xbb, 0x6c, 0x91, 0xb2, 0x38, 0x01, 0x65, 0x11, 0x45, 0x9f, 0x62, 0x08, 0x6f, 0x31,
0xcf, 0xc4, 0xba, 0xdc, 0xd0, 0x03, 0x91, 0xf1, 0x18, 0x1f, 0xcb, 0x4d, 0xfc, 0x73, 0x5a, 0xa2,
0x15, 0xb8, 0x3c, 0x8d, 0x80, 0x92, 0x1c, 0xa1, 0x03, 0xd0, 0x83, 0x2f, 0x5f, 0xe3, 0x07, 0x69
};
unsigned char dh_g[256] = { /* generator */
0x95, 0x7d, 0xd1, 0x49, 0x68, 0xc1, 0xa5, 0xf1, 0x48, 0xe6, 0x50, 0x4f, 0xa1, 0x10, 0x72, 0xc4,
0xef, 0x12, 0xec, 0x2d, 0x94, 0xbe, 0xc7, 0x20, 0x2c, 0x94, 0xf9, 0x68, 0x67, 0x0e, 0x22, 0x17,
0xb5, 0x5c, 0x0b, 0xca, 0xac, 0x9f, 0x25, 0x9c, 0xd2, 0xa6, 0x1a, 0x20, 0x10, 0x16, 0x6a, 0x42,
0x27, 0x83, 0x47, 0x42, 0xa0, 0x07, 0x52, 0x09, 0x33, 0x97, 0x4e, 0x30, 0x57, 0xd8, 0xb7, 0x1e,
0x46, 0xa6, 0xba, 0x4e, 0x40, 0x6a, 0xe9, 0x1a, 0x5a, 0xa0, 0x74, 0x56, 0x92, 0x55, 0xc2, 0xbd,
0x44, 0xcd, 0xb3, 0x33, 0xf7, 0x35, 0x46, 0x25, 0xdf, 0x84, 0x19, 0xf3, 0xe2, 0x7a, 0xac, 0x4e,
0xee, 0x1a, 0x86, 0x3b, 0xb3, 0x87, 0xa6, 0x66, 0xc1, 0x70, 0x21, 0x41, 0xd3, 0x58, 0x36, 0xb5,
0x3b, 0x6e, 0xa1, 0x55, 0x60, 0x9a, 0x59, 0xd3, 0x85, 0xd8, 0xdc, 0x6a, 0xff, 0x41, 0xb6, 0xbf,
0x42, 0xde, 0x64, 0x00, 0xd0, 0xee, 0x3a, 0xa1, 0x8a, 0xed, 0x12, 0xf9, 0xba, 0x54, 0x5c, 0xdb,
0x06, 0x24, 0x49, 0xe8, 0x47, 0xcf, 0x5b, 0xe4, 0xbb, 0xc0, 0xaa, 0x8a, 0x8c, 0xbe, 0x73, 0xd9,
0x02, 0xea, 0xee, 0x8d, 0x87, 0x5b, 0xbf, 0x78, 0x04, 0x41, 0x9e, 0xa8, 0x5c, 0x3c, 0x49, 0xde,
0x88, 0x6d, 0x62, 0x21, 0x7f, 0xf0, 0x5e, 0x2d, 0x1d, 0xfc, 0x47, 0x0d, 0x1b, 0xaa, 0x4e, 0x0d,
0x78, 0x20, 0xfe, 0x57, 0x0f, 0xca, 0xdf, 0xeb, 0x3c, 0x84, 0xa7, 0xe1, 0x61, 0xb2, 0x95, 0x98,
0x07, 0x73, 0x8e, 0x51, 0xc6, 0x87, 0xe4, 0xcf, 0xf1, 0x5f, 0x86, 0x99, 0xec, 0x8d, 0x44, 0x92,
0x2c, 0x99, 0xf6, 0xc0, 0xf4, 0x39, 0xe8, 0x05, 0xbf, 0xc1, 0x56, 0xde, 0xfe, 0x93, 0x75, 0x06,
0x69, 0x87, 0x83, 0x06, 0x51, 0x80, 0xa5, 0x6e, 0xa6, 0x19, 0x7d, 0x3b, 0xef, 0xfb, 0xe0, 0x4a
};

View File

@@ -1,62 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <openssl/aes.h>
#include "aes_xcbc_mac.h"
int aes_xcbc_mac_init(struct aes_xcbc_mac_ctx *ctx, const uint8_t *key)
{
AES_KEY aes_key;
int y, x;
AES_set_encrypt_key(key, 128, &aes_key);
for (y = 0; y < 3; y++) {
for (x = 0; x < 16; x++)
ctx->K[y][x] = y + 1;
AES_ecb_encrypt(ctx->K[y], ctx->K[y], &aes_key, 1);
}
/* setup K1 */
AES_set_encrypt_key(ctx->K[0], 128, &ctx->key);
memset(ctx->IV, 0, 16);
ctx->buflen = 0;
return 0;
}
int aes_xcbc_mac_process(struct aes_xcbc_mac_ctx *ctx, const uint8_t *in, unsigned int len)
{
while (len) {
if (ctx->buflen == 16) {
AES_ecb_encrypt(ctx->IV, ctx->IV, &ctx->key, 1);
ctx->buflen = 0;
}
ctx->IV[ctx->buflen++] ^= *in++;
--len;
}
return 0;
}
int aes_xcbc_mac_done(struct aes_xcbc_mac_ctx *ctx, uint8_t *out)
{
int i;
if (ctx->buflen == 16) {
/* K2 */
for (i = 0; i < 16; i++)
ctx->IV[i] ^= ctx->K[1][i];
} else {
ctx->IV[ctx->buflen] ^= 0x80;
/* K3 */
for (i = 0; i < 16; i++)
ctx->IV[i] ^= ctx->K[2][i];
}
AES_ecb_encrypt(ctx->IV, ctx->IV, &ctx->key, 1);
memcpy(out, ctx->IV, 16);
return 0;
}

View File

@@ -1,15 +0,0 @@
#ifndef __AES_XCBC_H_
#define __AES_XCBC_H_
struct aes_xcbc_mac_ctx {
uint8_t K[3][16];
uint8_t IV[16];
AES_KEY key;
int buflen;
};
int aes_xcbc_mac_init(struct aes_xcbc_mac_ctx *ctx, const uint8_t *key);
int aes_xcbc_mac_process(struct aes_xcbc_mac_ctx *ctx, const uint8_t *in, unsigned int len);
int aes_xcbc_mac_done(struct aes_xcbc_mac_ctx *ctx, uint8_t *out);
#endif

View File

@@ -1,203 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <linux/dvb/ca.h>
#include "misc.h"
#include "descrambler.h"
#include <config.h>
static const char * FILENAME = "[descrambler]";
static int desc_fd = -1;
static int desc_user_count = 0;
#ifndef CA_SET_PID
typedef struct ca_pid {
unsigned int pid;
int index; /* -1 == disable*/
} ca_pid_t;
#define CA_SET_PID _IOW('o', 135, ca_pid_t)
#endif
#ifndef CA_SET_DESCR_DATA
enum ca_descr_data_type {
CA_DATA_IV,
CA_DATA_KEY,
};
enum ca_descr_parity {
CA_PARITY_EVEN,
CA_PARITY_ODD,
};
struct ca_descr_data {
unsigned int index;
enum ca_descr_parity parity;
enum ca_descr_data_type data_type;
unsigned int length;
unsigned char *data;
};
#define CA_SET_DESCR_DATA _IOW('o', 137, struct ca_descr_data)
#endif
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
static const char *descrambler_filename = "/dev/ciplus_ca0";
int descrambler_set_key(int index, int parity, unsigned char *data)
{
struct ca_descr_data d;
int ret;
printf("%s -> %s\n", FILENAME, __FUNCTION__);
if (descrambler_open())
{
//printf("Complete Data-> Index: (%d) Parity: (%d) -> ", index, parity);
//hexdump(data, 32);
d.index = index;
d.parity = (ca_descr_parity)parity;
d.data_type = CA_DATA_KEY;
d.length = 16;
d.data = data;
printf("AES Index: (%d) Parity: (%d) -> ", d.index, d.parity);
hexdump(d.data, 16);
ret = ioctl(desc_fd, CA_SET_DESCR_DATA, &d);
if (ret)
{
printf("CA_SET_DESCR_DATA (AES) index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
}
d.index = index;
d.parity = (ca_descr_parity)parity;
d.data_type = CA_DATA_IV;
d.length = 16;
d.data = data + 16;
printf("IV Index: (%d) Parity: (%d) -> ", d.index, d.parity);
hexdump(d.data, 16);
ret = ioctl(desc_fd, CA_SET_DESCR_DATA, &d);
if (ret)
{
printf("CA_SET_DESCR_DATA (IV) index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
}
}
return 0;
}
#else
static const char *descrambler_filename = "/dev/dvb/adapter0/ca3";
/* Byte 0 to 15 are AES Key, Byte 16 to 31 are IV */
int descrambler_set_key(int index, int parity, unsigned char *data)
{
struct ca_descr_data d;
printf("%s -> %s\n", FILENAME, __FUNCTION__);
index |= 0x100;
if (descrambler_open())
{
d.index = index;
d.parity = (ca_descr_parity)parity;
d.data_type = CA_DATA_KEY;
d.length = 32;
d.data = data;
#if 0
printf("Index: %d Parity: (%d) -> ", d.index, d.parity);
hexdump(d.data, 32);
#endif
if (ioctl(desc_fd, CA_SET_DESCR_DATA, &d))
{
printf("CA_SET_DESCR_DATA index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
}
printf("Index: %d Parity: (%d) -> ", d.index, d.parity);
hexdump(d.data, 32);
}
return 0;
}
#endif
/* we don't use this for sh4 ci cam ! */
int descrambler_set_pid(int index, int enable, int pid)
{
struct ca_pid p;
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
unsigned int flags = 0x80;
if (index)
flags |= 0x40;
if (enable)
flags |= 0x20;
p.index = flags;
p.pid = pid;
#else
p.index = index;
if (enable)
p.pid = pid;
else
p.pid = -1;
#endif
printf("CA_SET_PID pid=0x%04x index=0x%04x\n", p.pid, p.index);
if (ioctl(desc_fd, CA_SET_PID, &p) == -1)
printf("CA_SET_PID pid=0x%04x index=0x%04x (errno=%d %s)\n", p.pid, p.index, errno, strerror(errno));
return 0;
}
bool descrambler_open(void)
{
if (desc_fd > 0)
return true;
desc_fd = open(descrambler_filename, O_RDWR | O_NONBLOCK );
if (desc_fd <= 0) {
printf("cannot open %s\n", descrambler_filename);
return false;
}
return true;
}
int descrambler_init(void)
{
desc_user_count++;
descrambler_open();
printf("%s -> %s %d\n", FILENAME, __FUNCTION__, desc_user_count);
return 0;
}
void descrambler_close(void)
{
close(desc_fd);
desc_fd = -1;
}
void descrambler_deinit(void)
{
desc_user_count--;
if (desc_user_count <= 0 && desc_fd > 0)
descrambler_close();
}

Some files were not shown because too many files have changed in this diff Show More