545 Commits

Author SHA1 Message Date
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
221 changed files with 14485 additions and 18041 deletions

19
.gitignore vendored
View File

@@ -1,21 +1,16 @@
/m4/
/autom4te.cache/
/aclocal.m4
/autom4te.cache/
Makefile.in
/config.guess
/config.h.in
/config.h.in~
/config.sub
/configure
/compile
/depcomp
/install-sh
/common/Makefile.in
/libeplayer3/Makefile.in
/libspark/Makefile.in
/libtriple/Makefile.in
/azbox/Makefile.in
/generic-pc/Makefile.in
/raspi/Makefile.in
/ltmain.sh
/m4/
/missing
/Makefile.in
/tools/Makefile.in
*.*~
*.o
*.Plo

2
AUTHORS Normal file
View File

@@ -0,0 +1,2 @@

0
COPYING Normal file
View File

2530
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,8 @@ bin_PROGRAMS = libstb-hal-test
libstb_hal_la_LIBADD = \
common/libcommon.la
libstb_hal_la_LDFLAGS = -version-info 1:0:1
libstb_hal_test_SOURCES = libtest.cpp
libstb_hal_test_LDADD = libstb-hal.la
@@ -39,3 +41,23 @@ libstb_hal_la_LIBADD += \
libspark/libspark.la \
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/video_cs.h \
include/video_hal.h

0
NEWS Normal file
View File

0
README Normal file
View File

View File

@@ -51,10 +51,6 @@ fi
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
check_path () {
return $(perl -e "if(\"$1\"=~m#^/usr/(local/)?bin#){print \"0\"}else{print \"1\";}")
}
])
dnl expand nested ${foo}/bar
@@ -144,138 +140,6 @@ AC_SUBST(UCODEDIR)
AC_SUBST(THEMESDIR)
dnl end workaround
AC_DEFUN([TUXBOX_APPS_ENDIAN],[
AC_CHECK_HEADERS(endian.h)
AC_C_BIGENDIAN
])
AC_DEFUN([TUXBOX_APPS_DVB],[
AC_ARG_WITH(dvbincludes,
[ --with-dvbincludes=PATH path for dvb includes [[NONE]]],
[DVBINCLUDES="$withval"],[DVBINCLUDES=""])
if test "$DVBINCLUDES"; then
CPPFLAGS="$CPPFLAGS -I$DVBINCLUDES"
fi
if test -z "$DVB_API_VERSION"; then
AC_CHECK_HEADERS(linux/dvb/version.h,[
AC_LANG_PREPROC_REQUIRE()
AC_REQUIRE([AC_PROG_EGREP])
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
#include <linux/dvb/version.h>
version DVB_API_VERSION
]])])
DVB_API_VERSION=`(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | $EGREP "^version" | sed "s,version\ ,,"`
rm -f conftest*
AC_MSG_NOTICE([found dvb version $DVB_API_VERSION])
])
fi
if test "$DVB_API_VERSION"; then
AC_DEFINE(HAVE_DVB,1,[Define to 1 if you have the dvb includes])
AC_DEFINE_UNQUOTED(HAVE_DVB_API_VERSION,$DVB_API_VERSION,[Define to the version of the dvb api])
else
AC_MSG_ERROR([can't find dvb headers])
fi
])
AC_DEFUN([_TUXBOX_APPS_LIB_CONFIG],[
AC_PATH_PROG($1_CONFIG,$2,no)
if test "$$1_CONFIG" != "no"; then
if test "$TARGET" = "cdk" && check_path "$$1_CONFIG"; then
AC_MSG_$3([could not find a suitable version of $2]);
else
if test "$1" = "CURL"; then
$1_CFLAGS=$($$1_CONFIG --cflags)
$1_LIBS=$($$1_CONFIG --libs)
else
if test "$1" = "FREETYPE"; then
$1_CFLAGS=$($$1_CONFIG --cflags)
$1_LIBS=$($$1_CONFIG --libs)
else
$1_CFLAGS=$($$1_CONFIG --prefix=$targetprefix --cflags)
$1_LIBS=$($$1_CONFIG --prefix=$targetprefix --libs)
fi
fi
fi
fi
AC_SUBST($1_CFLAGS)
AC_SUBST($1_LIBS)
])
AC_DEFUN([TUXBOX_APPS_LIB_CONFIG],[
_TUXBOX_APPS_LIB_CONFIG($1,$2,ERROR)
if test "$$1_CONFIG" = "no"; then
AC_MSG_ERROR([could not find $2]);
fi
])
AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_CHECK],[
_TUXBOX_APPS_LIB_CONFIG($1,$2,WARN)
])
AC_DEFUN([TUXBOX_APPS_PKGCONFIG],[
m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test x"$PKG_CONFIG" = x"" ; then
AC_MSG_ERROR([could not find pkg-config]);
fi
])
AC_DEFUN([_TUXBOX_APPS_LIB_PKGCONFIG],[
AC_REQUIRE([TUXBOX_APPS_PKGCONFIG])
AC_MSG_CHECKING(for package $2)
if $PKG_CONFIG --exists "$2" ; then
AC_MSG_RESULT(yes)
$1_CFLAGS=$($PKG_CONFIG --cflags "$2")
$1_LIBS=$($PKG_CONFIG --libs "$2")
$1_EXISTS=yes
else
AC_MSG_RESULT(no)
fi
AC_SUBST($1_CFLAGS)
AC_SUBST($1_LIBS)
])
AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG],[
_TUXBOX_APPS_LIB_PKGCONFIG($1,$2)
if test x"$$1_EXISTS" != xyes; then
AC_MSG_ERROR([could not find package $2]);
fi
])
AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG_CHECK],[
_TUXBOX_APPS_LIB_PKGCONFIG($1,$2)
])
AC_DEFUN([_TUXBOX_APPS_LIB_SYMBOL],[
AC_CHECK_LIB($2,$3,HAVE_$1="yes",HAVE_$1="no")
if test "$HAVE_$1" = "yes"; then
$1_LIBS=-l$2
fi
AC_SUBST($1_LIBS)
])
AC_DEFUN([TUXBOX_APPS_LIB_SYMBOL],[
_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,ERROR)
if test "$HAVE_$1" = "no"; then
AC_MSG_ERROR([could not find $2]);
fi
])
AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_SYMBOL],[
_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,WARN)
])
AC_DEFUN([TUXBOX_BOXTYPE],[
AC_ARG_WITH(boxtype,
[ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic],

View File

@@ -1,7 +1,8 @@
noinst_LTLIBRARIES = libazbox.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common
-I$(top_srcdir)/common \
-I$(top_srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = -lpthread
@@ -13,6 +14,5 @@ libazbox_la_SOURCES = \
audio.cpp \
init.cpp \
playback.cpp \
pwrmngr.cpp \
record.cpp

View File

@@ -9,7 +9,7 @@
#include <proc_tools.h>
#include "audio_lib.h"
#include "audio_hal.h"
#include "lt_debug.h"
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
@@ -20,54 +20,55 @@
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 *)
{
fd = -1;
clipfd = -1;
mixer_fd = -1;
openDevice();
Muted = false;
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)
{
closeDevice();
}
void cAudio::openDevice(void)
{
lt_debug("%s\n", __func__);
if (fd < 0)
{
if ((fd = open(AUDIO_DEVICE, O_RDONLY|O_CLOEXEC)) < 0)
lt_info("openDevice: open failed (%m)\n");
do_mute(true, false);
if (P->fd >= 0) {
ioctl(P->fd, AUDIO_CONTINUE); /* enigma2 also does CONTINUE before close... */
close(P->fd);
P->fd = -1;
}
else
lt_info("openDevice: already open (fd = %d)\n", fd);
if (P->clipfd >= 0)
close(P->clipfd);
if (P->mixer_fd >= 0)
close(P->mixer_fd);
free(pdata);
}
void cAudio::closeDevice(void)
int cAudio::mute(void)
{
lt_debug("%s\n", __func__);
ioctl(fd, AUDIO_CONTINUE); /* enigma2 also does CONTINUE before close... */
if (fd >= 0)
close(fd);
fd = -1;
if (clipfd >= 0)
close(clipfd);
clipfd = -1;
if (mixer_fd >= 0)
close(mixer_fd);
mixer_fd = -1;
return SetMute(true);
}
int cAudio::do_mute(bool enable, bool remember)
int cAudio::unmute(void)
{
lt_debug("%s(%d, %d)\n", __func__, enable, remember);
return SetMute(false);
}
if (remember)
Muted = enable;
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 )
@@ -96,14 +97,14 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
lt_debug("%s(%d, %d)\n", __func__, left, right);
volume = (left + right) / 2;
if (clipfd != -1 && mixer_fd != -1) {
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)
if (! muted)
tmp = left << 8 | right;
int ret = ioctl(mixer_fd, MIXER_WRITE(mixer_num), &tmp);
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__, mixer_num, tmp);
lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, P->mixer_num, tmp);
return ret;
}
@@ -111,7 +112,7 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
mixer.volume_left = map_volume(left);
mixer.volume_right = map_volume(right);
if (ioctl(fd, AUDIO_SET_MIXER, &mixer) < 0)
if (ioctl(P->fd, AUDIO_SET_MIXER, &mixer) < 0)
lt_info("%s: AUDIO_SET_MIXER failed (%m)\n", __func__);
return 0;
@@ -121,16 +122,16 @@ int cAudio::Start(void)
{
lt_debug("%s\n", __func__);
int ret;
ioctl(fd, AUDIO_CONTINUE);
ret = ioctl(fd, AUDIO_PLAY);
ioctl(P->fd, AUDIO_CONTINUE);
ret = ioctl(P->fd, AUDIO_PLAY);
return ret;
}
int cAudio::Stop(void)
{
lt_debug("%s\n", __func__);
ioctl(fd, AUDIO_STOP);
ioctl(fd, AUDIO_CONTINUE); /* no idea why we have to stop and then continue => enigma2 does it, too */
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;
}
@@ -142,7 +143,7 @@ bool cAudio::Pause(bool /*Pcm*/)
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
{
lt_debug("%s %d\n", __func__, Mode);
ioctl(fd, AUDIO_SET_AV_SYNC, Mode);
ioctl(P->fd, AUDIO_SET_AV_SYNC, Mode);
};
//AUDIO_ENCODING_AC3
@@ -158,7 +159,6 @@ void cAudio::SetStreamType(AUDIO_FORMAT type)
{
int bypass = AUDIO_STREAMTYPE_MPEG;
lt_debug("%s %d\n", __func__, type);
StreamType = type;
switch (type)
{
@@ -175,7 +175,7 @@ void cAudio::SetStreamType(AUDIO_FORMAT type)
// 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)
if (ioctl(P->fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
};
@@ -191,12 +191,12 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
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 (clipfd >= 0) {
lt_info("%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd);
if (P->clipfd >= 0) {
lt_info("%s: clipfd already opened (%d)\n", __func__, P->clipfd);
return -1;
}
mixer_num = -1;
mixer_fd = -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:
@@ -213,8 +213,8 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
}
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. */
clipfd = open(dsp_dev, O_WRONLY|O_CLOEXEC);
if (clipfd < 0) {
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;
}
@@ -223,29 +223,29 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
fmt = AFMT_S16_BE;
else
fmt = AFMT_S16_LE;
if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt))
if (ioctl(P->clipfd, SNDCTL_DSP_SETFMT, &fmt))
perror("SNDCTL_DSP_SETFMT");
if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch))
if (ioctl(P->clipfd, SNDCTL_DSP_CHANNELS, &ch))
perror("SNDCTL_DSP_CHANNELS");
if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate))
if (ioctl(P->clipfd, SNDCTL_DSP_SPEED, &srate))
perror("SNDCTL_DSP_SPEED");
if (ioctl(clipfd, SNDCTL_DSP_RESET))
if (ioctl(P->clipfd, SNDCTL_DSP_RESET))
perror("SNDCTL_DSP_RESET");
if (!mix_dev)
return 0;
mixer_fd = open(mix_dev, O_RDWR|O_CLOEXEC);
if (mixer_fd < 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(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
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(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
if (ioctl(P->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
lt_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
stereo = 0;
}
@@ -253,8 +253,8 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
if (usable == 0) {
lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n",
__func__, devmask, stereo);
close(mixer_fd);
mixer_fd = -1;
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... */
@@ -265,14 +265,14 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
__func__, devmask, stereo, __func__);
const char *tmp = getenv("MIX_NUMBER");
if (tmp)
mixer_num = atoi(tmp);
P->mixer_num = atoi(tmp);
lt_info("%s: mixer_num is %d -> device %08x\n",
__func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0);
__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 {
mixer_num = 0;
P->mixer_num = 0;
while (!(usable & 0x01)) {
mixer_num++;
P->mixer_num++;
usable >>= 1;
}
}
@@ -285,11 +285,11 @@ int cAudio::WriteClip(unsigned char *buffer, int size)
{
int ret;
// lt_debug("cAudio::%s\n", __FUNCTION__);
if (clipfd <= 0) {
if (P->clipfd <= 0) {
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
ret = write(clipfd, buffer, size);
ret = write(P->clipfd, buffer, size);
if (ret < 0)
lt_info("%s: write error (%m)\n", __FUNCTION__);
return ret;
@@ -298,15 +298,15 @@ int cAudio::WriteClip(unsigned char *buffer, int size)
int cAudio::StopClip()
{
lt_debug("%s\n", __FUNCTION__);
if (clipfd <= 0) {
if (P->clipfd <= 0) {
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
close(clipfd);
clipfd = -1;
if (mixer_fd >= 0)
close(mixer_fd);
mixer_fd = -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;
};
@@ -370,10 +370,15 @@ 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);
//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)
@@ -386,8 +391,7 @@ void cAudio::EnableAnalogOut(bool enable)
lt_debug("%s %d\n", __FUNCTION__, enable);
};
#define AUDIO_BYPASS_ON 0
#define AUDIO_BYPASS_OFF 1
#if 0
void cAudio::setBypassMode(bool disable)
{
lt_debug("%s %d\n", __func__, disable);
@@ -396,3 +400,4 @@ void cAudio::setBypassMode(bool disable)
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
return;
}
#endif

View File

@@ -1,98 +0,0 @@
/* public header file */
#ifndef _AUDIO_LIB_H_
#define _AUDIO_LIB_H_
#include "../common/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
{
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;
void openDevice(void);
void closeDevice(void);
int do_mute(bool enable, bool remember);
void setBypassMode(bool disable);
public:
/* construct & destruct */
cAudio(void *, void *, void *);
~cAudio(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);
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);
};
#endif

View File

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

View File

@@ -30,11 +30,13 @@
#include <cstring>
#include <cstdio>
#include <string>
#include "dmx_lib.h"
#include <sys/ioctl.h>
#include "dmx_hal.h"
#include "lt_debug.h"
/* Ugh... see comment in destructor for details... */
#include "video_lib.h"
#include "video_hal.h"
#include "video_priv.h"
extern cVideo *videoDecoder;
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
@@ -42,14 +44,8 @@ extern cVideo *videoDecoder;
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
#define dmx_err(_errfmt, _errstr, _revents) do { \
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
if (dmx_type == DMX_PSI_CHANNEL) { \
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
} else { \
_pid = p_flt.pid; \
}; \
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, _f); \
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
} while(0);
cDemux *videoDemux = NULL;
@@ -88,9 +84,6 @@ cDemux::cDemux(int n)
else
num = n;
fd = -1;
measure = false;
last_measure = 0;
last_data = 0;
}
cDemux::~cDemux()
@@ -165,8 +158,6 @@ void cDemux::Close(void)
ioctl(fd, DMX_STOP);
close(fd);
fd = -1;
if (measure)
return;
if (dmx_type == DMX_TP_CHANNEL)
{
dmx_tp_count--;
@@ -273,11 +264,13 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
return rc;
}
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
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)
{
@@ -286,6 +279,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
}
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)
@@ -389,8 +383,11 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
return true;
}
bool cDemux::pesFilter(const unsigned short pid)
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...
@@ -497,7 +494,7 @@ void cDemux::getSTC(int64_t * STC)
lt_debug("%s #%d\n", __func__, num);
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->GetPTS();
pts = videoDecoder->vdec->GetPTS();
*STC = pts;
}

View File

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

View File

@@ -1,70 +0,0 @@
#ifndef __DEMUX_TD_H
#define __DEMUX_TD_H
#include <cstdlib>
#include <vector>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include "../common/cs_types.h"
#define MAX_DMX_UNITS 4
typedef enum
{
DMX_INVALID = 0,
DMX_VIDEO_CHANNEL = 1,
DMX_AUDIO_CHANNEL,
DMX_PES_CHANNEL,
DMX_PSI_CHANNEL,
DMX_PIP_CHANNEL,
DMX_TP_CHANNEL,
DMX_PCR_ONLY_CHANNEL
} DMX_CHANNEL_TYPE;
typedef struct
{
int fd;
unsigned short pid;
} pes_pids;
class cDemux
{
private:
int num;
int fd;
int buffersize;
bool measure;
uint64_t last_measure, last_data;
DMX_CHANNEL_TYPE dmx_type;
std::vector<pes_pids> pesfds;
struct dmx_sct_filter_params s_flt;
struct dmx_pes_filter_params p_flt;
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);
// TD only functions
int getFD(void) { return fd; }; /* needed by cPlayback class */
void removePid(unsigned short Pid); /* needed by cRecord class */
std::vector<pes_pids> getPesPids(void) { return pesfds; };
//
cDemux(int num = 0);
~cDemux();
};
#endif //__DEMUX_H

View File

@@ -2,7 +2,7 @@
* 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
*/
@@ -30,6 +30,7 @@ hw_caps_t *get_hwcaps(void)
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.has_HDMI = 1;
caps.display_xres = 8;
caps.can_set_display_brightness = 0;
strcpy(caps.boxvendor, "AZBox");
const char *tmp;
char buf[64];
@@ -45,6 +46,7 @@ hw_caps_t *get_hwcaps(void)
}
else
strcpy(caps.boxname, "(unknown model)");
strcpy(caps.boxarch, "mipsel");
return &caps;
}

View File

@@ -1,5 +1,5 @@
#include <unistd.h>
#include "init_lib.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)

View File

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

View File

@@ -50,7 +50,7 @@
#define IN_FILE "/tmp/rmfp.in2"
#define OUT_FILE "/tmp/rmfp.out2"
#include "playback.h"
#include "playback_hal.h"
extern "C"{
#include "e2mruainclude.h"
@@ -73,8 +73,38 @@ static time_t monotonic_ms(void)
}
#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 cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen)
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;
@@ -141,21 +171,21 @@ bool cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int
* the output will be buffered after starting up and we will only
* see "Playback has started..." after the player exits
*/
void cPlayback::run_rmfp()
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(mfilename);
std::string filename(fname);
std::string file = '"' + filename + '"';
std::string final = base + file;
if (playMode == PLAYMODE_TS && mduration != 0)
if (pmode == PLAYMODE_TS && duration != 0)
{
std::stringstream duration;
duration << (mduration /** 60000LL*/);
final = base + "-duration " + duration.str() + " " + file;
std::stringstream du;
du << (duration /** 60000LL*/);
final = base + "-duration " + du.str() + " " + file;
}
pid_t pid = 0;
@@ -190,7 +220,7 @@ void cPlayback::run_rmfp()
else if (strstr(output, "End of file..."))
{
playing = 1; /* this can happen without "Playback has started..." */
eof_reached = true;
eof = true;
lt_info("%s: ===================> eof_reached = true\n", __func__);
}
}
@@ -206,14 +236,14 @@ void cPlayback::run_rmfp()
playing = 2;
else
playing = 0;
eof_reached = true;
eof = true;
pthread_exit(NULL);
}
/* helper function to call the cpp thread loop */
void *execute_rua_thread(void *c)
{
cPlayback *obj = (cPlayback *)c;
PBPrivate *obj = (PBPrivate *)c;
lt_info_c("%s\n", __func__);
obj->run_rmfp();
/* free(obj); // this is most likely wrong */
@@ -228,11 +258,11 @@ bool cPlayback::Open(playmode_t PlayMode)
"PLAYMODE_TS",
"PLAYMODE_FILE"
};
playMode = PlayMode;
if (playMode > 1)
pd->pmode = PlayMode;
if (pd->pmode > 1)
{
lt_info("%s: PlayMode %d out of range!\n", __func__, PlayMode);
playMode = PLAYMODE_FILE;
pd->pmode = PLAYMODE_FILE;
}
lt_info("%s: mode %d (%s)\n", __func__, PlayMode, aPLAYMODE[PlayMode]);
@@ -253,7 +283,7 @@ bool cPlayback::Open(playmode_t PlayMode)
if (i > 10)
{
lt_info("%s: ERROR - player is not idle after 10 seconds!\n", __func__);
open_success = false;
pd->open_success = false;
return false;
}
sleep(1);
@@ -266,10 +296,15 @@ bool cPlayback::Open(playmode_t PlayMode)
unlink(IN_FILE);
unlink(OUT_FILE);
open_success = true;
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)
@@ -278,49 +313,49 @@ bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned s
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, open_success);
__func__, vpid, vtype, _apid, ac3, duration, pd->open_success);
if (!open_success)
if (!pd->open_success)
return false;
eof_reached = false;
pd->eof = false;
//create playback path
apid = 0;
subpid = 0;
mfilename = filename;
mduration = duration;
if (pthread_create(&thread, 0, execute_rua_thread, this) != 0)
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 (! playing)
while (! pd->playing)
sleep(1);
if (playing == 2)
playing = 0;
if (pd->playing == 2)
pd->playing = 0;
return ret;
}
void cPlayback::Close(void)
{
lt_info("%s: playing %d thread_started %d\n", __func__, playing, thread_started);
lt_info("%s: playing %d thread_started %d\n", __func__, pd->playing, pd->thread_started);
if (thread_started)
if (pd->thread_started)
{
rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
pd->rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
if (pthread_join(thread, NULL))
if (pthread_join(pd->thread, NULL))
lt_info("%s: error joining rmfp thread (%m)\n", __func__);
playing = 0;
thread_started = false;
pd->playing = 0;
pd->thread_started = false;
}
else
lt_info("%s: Warning: thread_started == false!\n", __func__);
if (open_success)
if (pd->open_success)
{
proc_put("/proc/player", "1", 2);
open_success = false;
pd->open_success = false;
lt_info("%s: /proc/player switched to '1'\n", __func__);
usleep(1000000);
}
@@ -329,39 +364,39 @@ void cPlayback::Close(void)
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
{
lt_info("%s: pid %i\n", __func__, pid);
if (pid != apid) {
rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0);
apid = 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)
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
{
lt_info("%s: pid %i\n", __func__, pid);
if (pid != subpid)
if (pid != pd->subpid)
{
rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0);
subpid = pid;
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__, playing, speed);
lt_info("%s: playing %d speed %d\n", __func__, pd->playing, speed);
if (!playing)
if (!pd->playing)
return false;
playback_speed = speed;
pd->speed = speed;
if (speed > 1 || speed < 0)
rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
pd->rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
else if (speed == 0)
rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
pd->rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
else
rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
pd->rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
return true;
}
@@ -378,22 +413,22 @@ bool cPlayback::GetSpeed(int &/*speed*/) const
// in milliseconds
bool cPlayback::GetPosition(int &position, int &duration)
{
lt_debug("%s: playing %d\n", __func__, playing);
lt_debug("%s: playing %d\n", __func__, pd->playing);
if (eof_reached)
if (pd->eof)
{
position = mduration;
duration = mduration;
position = pd->duration;
duration = pd->duration;
return true;
}
if (!playing)
if (!pd->playing)
return false;
char buf[32];
/* custom command 222 returns "12345\n1234\n",
* first line is duration, second line is position */
if (! rmfp_command(222, 0, false, buf, 32))
if (! pd->rmfp_command(222, 0, false, buf, 32))
return false;
duration = atoi(buf);
char *p = strchr(buf, '\n');
@@ -404,11 +439,11 @@ bool cPlayback::GetPosition(int &position, int &duration)
if (duration == 0)
duration = position + 1000;
if (playMode == PLAYMODE_TS)
if (pd->pmode == PLAYMODE_TS)
{
if (position > mduration)
mduration = position + 1000;
duration = mduration;
if (position > pd->duration)
pd->duration = position + 1000;
duration = pd->duration;
return true;
}
return true;
@@ -416,23 +451,23 @@ bool cPlayback::GetPosition(int &position, int &duration)
bool cPlayback::SetPosition(int position, bool absolute)
{
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing);
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, pd->playing);
if (!playing)
if (!pd->playing)
return false;
int seconds = position / 1000;;
if (absolute)
{
rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0);
pd->rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0);
return true;
}
if (position > 0)
rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0);
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0);
else if (position < 0)
rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
return true;
}
@@ -440,7 +475,7 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
{
lt_info("%s\n", __func__);
char buf[32];
rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
pd->rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
unsigned int audio_count = atoi(buf);
*numpida = audio_count;
@@ -451,7 +486,7 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
char streamidstring[11];
char audio_lang[21];
memset(buf, 0, sizeof(buf));
rmfp_command(CUSTOM_COMMAND_GET_AUDIO_BY_ID, aid, true, buf, 32);
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);
@@ -469,7 +504,7 @@ void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t
lt_info("%s\n", __func__);
char buf[32];
rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
pd->rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
unsigned int spu_count = atoi(buf);
*numpids = spu_count;
@@ -480,7 +515,7 @@ void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t
char streamidstring[11];
char spu_lang[21];
memset(buf, 0, sizeof(buf));
rmfp_command(CUSTOM_COMMAND_GET_SUB_BY_ID, sid, true, buf, 32);
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);
@@ -504,18 +539,36 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
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__);
playing = 0;
thread_started = false;
eof_reached = false;
open_success = false;
pthread_mutex_init(&rmfp_cmd_mutex, NULL);
pd = new PBPrivate();
}
cPlayback::~cPlayback()
{
lt_info("%s\n", __func__);
pthread_mutex_destroy(&rmfp_cmd_mutex);
delete pd;
pd = NULL;
}

View File

@@ -1,62 +0,0 @@
#ifndef __PLAYBACK_H
#define __PLAYBACK_H
#include <string>
#include <stdint.h>
#include <vector>
typedef enum {
PLAYMODE_TS = 0,
PLAYMODE_FILE,
} playmode_t;
class cPlayback
{
private:
pthread_mutex_t rmfp_cmd_mutex;
int playing;
bool eof_reached;
int playback_speed;
playmode_t playMode;
bool open_success;
uint16_t apid;
uint16_t subpid;
char *mfilename;
int mduration;
pthread_t thread;
bool thread_started;
/* private functions */
bool rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen);
public:
cPlayback(int num = 0);
~cPlayback();
void run_rmfp();
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 SetAPid(unsigned short pid, int ac3);
bool SetSpeed(int speed);
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration); /* pos: current time in ms, dur: file length in ms */
bool SetPosition(int position, bool absolute = false); /* position: jump in ms */
void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language);
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
bool SelectSubtitles(int pid);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
#if 0
// Functions that are not used by movieplayer.cpp:
bool Stop(void);
bool GetOffset(off64_t &offset);
bool IsPlaying(void) const { return playing; }
bool IsEnabled(void) const { return enabled; }
void * GetHandle(void);
void * GetDmHandle(void);
int GetCurrPlaybackSpeed(void) const { return nPlaybackSpeed; }
void PlaybackNotify (int Event, void *pData, void *pTag);
void DMNotify(int Event, void *pTsBuf, void *Tag);
#endif
};
#endif

View File

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

View File

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

View File

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

View File

@@ -37,7 +37,9 @@
#include <proc_tools.h>
#include "video_lib.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)
@@ -75,12 +77,22 @@ static void show_iframe(int fd, unsigned char *iframe, size_t st_size);
#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;
scartvoltage = -1;
video_standby = 0;
fd = -1;
@@ -111,17 +123,17 @@ cVideo::cVideo(int, void *, void *, unsigned int)
close(blankfd);
}
openDevice();
Pig(-1, -1, -1, -1);
Pig(-1, -1, -1, -1, 1, 1);
}
cVideo::~cVideo(void)
VDec::~VDec(void)
{
closeDevice();
if (blank_data)
free(blank_data);
}
void cVideo::openDevice(void)
void VDec::openDevice(void)
{
int n = 0;
lt_debug("%s\n", __func__);
@@ -143,7 +155,7 @@ retry:
playstate = VIDEO_STOPPED;
}
void cVideo::closeDevice(void)
void VDec::closeDevice(void)
{
lt_debug("%s\n", __func__);
if (fd >= 0)
@@ -181,6 +193,11 @@ int cVideo::setAspectRatio(int aspect, int mode)
}
int cVideo::getAspectRatio(void)
{
return vdec->getAspectRatio();
}
int VDec::getAspectRatio(void)
{
video_size_t s;
if (fd == -1)
@@ -198,7 +215,7 @@ int cVideo::getAspectRatio(void)
return s.aspect_ratio * 2 + 1;
}
int cVideo::setCroppingMode(int /*vidDispMode_t format*/)
int cVideo::setCroppingMode(void)
{
return 0;
#if 0
@@ -215,6 +232,16 @@ int cVideo::setCroppingMode(int /*vidDispMode_t format*/)
}
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
@@ -227,7 +254,7 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho
return fop(ioctl, VIDEO_PLAY);
}
int cVideo::Stop(bool blank)
int VDec::Stop(bool blank)
{
lt_debug("%s(%d)\n", __FUNCTION__, blank);
if (stillpicture)
@@ -242,7 +269,12 @@ int cVideo::Stop(bool blank)
return fop(ioctl, VIDEO_STOP, blank ? 1 : 0);
}
int cVideo::setBlank(int)
int cVideo::setBlank(int b)
{
return vdec->setBlank(b);
}
int VDec::setBlank(int)
{
pthread_mutex_lock(&stillp_mutex);
if (blank_data)
@@ -291,7 +323,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember)
int cVideo::getPlayState(void)
{
return playstate;
return vdec->playstate;
}
void cVideo::SetVideoMode(analog_mode_t mode)
@@ -320,6 +352,11 @@ void cVideo::SetVideoMode(analog_mode_t mode)
}
void cVideo::ShowPicture(const char * fname)
{
vdec->ShowPicture(fname);
}
void VDec::ShowPicture(const char * fname)
{
lt_debug("%s(%s)\n", __func__, fname);
char destname[512];
@@ -402,10 +439,15 @@ void cVideo::ShowPicture(const char * fname)
void cVideo::StopPicture()
{
lt_debug("%s\n", __func__);
stillpicture = false;
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)
@@ -428,26 +470,12 @@ int cVideo::getBlank(void)
return !ret;
}
/* this function is regularly called, checks if video parameters
changed and triggers appropriate actions */
void cVideo::VideoParamWatchdog(void)
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
{
#if 0
static unsigned int _v_info = (unsigned int) -1;
unsigned int v_info;
if (fd == -1)
return;
ioctl(fd, MPEG_VID_GET_V_INFO_RAW, &v_info);
if (_v_info != v_info)
{
lt_debug("%s params changed. old: %08x new: %08x\n", __FUNCTION__, _v_info, v_info);
setAspectRatio(-1, -1);
}
_v_info = v_info;
#endif
vdec->Pig(x, y, w, h, osd_w, osd_h);
}
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int 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;
@@ -509,6 +537,11 @@ static inline int rate2csapi(int rate)
}
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;
@@ -554,6 +587,11 @@ void cVideo::SetSyncMode(AVSYNC_TYPE mode)
};
int cVideo::SetStreamType(VIDEO_FORMAT type)
{
return vdec->SetStreamType(type);
}
int VDec::SetStreamType(VIDEO_FORMAT type)
{
static const char *VF[] = {
"VIDEO_FORMAT_MPEG2",
@@ -585,7 +623,7 @@ int cVideo::SetStreamType(VIDEO_FORMAT type)
return 0;
}
int64_t cVideo::GetPTS(void)
int64_t VDec::GetPTS(void)
{
int64_t pts = 0;
if (ioctl(fd, VIDEO_GET_PTS, &pts) < 0)

View File

@@ -1,196 +0,0 @@
#ifndef _VIDEO_TD_H
#define _VIDEO_TD_H
#include <linux/dvb/video.h>
#include "../common/cs_types.h"
#include "dmx_lib.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,
VIDEO_FORMAT_VC1,
VIDEO_FORMAT_JPEG,
VIDEO_FORMAT_GIF,
VIDEO_FORMAT_PNG
} 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_AUTO,
VIDEO_STD_1080P50, /* SPARK only */
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 cVideo
{
friend class cDemux;
friend class cPlayback;
private:
/* video device */
int fd;
/* apparently we cannot query the driver's state
=> remember it */
video_play_state_t playstate;
int /*vidDispMode_t*/ croppingMode;
int /*vidOutFmt_t*/ outputformat;
int scartvoltage;
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;
int64_t GetPTS(void);
void openDevice(void);
void closeDevice(void);
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(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);
/* 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; };
void 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 VideoParamWatchdog(void);
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);
};
#endif

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);
void 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

@@ -2,7 +2,11 @@ noinst_LTLIBRARIES = libcommon.la
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_CXXFLAGS += \
-I $(top_srcdir)/include
libcommon_la_SOURCES = \
ca.cpp \
lt_debug.cpp \
proc_tools.c
lt_debug.c \
proc_tools.c \
pwrmngr.cpp

View File

@@ -1 +0,0 @@
../include/hardware_caps.h

View File

@@ -21,10 +21,16 @@
#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

@@ -1,8 +1,28 @@
#include <stdio.h>
#include <cstdlib>
/*
* (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 "pwrmngr.h"
#include "lt_debug.h"
#if HAVE_TRIPLEDRAGON
#include <stdio.h>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
@@ -11,32 +31,50 @@
#include <avs/avs_inf.h>
#include <tdpanel/lcdstuff.h>
#endif
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PWRMNGR, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_PWRMNGR, this, args)
void cCpuFreqManager::Up(void) { lt_debug("%s\n", __FUNCTION__); }
void cCpuFreqManager::Down(void) { lt_debug("%s\n", __FUNCTION__); }
void cCpuFreqManager::Reset(void) { lt_debug("%s\n", __FUNCTION__); }
/* those function dummies return true or "harmless" values */
bool cCpuFreqManager::SetDelta(unsigned long) { lt_debug("%s\n", __FUNCTION__); return true; }
unsigned long cCpuFreqManager::GetCpuFreq(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
unsigned long cCpuFreqManager::GetDelta(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
//
cCpuFreqManager::cCpuFreqManager(void) { lt_debug("%s\n", __FUNCTION__); }
bool cPowerManager::SetState(PWR_STATE) { lt_debug("%s\n", __FUNCTION__); return true; }
bool cPowerManager::Open(void) { lt_debug("%s\n", __FUNCTION__); return true; }
void cPowerManager::Close(void) { lt_debug("%s\n", __FUNCTION__); }
//
bool cPowerManager::SetStandby(bool Active, bool Passive)
/* cpufreqmanager */
void cCpuFreqManager::Up(void)
{
lt_debug("%s(%d, %d)\n", __FUNCTION__, Active, Passive);
lt_debug("%s\n", __func__);
}
void cCpuFreqManager::Down(void)
{
lt_debug("%s\n", __func__);
}
void cCpuFreqManager::Reset(void)
{
lt_debug("%s\n", __func__);
}
/* those function dummies return true or "harmless" values */
bool cCpuFreqManager::SetDelta(unsigned long)
{
lt_debug("%s\n", __func__);
return true;
}
unsigned long cCpuFreqManager::GetDelta(void)
{
lt_debug("%s\n", __func__);
return 0;
}
unsigned long cCpuFreqManager::GetCpuFreq(void)
{
lt_debug("%s\n", __func__);
return 0;
}
bool cCpuFreqManager::SetCpuFreq(unsigned long f)
{
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:
* during a recording, cpu freq is kept "high", even if the box is sent to standby
@@ -47,7 +85,6 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
* f == 0 => max => not standby
* f == 50000000 => min => standby
*/
lt_debug("%s(%lu) => set standby = %s\n", __FUNCTION__, f, f?"true":"false");
int fd = open("/dev/stb/tdsystem", O_RDONLY);
if (fd < 0)
{
@@ -78,10 +115,38 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
}
close(fd);
#endif
return true;
}
//
cPowerManager::cPowerManager(void) { lt_debug("%s\n", __FUNCTION__); }
cPowerManager::~cPowerManager() { lt_debug("%s\n", __FUNCTION__); }
cCpuFreqManager::cCpuFreqManager(void)
{
lt_debug("%s\n", __func__);
}
/* powermanager */
bool cPowerManager::Open(void)
{
lt_debug("%s\n", __func__);
return true;
}
void cPowerManager::Close(void)
{
lt_debug("%s\n", __func__);
}
bool cPowerManager::SetStandby(bool Active, bool Passive)
{
lt_debug("%s(%d, %d)\n", __func__, Active, Passive);
return true;
}
cPowerManager::cPowerManager(void)
{
lt_debug("%s\n", __func__);
}
cPowerManager::~cPowerManager()
{
lt_debug("%s\n", __func__);
}

View File

@@ -1,36 +1,77 @@
AC_INIT([libstb-hal], [0.1.1])
AC_INIT([libstb-hal], [0.2.0])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
AC_CONFIG_MACRO_DIR([m4])
AC_GNU_SOURCE
LT_INIT
## ugly, disables shared library build (not wanted yet)
enable_shared=no
TUXBOX_APPS
TUXBOX_APPS_DIRECTORY
TUXBOX_APPS_PKGCONFIG
TUXBOX_BOXTYPE
AC_PROG_CC
AC_PROG_CXX
PKG_PROG_PKG_CONFIG
## both disabled => libtool still defaults to static
## at least the libtool I tested with ;-)
## --enable-shared => build only shared
## --enable-shared --enable-static => build both
AC_DISABLE_SHARED
AC_DISABLE_STATIC
AC_SYS_LARGEFILE
AM_PROG_LIBTOOL
AC_PROG_LIBTOOL
AC_ARG_ENABLE(clutter,
AS_HELP_STRING(--enable-clutter, use clutter instead of OpenGL),
,[enable_clutter=no])
AM_CONDITIONAL(USE_CLUTTER,test "$enable_clutter" = "yes")
AM_CONDITIONAL(USE_OPENGL,test "$enable_clutter" = "no")
if test "$enable_clutter" = "yes"; then
AC_DEFINE(USE_CLUTTER,1,[use clutter instead of opengl])
else
AC_DEFINE(USE_OPENGL,1,[use opengl instead of clutter])
fi
if test x"$BOXTYPE" = x"tripledragon"; then
TUXBOX_APPS_LIB_PKGCONFIG(DIRECTFB, directfb)
PKG_CHECK_MODULES([DIRECTFB], [directfb])
fi
if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
if test x$BOXTYPE = xgeneric; then
if test x"$enable_clutter" = xyes; then
PKG_CHECK_MODULES([CLUTTER], [clutter-1.0])
fi
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])
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
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_OUTPUT([
Makefile
common/Makefile

View File

@@ -1,28 +1,41 @@
noinst_LTLIBRARIES = libgeneric.la
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
AM_CPPFLAGS += -Wfatal-errors
AM_CPPFLAGS += \
-I$(top_srcdir)/common
-I$(top_srcdir)/common \
-I$(top_srcdir)/include \
@AVUTIL_CFLAGS@ \
@CLUTTER_CFLAGS@
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = \
-lglut -lGL -lGLU -lGLEW -lao \
-lao \
-lOpenThreads \
@AVFORMAT_LIBS@ \
@AVUTIL_LIBS@ \
@AVCODEC_LIBS@ \
@SWRESAMPLE_LIBS@ \
@SWSCALE_LIBS@
@SWSCALE_LIBS@ \
@CLUTTER_LIBS@
if USE_OPENGL
AM_LDFLAGS += -lglut -lGL -lGLU -lGLEW -lao
endif
libgeneric_la_SOURCES = \
hardware_caps.c \
dmx.cpp \
video.cpp \
audio.cpp \
glfb.cpp \
init.cpp \
playback.cpp \
pwrmngr.cpp \
record.cpp
if USE_CLUTTER
libgeneric_la_SOURCES += clutterfb.cpp
endif
if USE_OPENGL
libgeneric_la_SOURCES += glfb.cpp
endif

View File

@@ -22,55 +22,51 @@
#include <cstdio>
#include <cstdlib>
#include "audio_lib.h"
#include "dmx_lib.h"
#include "audio_hal.h"
#include "audio_priv.h"
#include "dmx_hal.h"
#include "lt_debug.h"
#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;
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);
@@ -78,19 +74,19 @@ cAudio::~cAudio(void)
ao_shutdown();
}
void cAudio::openDevice(void)
int cAudio::mute(void)
{
lt_debug("%s\n", __func__);
return SetMute(true);
}
void cAudio::closeDevice(void)
int cAudio::unmute(void)
{
lt_debug("%s\n", __func__);
return SetMute(false);
}
int cAudio::do_mute(bool enable, bool remember)
int cAudio::SetMute(bool enable)
{
lt_debug("%s(%d, %d)\n", __func__, enable, remember);
lt_debug("%s(%d)\n", __func__, enable);
return 0;
}
@@ -101,21 +97,31 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
}
int cAudio::Start(void)
{
return adec->Start();
}
int cAudio::Stop(void)
{
return adec->Stop();
}
int ADec::Start(void)
{
lt_debug("%s >\n", __func__);
if (! HAL_nodec)
OpenThreads::Thread::start();
start();
lt_debug("%s <\n", __func__);
return 0;
}
int cAudio::Stop(void)
int ADec::Stop(void)
{
lt_debug("%s >\n", __func__);
if (thread_started)
{
thread_started = false;
OpenThreads::Thread::join();
join();
}
lt_debug("%s <\n", __func__);
return 0;
@@ -142,6 +148,11 @@ int cAudio::setChannel(int /*channel*/)
};
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
{
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;
@@ -168,6 +179,11 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
};
int cAudio::WriteClip(unsigned char *buffer, int 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) {
@@ -195,14 +211,45 @@ 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 */
freq = 0;
bitrate = 0; /* not used, but easy to get :-) */
mode = 0; /* default: stereo */
printf("cAudio::getAudioInfo c %p\n", c);
if (c) {
type = (c->codec_id != AV_CODEC_ID_MP2); /* only mpeg / not mpeg is indicated */
switch (c->codec_id) {
case AV_CODEC_ID_MP2:
type = AUDIO_FMT_MPEG;
break;
case AV_CODEC_ID_MP3:
type = AUDIO_FMT_MP3;
break;
case AV_CODEC_ID_AC3:
case AV_CODEC_ID_TRUEHD:
type = AUDIO_FMT_DOLBY_DIGITAL;
break;
case AV_CODEC_ID_EAC3:
type = AUDIO_FMT_DD_PLUS;
break;
case AV_CODEC_ID_AAC:
type = AUDIO_FMT_AAC;
break;
case AV_CODEC_ID_DTS:
type = AUDIO_FMT_DTS;
break;
case AV_CODEC_ID_MLP:
type = AUDIO_FMT_MLP;
break;
default:
break;
}
freq = c->sample_rate;
bitrate = c->bit_rate;
if (c->channels == 1)
@@ -240,7 +287,7 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m
}
}
lt_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n",
__func__, type, layer, freq, bitrate, mode, c->codec_id);
__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*/)
@@ -268,17 +315,12 @@ void cAudio::EnableAnalogOut(bool enable)
lt_debug("%s %d\n", __func__, enable);
};
void cAudio::setBypassMode(bool disable)
{
lt_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) {
@@ -305,7 +347,7 @@ int cAudio::my_read(uint8_t *buf, int buf_size)
return tmp;
}
void cAudio::run()
void ADec::run()
{
lt_info("====================== start decoder thread ================================\n");
/* libavcodec & friends */
@@ -357,28 +399,31 @@ void cAudio::run()
lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams);
goto out;
}
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);
p = avfc->streams[0]->codecpar;
if (p->codec_type != AVMEDIA_TYPE_AUDIO)
lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, p->codec_type);
c = avfc->streams[0]->codec;
codec = avcodec_find_decoder(c->codec_id);
codec = avcodec_find_decoder(p->codec_id);
if (!codec) {
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->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) {
lt_info("%s: avcodec_open2() failed\n", __func__);
goto out;
}
frame = avcodec_alloc_frame();
frame = av_frame_alloc();
if (!frame) {
lt_info("%s: avcodec_alloc_frame 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 */
o_ch = c->channels; /* 2 */
o_sr = c->sample_rate; /* 48000 */
o_layout = c->channel_layout; /* AV_CH_LAYOUT_STEREO */
o_ch = p->channels; /* 2 */
o_sr = p->sample_rate; /* 48000 */
o_layout = p->channel_layout; /* AV_CH_LAYOUT_STEREO */
if (sformat.channels != o_ch || sformat.rate != o_sr ||
sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL)
{
@@ -405,10 +450,10 @@ void cAudio::run()
#endif
av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt);
lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n",
avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels);
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 */
c->channel_layout, c->sample_fmt, c->sample_rate, /* input */
p->channel_layout, c->sample_fmt, p->sample_rate, /* input */
0, NULL);
if (! swr) {
lt_info("could not alloc resample context\n");
@@ -422,15 +467,15 @@ void cAudio::run()
avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
if (gotframe && thread_started) {
int out_linesize;
obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) +
frame->nb_samples, o_sr, c->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) {
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) {
lt_info("av_samples_alloc failed\n");
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
break; /* while (thread_started) */
}
obuf_sz_max = obuf_sz;
@@ -443,15 +488,16 @@ void cAudio::run()
obuf_sz, AV_SAMPLE_FMT_S16, 1);
ao_play(adevice, (char *)obuf, o_buf_sz);
}
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
}
// ao_close(adevice); /* can take long :-( */
av_free(obuf);
swr_free(&swr);
out3:
avcodec_free_frame(&frame);
av_frame_free(&frame);
out2:
avcodec_close(c);
av_free(c);
c = NULL;
out:
avformat_close_input(&avfc);

View File

@@ -1,105 +0,0 @@
/* public header file */
#ifndef _AUDIO_LIB_H_
#define _AUDIO_LIB_H_
#include <stdint.h>
#include <OpenThreads/Thread>
#include "../common/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 OpenThreads::Thread
{
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;
bool thread_started;
int volume;
int64_t curr_pts;
void openDevice(void);
void closeDevice(void);
int do_mute(bool enable, bool remember);
void setBypassMode(bool disable);
void run();
public:
/* construct & destruct */
cAudio(void *, void *, void *);
~cAudio(void);
int64_t getPts() { return curr_pts; }
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);
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);
int my_read(uint8_t *buf, int buf_size);
};
#endif

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;
};

523
generic-pc/clutterfb.cpp Normal file
View File

@@ -0,0 +1,523 @@
/*
Framebuffer implementation using clutter https://developer.gnome.org/clutter/
Copyright (C) 2016 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
based on the openGL framebuffer implementation
Copyright 2010 Carsten Juttner <carjay@gmx.net>
Copyright 2012,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/>.
TODO: AV-Sync code is "experimental" at best
*/
#include "config.h"
#include <vector>
#include <sys/types.h>
#include <signal.h>
#include <cstdio>
#include <cstring>
#include <errno.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include "glfb_priv.h"
#include "video_priv.h"
#include "audio_priv.h"
#include <clutter/x11/clutter-x11.h>
#include "lt_debug.h"
#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 VDec *vdec;
extern ADec *adec;
/* the private class that does stuff only needed inside libstb-hal.
* is used e.g. by cVideo... */
GLFbPC *glfb_priv = NULL;
GLFramebuffer::GLFramebuffer(int x, int y)
{
Init();
glfb_priv = new GLFbPC(x, y, osd_buf);
si = glfb_priv->getScreenInfo();
start();
while (!glfb_priv->mInitDone)
usleep(1);
}
GLFramebuffer::~GLFramebuffer()
{
glfb_priv->mShutDown = true;
join();
delete glfb_priv;
glfb_priv = NULL;
}
void GLFramebuffer::blit()
{
glfb_priv->blit();
}
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
{
osd_buf = &buf;
mState.width = x;
mState.height = y;
mX = &_mX[0];
mY = &_mY[0];
*mX = x;
*mY = y;
av_reduce(&mOA.num, &mOA.den, x, y, INT_MAX);
mVA = mOA; /* initial aspect ratios are from the FB resolution, those */
_mVA = mVA; /* will be updated by the videoDecoder functions anyway */
mVAchanged = true;
mCrop = DISPLAY_AR_MODE_PANSCAN;
zoom = 1.0;
xscale = 1.0;
const char *tmp = getenv("GLFB_FULLSCREEN");
mFullscreen = !!(tmp);
mState.blit = true;
last_apts = 0;
/* linux framebuffer compat mode */
si.bits_per_pixel = 32;
si.xres = mState.width;
si.xres_virtual = si.xres;
si.yres = mState.height;
si.yres_virtual = si.yres;
si.blue.length = 8;
si.blue.offset = 0;
si.green.length = 8;
si.green.offset = 8;
si.red.length = 8;
si.red.offset = 16;
si.transp.length = 8;
si.transp.offset = 24;
unlink("/tmp/neutrino.input");
mkfifo("/tmp/neutrino.input", 0600);
input_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
if (input_fd < 0)
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
initKeys();
}
GLFbPC::~GLFbPC()
{
mShutDown = true;
if (input_fd >= 0)
close(input_fd);
osd_buf->clear();
}
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_F5] = KEY_RECORD;
mKeyMap[CLUTTER_KEY_F6] = KEY_PLAY;
mKeyMap[CLUTTER_KEY_F7] = KEY_PAUSE;
mKeyMap[CLUTTER_KEY_F8] = KEY_STOP;
mKeyMap[CLUTTER_KEY_F9] = KEY_FORWARD;
mKeyMap[CLUTTER_KEY_F10] = KEY_REWIND;
mKeyMap[CLUTTER_KEY_F11] = KEY_NEXT;
mKeyMap[CLUTTER_KEY_F12] = KEY_PREVIOUS;
mKeyMap[CLUTTER_KEY_Page_Up] = KEY_PAGEUP;
mKeyMap[CLUTTER_KEY_Page_Down] = KEY_PAGEDOWN;
mKeyMap[CLUTTER_KEY_Return] = KEY_OK;
mKeyMap[CLUTTER_KEY_Escape] = KEY_EXIT;
mKeyMap['0'] = KEY_0;
mKeyMap['1'] = KEY_1;
mKeyMap['2'] = KEY_2;
mKeyMap['3'] = KEY_3;
mKeyMap['4'] = KEY_4;
mKeyMap['5'] = KEY_5;
mKeyMap['6'] = KEY_6;
mKeyMap['7'] = KEY_7;
mKeyMap['8'] = KEY_8;
mKeyMap['9'] = KEY_9;
mKeyMap['+'] = KEY_VOLUMEUP;
mKeyMap['-'] = KEY_VOLUMEDOWN;
mKeyMap['.'] = KEY_MUTE;
mKeyMap['a'] = KEY_AUDIO;
mKeyMap['e'] = KEY_EPG;
// ['f'] is reserved to toggle fullscreen;
mKeyMap['g'] = KEY_GAMES;
mKeyMap['h'] = KEY_HELP;
mKeyMap['i'] = KEY_INFO;
mKeyMap['m'] = KEY_MENU;
mKeyMap['p'] = KEY_POWER;
mKeyMap['r'] = KEY_RADIO;
mKeyMap['s'] = KEY_SUBTITLE;
mKeyMap['t'] = KEY_TV;
mKeyMap['v'] = KEY_VIDEO;
mKeyMap['z'] = KEY_SLEEP;
/* shift keys */
mKeyMap['F'] = KEY_FAVORITES;
mKeyMap['M'] = KEY_MODE;
mKeyMap['S'] = KEY_SAT;
mKeyMap['T'] = KEY_TEXT;
mKeyMap['W'] = KEY_WWW;
}
static ClutterActor *stage = NULL;
static ClutterActor *fb_actor = NULL;
static ClutterActor *vid_actor = NULL;
static ClutterTimeline *tl = NULL;
void GLFramebuffer::run()
{
int argc = 1;
int x = glfb_priv->mState.width;
int y = glfb_priv->mState.height;
/* some dummy commandline for GLUT to be happy */
char *a = (char *)"neutrino";
char **argv = (char **)malloc(sizeof(char *) * 2);
argv[0] = a;
argv[1] = NULL;
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
if (clutter_init(&argc, &argv) != CLUTTER_INIT_SUCCESS) {
lt_info("GLFB: error initializing clutter\n");
return;
}
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);
clutter_actor_set_background_color(stage, &stage_color);
clutter_actor_set_content_gravity(stage, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
//g_signal_connect(stage, "destroy", G_CALLBACK(clutter_main_quit), NULL);
g_signal_connect(stage, "key-press-event", G_CALLBACK(GLFbPC::keyboardcb), (void *)1);
g_signal_connect(stage, "key-release-event", G_CALLBACK(GLFbPC::keyboardcb), NULL);
clutter_stage_set_user_resizable(CLUTTER_STAGE (stage), TRUE);
clutter_actor_grab_key_focus(stage);
clutter_actor_show(stage);
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = x * y * 4 * 2;
osd_buf.resize(fbmem);
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)) {
lt_info("GLFB::%s clutter_image_set_data failed? (vid)\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(vid_actor, fb);
g_object_unref(fb);
clutter_actor_set_size(vid_actor, x, y);
clutter_actor_set_position(vid_actor, 0, 0);
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
clutter_actor_set_content_gravity(vid_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
clutter_actor_set_pivot_point(vid_actor, 0.5, 0.5);
clutter_actor_add_child(stage, vid_actor);
clutter_actor_show(vid_actor);
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)) {
lt_info("GLFB::%s clutter_image_set_data failed? (osd)\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(fb_actor, fb);
g_object_unref(fb);
clutter_actor_set_size(fb_actor, x, y);
clutter_actor_set_position(fb_actor, 0, 0);
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
clutter_actor_set_content_gravity(fb_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
clutter_actor_add_child(stage, fb_actor);
clutter_actor_show(fb_actor);
glfb_priv->mInitDone = true; /* signal that setup is finished */
tl = clutter_timeline_new(100);
g_signal_connect(tl, "new-frame", G_CALLBACK(GLFbPC::rendercb), NULL);
clutter_timeline_set_repeat_count(tl, -1);
clutter_timeline_start(tl);
clutter_main();
g_object_unref(tl);
free(argv);
lt_info("GLFB: GL thread stopping\n");
}
/* static */ void GLFbPC::rendercb()
{
glfb_priv->render();
}
/* static */ bool GLFbPC::keyboardcb(ClutterActor * /*actor*/, ClutterEvent *event, gpointer user_data)
{
guint key = clutter_event_get_key_symbol (event);
int keystate = user_data ? 1 : 0;
lt_debug_c("GLFB::%s: 0x%x, %d\n", __func__, key, keystate);
struct input_event ev;
if (key == 'f' && keystate)
{
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;
}
std::map<int, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
if (i == glfb_priv->mKeyMap.end())
return true;
ev.code = i->second;
ev.value = keystate; /* key own */
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(glfb_priv->input_fd, &ev, sizeof(ev));
return true;
}
int sleep_us = 30000;
void GLFbPC::render()
{
if(mShutDown)
clutter_main_quit();
mReInitLock.lock();
if (vdec && vdec->pig_changed)
{
mReInit = true;
vdec->pig_changed = false;
}
if (mReInit)
{
int xoff = 0;
int yoff = 0;
mVAchanged = true;
mReInit = false;
#if 0
mX = &_mX[mFullscreen];
mY = &_mY[mFullscreen];
#endif
*mX = *mY * mOA.num / mOA.den;
if (mFullscreen) {
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), TRUE);
clutter_actor_show(stage);
clutter_stage_ensure_redraw(CLUTTER_STAGE(stage));
} else {
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), FALSE);
// *mX = *mY * mOA.num / mOA.den;
clutter_actor_set_size(stage, *mX, *mY);
}
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;
lt_debug("GLFB::%s blit!\n", __func__);
bltOSDBuffer(); /* OSD */
}
if (mVAchanged)
{
mVAchanged = false;
zoom = 1.0;
float xzoom = 1.0;
//xscale = 1.0;
int cmp = av_cmp_q(mVA, mOA);
const AVRational a149 = { 14, 9 };
switch (cmp) {
default:
case INT_MIN: /* invalid */
case 0: /* identical */
lt_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
break;
case 1: /* mVA > mOA -- video is wider than display */
lt_debug("%s: mVA > mOA\n", __func__);
switch (mCrop) {
case DISPLAY_AR_MODE_PANSCAN:
zoom = av_q2d(mVA) / av_q2d(mOA);
break;
case DISPLAY_AR_MODE_LETTERBOX:
break;
case DISPLAY_AR_MODE_PANSCAN2:
zoom = av_q2d(a149) / av_q2d(mOA);
break;
case DISPLAY_AR_MODE_NONE:
xzoom = av_q2d(mOA) / av_q2d(mVA);
zoom = av_q2d(mVA) / av_q2d(mOA);
break;
default:
break;
}
break;
case -1: /* mVA < mOA -- video is taller than display */
lt_debug("%s: mVA < mOA\n", __func__);
switch (mCrop) {
case DISPLAY_AR_MODE_LETTERBOX:
break;
case DISPLAY_AR_MODE_PANSCAN2:
if (av_cmp_q(a149, mOA) < 0) {
zoom = av_q2d(mVA) * av_q2d(a149) / av_q2d(mOA);
break;
}
/* fallthrough for output format 14:9 */
case DISPLAY_AR_MODE_PANSCAN:
zoom = av_q2d(mOA) / av_q2d(mVA);
break;
case DISPLAY_AR_MODE_NONE:
xzoom = av_q2d(mOA) / av_q2d(mVA);
break;
default:
break;
}
break;
}
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);
clutter_timeline_set_delay(tl, sleep_us/1000);
clutter_timeline_start(tl);
}
void GLFbPC::bltOSDBuffer()
{
// 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)) {
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(fb_actor, fb);
g_object_unref(fb);
clutter_actor_show(fb_actor);
}
void GLFbPC::bltDisplayBuffer()
{
// lt_info("GLFB::%s vdec: %p\n", __func__, vdec);
if (!vdec) /* cannot start yet */
return;
static bool warn = true;
VDec::SWFramebuffer *buf = vdec->getDecBuf();
if (!buf) {
if (warn)
lt_info("GLFB::%s did not get a buffer...\n", __func__);
warn = false;
return;
}
warn = true;
int w = buf->width(), h = buf->height();
if (w == 0 || h == 0)
return;
AVRational a = buf->AR();
if (a.den != 0 && a.num != 0 && av_cmp_q(a, _mVA)) {
_mVA = a;
/* _mVA is the raw buffer's aspect, mVA is the real scaled output aspect */
av_reduce(&mVA.num, &mVA.den, w * a.num, h * a.den, INT_MAX);
// mVA.num: 16 mVA.den: 9 w: 720 h: 576
// 16*576/720/9 = 1.42222
xscale = (double)mVA.num*h/(double)mVA.den/w;
mVAchanged = true;
}
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)) {
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
_exit(1); /* life is hard */
}
clutter_actor_set_content(vid_actor, fb);
g_object_unref(fb);
clutter_actor_show(vid_actor);
/* "rate control" mechanism starts here...
* this implementation is pretty naive and not working too well, but
* better this than nothing... :-) */
int64_t apts = 0;
int64_t vpts = buf->pts();
if (adec)
apts = adec->getPts();
if (apts != last_apts) {
int rate, dummy1, dummy2;
if (apts < vpts)
sleep_us = (sleep_us * 2 + (vpts - apts)*10/9) / 3;
else if (sleep_us > 1000)
sleep_us -= 1000;
last_apts = apts;
vdec->getPictureInfo(dummy1, dummy2, rate);
if (rate > 0)
rate = 2000000 / rate; /* limit to half the frame rate */
else
rate = 50000; /* minimum 20 fps */
if (sleep_us > rate)
sleep_us = rate;
else if (sleep_us < 1)
sleep_us = 1;
}
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

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

View File

@@ -32,26 +32,21 @@
#include <cstdio>
#include <string>
#include <unistd.h>
#include "dmx_lib.h"
#include <sys/ioctl.h>
#include "dmx_hal.h"
#include "lt_debug.h"
/* needed for getSTC :-( */
#include "video_lib.h"
extern cVideo *videoDecoder;
#include "video_priv.h"
extern VDec *vdec;
#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 { \
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
if (dmx_type == DMX_PSI_CHANNEL) { \
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
} else { \
_pid = p_flt.pid; \
}; \
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, _f); \
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
} while(0);
cDemux *videoDemux = NULL;
@@ -92,9 +87,6 @@ cDemux::cDemux(int n)
else
num = n;
fd = -1;
measure = false;
last_measure = 0;
last_data = 0;
}
cDemux::~cDemux()
@@ -160,8 +152,6 @@ void cDemux::Close(void)
ioctl(fd, DMX_STOP);
close(fd);
fd = -1;
if (measure)
return;
if (dmx_type == DMX_TP_CHANNEL)
{
dmx_tp_count--;
@@ -253,11 +243,13 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
return rc;
}
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
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)
{
@@ -266,6 +258,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
}
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)
@@ -366,8 +359,11 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
return true;
}
bool cDemux::pesFilter(const unsigned short pid)
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...
@@ -478,8 +474,8 @@ void cDemux::removePid(unsigned short Pid)
void cDemux::getSTC(int64_t * STC)
{
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->GetPTS();
if (vdec)
pts = vdec->GetPTS();
*STC = pts;
}

View File

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

View File

@@ -1,70 +0,0 @@
#ifndef __DEMUX_TD_H
#define __DEMUX_TD_H
#include <cstdlib>
#include <vector>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include "../common/cs_types.h"
#define MAX_DMX_UNITS 4
typedef enum
{
DMX_INVALID = 0,
DMX_VIDEO_CHANNEL = 1,
DMX_AUDIO_CHANNEL,
DMX_PES_CHANNEL,
DMX_PSI_CHANNEL,
DMX_PIP_CHANNEL,
DMX_TP_CHANNEL,
DMX_PCR_ONLY_CHANNEL
} DMX_CHANNEL_TYPE;
typedef struct
{
int fd;
unsigned short pid;
} pes_pids;
class cDemux
{
private:
int num;
int fd;
int buffersize;
bool measure;
uint64_t last_measure, last_data;
DMX_CHANNEL_TYPE dmx_type;
std::vector<pes_pids> pesfds;
struct dmx_sct_filter_params s_flt;
struct dmx_pes_filter_params p_flt;
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);
// TD only functions
int getFD(void) { return fd; }; /* needed by cPlayback class */
void removePid(unsigned short Pid); /* needed by cRecord class */
std::vector<pes_pids> getPesPids(void) { return pesfds; };
//
cDemux(int num = 0);
~cDemux();
};
#endif //__DEMUX_H

View File

@@ -22,6 +22,7 @@
TODO: AV-Sync code is "experimental" at best
*/
#include "config.h"
#include <vector>
#include <sys/types.h>
@@ -37,9 +38,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include "glfb.h"
#include "video_lib.h"
#include "audio_lib.h"
#include "glfb_priv.h"
#include "video_priv.h"
#include "audio_priv.h"
#include "lt_debug.h"
@@ -49,13 +50,39 @@
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
extern cVideo *videoDecoder;
extern cAudio *audioDecoder;
extern VDec *vdec;
extern ADec *adec;
static GLFramebuffer *gThiz = 0; /* GLUT does not allow for an arbitrary argument to the render func */
/* the private class that does stuff only needed inside libstb-hal.
* is used e.g. by cVideo... */
GLFbPC *glfb_priv = NULL;
GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mInitDone(false)
GLFramebuffer::GLFramebuffer(int x, int y)
{
Init();
glfb_priv = new GLFbPC(x, y, osd_buf);
si = glfb_priv->getScreenInfo();
start();
while (!glfb_priv->mInitDone)
usleep(1);
}
GLFramebuffer::~GLFramebuffer()
{
glfb_priv->mShutDown = true;
join();
delete glfb_priv;
glfb_priv = NULL;
}
void GLFramebuffer::blit()
{
glfb_priv->blit();
}
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
{
osd_buf = &buf;
mState.width = x;
mState.height = y;
mX = &_mX[0];
@@ -76,19 +103,19 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
last_apts = 0;
/* linux framebuffer compat mode */
screeninfo.bits_per_pixel = 32;
screeninfo.xres = mState.width;
screeninfo.xres_virtual = screeninfo.xres;
screeninfo.yres = mState.height;
screeninfo.yres_virtual = screeninfo.yres;
screeninfo.blue.length = 8;
screeninfo.blue.offset = 0;
screeninfo.green.length = 8;
screeninfo.green.offset = 8;
screeninfo.red.length = 8;
screeninfo.red.offset = 16;
screeninfo.transp.length = 8;
screeninfo.transp.offset = 24;
si.bits_per_pixel = 32;
si.xres = mState.width;
si.xres_virtual = si.xres;
si.yres = mState.height;
si.yres_virtual = si.yres;
si.blue.length = 8;
si.blue.offset = 0;
si.green.length = 8;
si.green.offset = 8;
si.red.length = 8;
si.red.offset = 16;
si.transp.length = 8;
si.transp.offset = 24;
unlink("/tmp/neutrino.input");
mkfifo("/tmp/neutrino.input", 0600);
@@ -96,50 +123,47 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
if (input_fd < 0)
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
initKeys();
OpenThreads::Thread::start();
while (!mInitDone)
usleep(1);
}
GLFramebuffer::~GLFramebuffer()
GLFbPC::~GLFbPC()
{
mShutDown = true;
OpenThreads::Thread::join();
if (input_fd >= 0)
close(input_fd);
osd_buf->clear();
}
void GLFramebuffer::initKeys()
void GLFbPC::initKeys()
{
/*
Keep in sync with initKeys() in clutterfb.cpp
*/
mSpecialMap[GLUT_KEY_UP] = KEY_UP;
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
mSpecialMap[GLUT_KEY_LEFT] = KEY_LEFT;
mSpecialMap[GLUT_KEY_RIGHT] = KEY_RIGHT;
mSpecialMap[GLUT_KEY_F1] = KEY_RED;
mSpecialMap[GLUT_KEY_F2] = KEY_GREEN;
mSpecialMap[GLUT_KEY_F3] = KEY_YELLOW;
mSpecialMap[GLUT_KEY_F4] = KEY_BLUE;
mSpecialMap[GLUT_KEY_F1] = KEY_RED;
mSpecialMap[GLUT_KEY_F2] = KEY_GREEN;
mSpecialMap[GLUT_KEY_F3] = KEY_YELLOW;
mSpecialMap[GLUT_KEY_F4] = KEY_BLUE;
mSpecialMap[GLUT_KEY_F5] = KEY_WWW;
mSpecialMap[GLUT_KEY_F6] = KEY_SUBTITLE;
mSpecialMap[GLUT_KEY_F7] = KEY_MOVE;
mSpecialMap[GLUT_KEY_F8] = KEY_SLEEP;
mSpecialMap[GLUT_KEY_F5] = KEY_RECORD;
mSpecialMap[GLUT_KEY_F6] = KEY_PLAY;
mSpecialMap[GLUT_KEY_F7] = KEY_PAUSE;
mSpecialMap[GLUT_KEY_F8] = KEY_STOP;
mSpecialMap[GLUT_KEY_F9] = KEY_FORWARD;
mSpecialMap[GLUT_KEY_F10] = KEY_REWIND;
mSpecialMap[GLUT_KEY_F11] = KEY_NEXT;
mSpecialMap[GLUT_KEY_F12] = KEY_PREVIOUS;
mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP;
mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN;
mKeyMap[0x0d] = KEY_OK;
mKeyMap[0x1b] = KEY_EXIT;
mKeyMap['e'] = KEY_EPG;
mKeyMap['i'] = KEY_INFO;
mKeyMap['m'] = KEY_MENU;
mKeyMap['+'] = KEY_VOLUMEUP;
mKeyMap['-'] = KEY_VOLUMEDOWN;
mKeyMap['.'] = KEY_MUTE;
mKeyMap['h'] = KEY_HELP;
mKeyMap['p'] = KEY_POWER;
mKeyMap['0'] = KEY_0;
mKeyMap['1'] = KEY_1;
@@ -151,13 +175,49 @@ void GLFramebuffer::initKeys()
mKeyMap['7'] = KEY_7;
mKeyMap['8'] = KEY_8;
mKeyMap['9'] = KEY_9;
mKeyMap['+'] = KEY_VOLUMEUP;
mKeyMap['-'] = KEY_VOLUMEDOWN;
mKeyMap['.'] = KEY_MUTE;
mKeyMap['a'] = KEY_AUDIO;
mKeyMap['e'] = KEY_EPG;
// ['f'] is reserved to toggle fullscreen;
mKeyMap['g'] = KEY_GAMES;
mKeyMap['h'] = KEY_HELP;
mKeyMap['i'] = KEY_INFO;
mKeyMap['m'] = KEY_MENU;
mKeyMap['p'] = KEY_POWER;
mKeyMap['r'] = KEY_RADIO;
mKeyMap['s'] = KEY_SUBTITLE;
mKeyMap['t'] = KEY_TV;
mKeyMap['v'] = KEY_VIDEO;
mKeyMap['z'] = KEY_SLEEP;
/* shift keys */
mKeyMap['F'] = KEY_FAVORITES;
mKeyMap['M'] = KEY_MODE;
mKeyMap['S'] = KEY_SAT;
mKeyMap['T'] = KEY_TEXT;
mKeyMap['W'] = KEY_WWW;
}
void GLFramebuffer::run()
{
setupCtx();
setupOSDBuffer();
mInitDone = true; /* signal that setup is finished */
int argc = 1;
int x = glfb_priv->mState.width;
int y = glfb_priv->mState.height;
/* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 };
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);
glutCreateWindow("Neutrino");
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = x * y * 4 * 2;
osd_buf.resize(fbmem);
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 */
GLenum err = glewInit();
@@ -172,16 +232,15 @@ void GLFramebuffer::run()
}
else
{
gThiz = this;
glutSetCursor(GLUT_CURSOR_NONE);
glutDisplayFunc(GLFramebuffer::rendercb);
glutKeyboardFunc(GLFramebuffer::keyboardcb);
glutSpecialFunc(GLFramebuffer::specialcb);
glutReshapeFunc(GLFramebuffer::resizecb);
setupGLObjects(); /* needs GLEW prototypes */
glutDisplayFunc(GLFbPC::rendercb);
glutKeyboardFunc(GLFbPC::keyboardcb);
glutSpecialFunc(GLFbPC::specialcb);
glutReshapeFunc(GLFbPC::resizecb);
glfb_priv->setupGLObjects(); /* needs GLEW prototypes */
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
releaseGLObjects();
glfb_priv->releaseGLObjects();
}
}
else
@@ -189,20 +248,20 @@ void GLFramebuffer::run()
lt_info("GLFB: GL thread stopping\n");
}
void GLFramebuffer::setupCtx()
#if 0
void GLFbPC::setupCtx()
{
int argc = 1;
/* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 };
lt_info("GLFB: GL thread starting\n");
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);
glutCreateWindow("Neutrino");
}
void GLFramebuffer::setupOSDBuffer()
void GLFbPC::setupOSDBuffer()
{ /* the OSD buffer size can be decoupled from the actual
window size since the GL can blit-stretch with no
trouble at all, ah, the luxury of ignorance... */
@@ -211,12 +270,13 @@ void GLFramebuffer::setupOSDBuffer()
{
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = mState.width * mState.height * 4 * 2;
mOSDBuffer.resize(fbmem);
lt_info("GLFB: OSD buffer set to %d bytes\n", fbmem);
osd_buf->resize(fbmem);
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
}
}
#endif
void GLFramebuffer::setupGLObjects()
void GLFbPC::setupGLObjects()
{
unsigned char buf[4] = { 0, 0, 0, 0 }; /* 1 black pixel */
glGenTextures(1, &mState.osdtex);
@@ -244,7 +304,7 @@ void GLFramebuffer::setupGLObjects()
}
void GLFramebuffer::releaseGLObjects()
void GLFbPC::releaseGLObjects()
{
glDeleteBuffers(1, &mState.pbo);
glDeleteBuffers(1, &mState.displaypbo);
@@ -253,56 +313,56 @@ void GLFramebuffer::releaseGLObjects()
}
/* static */ void GLFramebuffer::rendercb()
/* static */ void GLFbPC::rendercb()
{
gThiz->render();
glfb_priv->render();
}
/* static */ void GLFramebuffer::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
/* static */ void GLFbPC::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
{
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev;
if (key == 'f')
{
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, gThiz->mFullscreen?"off":"on");
gThiz->mFullscreen = !(gThiz->mFullscreen);
gThiz->mReInit = true;
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;
}
std::map<unsigned char, int>::const_iterator i = gThiz->mKeyMap.find(key);
if (i == gThiz->mKeyMap.end())
std::map<unsigned char, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
if (i == glfb_priv->mKeyMap.end())
return;
ev.code = i->second;
ev.value = 1; /* key own */
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(gThiz->input_fd, &ev, sizeof(ev));
write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0; /* neutrino is stupid, so push key up directly after key down */
write(gThiz->input_fd, &ev, sizeof(ev));
write(glfb_priv->input_fd, &ev, sizeof(ev));
}
/* static */ void GLFramebuffer::specialcb(int key, int /*x*/, int /*y*/)
/* static */ void GLFbPC::specialcb(int key, int /*x*/, int /*y*/)
{
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev;
std::map<int, int>::const_iterator i = gThiz->mSpecialMap.find(key);
if (i == gThiz->mSpecialMap.end())
std::map<int, int>::const_iterator i = glfb_priv->mSpecialMap.find(key);
if (i == glfb_priv->mSpecialMap.end())
return;
ev.code = i->second;
ev.value = 1;
ev.type = EV_KEY;
gettimeofday(&ev.time, NULL);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(gThiz->input_fd, &ev, sizeof(ev));
write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0;
write(gThiz->input_fd, &ev, sizeof(ev));
write(glfb_priv->input_fd, &ev, sizeof(ev));
}
int sleep_us = 30000;
void GLFramebuffer::render()
void GLFbPC::render()
{
if(mShutDown)
glutLeaveMainLoop();
@@ -430,12 +490,12 @@ void GLFramebuffer::render()
glutPostRedisplay();
}
/* static */ void GLFramebuffer::resizecb(int w, int h)
/* static */ void GLFbPC::resizecb(int w, int h)
{
gThiz->checkReinit(w, h);
glfb_priv->checkReinit(w, h);
}
void GLFramebuffer::checkReinit(int x, int y)
void GLFbPC::checkReinit(int x, int y)
{
static int last_x = 0, last_y = 0;
@@ -455,7 +515,7 @@ void GLFramebuffer::checkReinit(int x, int y)
last_y = y;
}
void GLFramebuffer::drawSquare(float size, float x_factor)
void GLFbPC::drawSquare(float size, float x_factor)
{
GLfloat vertices[] = {
1.0f, 1.0f,
@@ -473,17 +533,17 @@ void GLFramebuffer::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 */
@@ -511,11 +571,11 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
}
void GLFramebuffer::bltOSDBuffer()
void GLFbPC::bltOSDBuffer()
{
/* FIXME: copy each time */
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mState.pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, mOSDBuffer.size(), &mOSDBuffer[0], GL_STREAM_DRAW_ARB);
glBufferData(GL_PIXEL_UNPACK_BUFFER, osd_buf->size(), osd_buf->data(), GL_STREAM_DRAW_ARB);
glBindTexture(GL_TEXTURE_2D, mState.osdtex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mState.width, mState.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
@@ -523,12 +583,12 @@ void GLFramebuffer::bltOSDBuffer()
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
void GLFramebuffer::bltDisplayBuffer()
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)
lt_info("GLFB::%s did not get a buffer...\n", __func__);
@@ -560,10 +620,9 @@ void GLFramebuffer::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)
@@ -571,7 +630,7 @@ void GLFramebuffer::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
@@ -582,11 +641,5 @@ void GLFramebuffer::bltDisplayBuffer()
sleep_us = 1;
}
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, videoDecoder->buf_num);
}
void GLFramebuffer::clear()
{
/* clears front and back buffer */
memset(&mOSDBuffer[0], 0, mOSDBuffer.size());
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
}

View File

@@ -1,6 +1,6 @@
/*
Copyright 2010 Carsten Juttner <carjay@gmx.net>
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
Copyright 2012,2013,2016 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
@@ -14,42 +14,46 @@
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 of the GLFB thread that is only used inside libstb-hal
and not exposed to the application.
*/
#ifndef __glthread__
#define __glthread__
#include <OpenThreads/Thread>
#ifndef __glfb_priv__
#define __glfb_priv__
#include <OpenThreads/Mutex>
#include <vector>
#include <map>
#if USE_OPENGL
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <linux/fb.h> /* for screeninfo etc. */
#endif
#if USE_CLUTTER
#include <clutter/clutter.h>
#endif
#include "glfb.h"
extern "C" {
#include <libavutil/rational.h>
}
class GLFramebuffer : public OpenThreads::Thread
class GLFbPC
{
public:
GLFramebuffer(int x, int y);
~GLFramebuffer();
void run();
std::vector<unsigned char> *getOSDBuffer() { return &mOSDBuffer; } /* pointer to OSD bounce buffer */
GLFbPC(int x, int y, std::vector<unsigned char> &buf);
~GLFbPC();
std::vector<unsigned char> *getOSDBuffer() { return osd_buf; } /* pointer to OSD bounce buffer */
int getOSDWidth() { return mState.width; }
int getOSDHeight() { return mState.height; }
void blit() { mState.blit = true; }
void blit() { mState.blit = true; };
fb_var_screeninfo getScreenInfo() { return si; }
void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; }
void clear();
fb_var_screeninfo getScreenInfo() { return screeninfo; }
/* just make everything public for simplicity - this is only used inside libstb-hal anyway
private:
fb_var_screeninfo screeninfo;
*/
fb_var_screeninfo si;
int *mX;
int *mY;
int _mX[2]; /* output window size */
@@ -70,35 +74,50 @@ private:
// OpenThreads::Condition mInitCond; /* condition variable for init */
// mutable OpenThreads::Mutex mMutex; /* lock our data */
std::vector<unsigned char> mOSDBuffer; /* silly bounce buffer */
std::vector<unsigned char> *osd_buf; /* silly bounce buffer */
#if USE_OPENGL
std::map<unsigned char, int> mKeyMap;
std::map<int, int> mSpecialMap;
#endif
#if USE_CLUTTER
std::map<int, int> mKeyMap;
#endif
int input_fd;
int64_t last_apts;
void run();
static void rendercb(); /* callback for GLUT */
void render(); /* actual render function */
#if USE_OPENGL
static void keyboardcb(unsigned char key, int x, int y);
static void specialcb(int key, int x, int y);
static void resizecb(int w, int h);
void checkReinit(int w, int h); /* e.g. in case window was resized */
void initKeys(); /* setup key bindings for window */
void setupCtx(); /* create the window and make the context current */
void setupOSDBuffer(); /* create the OSD buffer */
void setupGLObjects(); /* PBOs, textures and stuff */
void releaseGLObjects();
void drawSquare(float size, float x_factor = 1); /* do not be square */
#endif
#if USE_CLUTTER
static bool keyboardcb(ClutterActor *actor, ClutterEvent *event, gpointer user_data);
#endif
void initKeys(); /* setup key bindings for window */
#if 0
void setupCtx(); /* create the window and make the context current */
void setupOSDBuffer(); /* create the OSD buffer */
#endif
struct {
int width; /* width and height, fixed for a framebuffer instance */
int height;
bool blit;
#if USE_OPENGL
GLuint osdtex; /* holds the OSD texture */
GLuint pbo; /* PBO we use for transfer to texture */
GLuint displaytex; /* holds the display texture */
GLuint displaypbo;
bool blit;
#endif
} mState;
void bltOSDBuffer();

View File

@@ -2,24 +2,22 @@
* 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 <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>
static int initialized = 0;
static hw_caps_t caps;
hw_caps_t *get_hwcaps(void)
{
struct utsname u;
if (initialized)
return &caps;
@@ -30,8 +28,13 @@ hw_caps_t *get_hwcaps(void)
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.has_HDMI = 1;
caps.display_xres = 8;
caps.can_set_display_brightness = 0;
strcpy(caps.boxvendor, "Generic");
strcpy(caps.boxname, "PC");
if (! uname(&u))
strncpy(caps.boxarch, u.machine, sizeof(caps.boxarch));
else
fprintf(stderr, "%s: uname() failed: %m\n", __func__);
return &caps;
}

View File

@@ -1,7 +1,8 @@
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include "init_lib.h"
#include "init_td.h"
#include "lt_debug.h"
#include "glfb.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
@@ -50,5 +51,6 @@ void shutdown_td_api()
lt_info("%s, initialized = %d\n", __func__, (int)initialized);
if (glfb)
delete glfb;
glfb = NULL;
initialized = false;
}

View File

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

View File

@@ -1,6 +1,6 @@
#include <stdio.h>
#include "playback.h"
#include "playback_hal.h"
static const char * FILENAME = "playback-dummy";
@@ -13,20 +13,25 @@ void cPlayback::Close(void)
{
}
bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, bool ac3, int duration)
bool cPlayback::Start(std::string /*filename*/, std::string /*headers*/)
{
return false;
}
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(unsigned short 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)
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
{
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
return true;
@@ -34,7 +39,7 @@ bool cPlayback::SelectSubtitles(int pid)
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;
}
@@ -75,6 +80,26 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
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*/)
{
printf("%s:%s\n", FILENAME, __func__);

View File

@@ -1,36 +0,0 @@
#ifndef __PLAYBACK_H
#define __PLAYBACK_H
#include <string>
#include <stdint.h>
#include <vector>
typedef enum {
PLAYMODE_TS = 0,
PLAYMODE_FILE,
} playmode_t;
class cPlayback
{
private:
bool playing;
public:
bool Open(playmode_t PlayMode);
void Close(void);
bool Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, bool ac3, int duration);
bool Stop(void);
bool SetAPid(unsigned short pid, bool ac3);
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 *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language);
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
bool SelectSubtitles(int pid);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
//
cPlayback(int num = 0);
~cPlayback();
};
#endif

View File

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

View File

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

View File

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

View File

@@ -23,6 +23,7 @@
* TODO: buffer handling surely needs some locking...
*/
#include "config.h"
#include <unistd.h>
#include <cstring>
#include <cstdio>
@@ -30,6 +31,7 @@
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
@@ -38,17 +40,26 @@ extern "C" {
/* my own buf 256k */
#define DMX_BUF_SZ 0x20000
#include "video_lib.h"
#include "dmx_lib.h"
#include "glfb.h"
#if USE_OPENGL
#define VDEC_PIXFMT AV_PIX_FMT_RGB32
#endif
#if USE_CLUTTER
#define VDEC_PIXFMT AV_PIX_FMT_BGR24
#endif
#include "video_hal.h"
#include "dmx_hal.h"
#include "glfb_priv.h"
#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 GLFramebuffer *glfb;
extern GLFbPC *glfb_priv;
int system_rev = 0;
extern bool HAL_nodec;
@@ -68,6 +79,13 @@ static const AVRational aspect_ratios[6] = {
cVideo::cVideo(int, void *, void *, unsigned int)
{
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();
if (!HAL_nodec)
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
@@ -79,31 +97,52 @@ cVideo::cVideo(int, void *, void *, unsigned int)
buf_in = 0;
buf_out = 0;
pig_x = pig_y = pig_w = pig_h = 0;
pig_changed = false;
display_aspect = DISPLAY_AR_16_9;
display_crop = DISPLAY_AR_MODE_LETTERBOX;
v_format = VIDEO_FORMAT_MPEG2;
output_h = 0;
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)
{
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)
display_crop = (DISPLAY_AR_MODE) cropping;
if (display_aspect < DISPLAY_AR_RAW) /* don't know what to do with this */
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
return 0;
}
int cVideo::getAspectRatio(void)
{
return vdec->getAspectRatio();
}
int VDec::getAspectRatio(void)
{
buf_m.lock();
int ret = 0;
@@ -132,12 +171,22 @@ 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 *)
{
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)
@@ -146,7 +195,7 @@ int cVideo::Start(void *, unsigned short, unsigned short, void *)
return 0;
}
int cVideo::Stop(bool)
int VDec::Stop(bool)
{
lt_debug("%s running %d >\n", __func__, thread_running);
if (thread_running) {
@@ -162,7 +211,29 @@ int cVideo::setBlank(int)
return 1;
}
int cVideo::GetVideoSystem()
{
return vdec->GetVideoSystem();
}
int VDec::GetVideoSystem()
{
int current_video_system = VIDEO_STD_1080I50;
if(dec_w < 720)
current_video_system = VIDEO_STD_PAL;
else if(dec_w > 720 && dec_w <= 1280)
current_video_system = VIDEO_STD_720P50;
return current_video_system;
}
int cVideo::SetVideoSystem(int system, bool)
{
return vdec->SetVideoSystem(system);
}
int VDec::SetVideoSystem(int system)
{
int h;
switch(system)
@@ -195,16 +266,16 @@ int cVideo::SetVideoSystem(int system, bool)
lt_info("%s: unhandled value %d\n", __func__, system);
return 0;
}
v_std = (VIDEO_STD) system;
// v_std = (VIDEO_STD) system;
output_h = h;
if (display_aspect < DISPLAY_AR_RAW) /* don't know what to do with this */
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
return 0;
}
int cVideo::getPlayState(void)
{
return VIDEO_PLAYING;
return 1;
}
void cVideo::SetVideoMode(analog_mode_t)
@@ -212,10 +283,21 @@ void cVideo::SetVideoMode(analog_mode_t)
}
void cVideo::ShowPicture(const char *fname)
{
vdec->ShowPicture(fname);
}
void VDec::ShowPicture(const char *fname)
{
lt_info("%s(%s)\n", __func__, fname);
if (access(fname, R_OK))
return;
still_m.lock();
stillpicture = true;
buf_num = 0;
buf_in = 0;
buf_out = 0;
still_m.unlock();
unsigned int i;
int stream_id = -1;
@@ -223,6 +305,7 @@ void cVideo::ShowPicture(const char *fname)
int len;
AVFormatContext *avfc = NULL;
AVCodecContext *c = NULL;
AVCodecParameters *p = NULL;
AVCodec *codec;
AVFrame *frame, *rgbframe;
AVPacket avpkt;
@@ -237,21 +320,22 @@ void cVideo::ShowPicture(const char *fname)
goto out_close;
}
for (i = 0; i < avfc->nb_streams; i++) {
if (avfc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
if (avfc->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
stream_id = i;
break;
}
}
if (stream_id < 0)
goto out_close;
c = avfc->streams[stream_id]->codec;
codec = avcodec_find_decoder(c->codec_id);
if (!avcodec_open2(c, codec, NULL) < 0) {
lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, c->codec_id);
p = avfc->streams[stream_id]->codecpar;
codec = avcodec_find_decoder(p->codec_id);
c = avcodec_alloc_context3(codec);
if (avcodec_open2(c, codec, NULL) < 0) {
lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, p->codec_id);
goto out_close;
}
frame = avcodec_alloc_frame();
rgbframe = avcodec_alloc_frame();
frame = av_frame_alloc();
rgbframe = av_frame_alloc();
if (!frame || !rgbframe) {
lt_info("%s: Could not allocate video frame\n", __func__);
goto out_free;
@@ -264,15 +348,15 @@ void cVideo::ShowPicture(const char *fname)
len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (len < 0) {
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
goto out_free;
}
if (avpkt.size > len)
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
if (got_frame) {
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
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, PIX_FMT_RGB32,
c->width, c->height, VDEC_PIXFMT,
SWS_BICUBIC, 0, 0, 0);
if (!convert)
lt_info("%s: ERROR setting up SWS context\n", __func__);
@@ -281,8 +365,8 @@ void cVideo::ShowPicture(const char *fname)
SWFramebuffer *f = &buffers[buf_in];
if (f->size() < need)
f->resize(need);
avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
c->width, c->height);
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
c->width, c->height, 1);
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
rgbframe->data, rgbframe->linesize);
sws_freeContext(convert);
@@ -303,11 +387,12 @@ void cVideo::ShowPicture(const char *fname)
buf_m.unlock();
}
}
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
out_free:
avcodec_close(c);
avcodec_free_frame(&frame);
avcodec_free_frame(&rgbframe);
av_free(c);
av_frame_free(&frame);
av_frame_free(&rgbframe);
out_close:
avformat_close_input(&avfc);
lt_debug("%s(%s) end\n", __func__, fname);
@@ -315,6 +400,10 @@ void cVideo::ShowPicture(const char *fname)
void cVideo::StopPicture()
{
lt_info("%s\n", __func__);
vdec->still_m.lock();
vdec->stillpicture = false;
vdec->still_m.unlock();
}
void cVideo::Standby(unsigned int)
@@ -327,18 +416,54 @@ int cVideo::getBlank(void)
}
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;
pig_w = w;
pig_h = h;
pig_changed = true;
}
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;
rate = dec_r;
switch (dec_r) {
case 23://23.976fps
rate = VIDEO_FRAME_RATE_23_976;
break;
case 24:
rate = VIDEO_FRAME_RATE_24;
break;
case 25:
rate = VIDEO_FRAME_RATE_25;
break;
case 29://29,976fps
rate = VIDEO_FRAME_RATE_29_97;
break;
case 30:
rate = VIDEO_FRAME_RATE_30;
break;
case 50:
rate = VIDEO_FRAME_RATE_50;
break;
case 60:
rate = VIDEO_FRAME_RATE_60;
break;
default:
rate = dec_r;
break;
}
}
void cVideo::SetSyncMode(AVSYNC_TYPE)
@@ -346,12 +471,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) {
@@ -390,10 +520,11 @@ static int my_read(void *, uint8_t *buf, int buf_size)
return tmp;
}
void cVideo::run(void)
void VDec::run(void)
{
lt_info("====================== start decoder thread ================================\n");
AVCodec *codec;
AVCodecParameters *p = NULL;
AVCodecContext *c= NULL;
AVFormatContext *avfc = NULL;
AVInputFormat *inp;
@@ -434,26 +565,27 @@ void cVideo::run(void)
lt_info("%s: nb_streams %d, should be 1 => retry\n", __func__, avfc->nb_streams);
if (av_read_frame(avfc, &avpkt) < 0)
lt_info("%s: av_read_frame < 0\n", __func__);
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
if (! thread_running)
goto out;
}
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
lt_info("%s: no video codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);
p = avfc->streams[0]->codecpar;
if (p->codec_type != AVMEDIA_TYPE_VIDEO)
lt_info("%s: no video codec? 0x%x\n", __func__, p->codec_type);
c = avfc->streams[0]->codec;
codec = avcodec_find_decoder(c->codec_id);
codec = avcodec_find_decoder(p->codec_id);
if (!codec) {
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->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) {
lt_info("%s: Could not open codec\n", __func__);
goto out;
}
frame = avcodec_alloc_frame();
rgbframe = avcodec_alloc_frame();
frame = av_frame_alloc();
rgbframe = av_frame_alloc();
if (!frame || !rgbframe) {
lt_info("%s: Could not allocate video frame\n", __func__);
goto out2;
@@ -475,16 +607,17 @@ void cVideo::run(void)
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
warn_d = time(NULL);
}
av_free_packet(&avpkt);
av_packet_unref(&avpkt);
continue;
}
if (avpkt.size > len)
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
if (got_frame) {
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
still_m.lock();
if (got_frame && ! stillpicture) {
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
convert = sws_getCachedContext(convert,
c->width, c->height, c->pix_fmt,
c->width, c->height, PIX_FMT_RGB32,
c->width, c->height, VDEC_PIXFMT,
SWS_BICUBIC, 0, 0, 0);
if (!convert)
lt_info("%s: ERROR setting up SWS context\n", __func__);
@@ -493,8 +626,8 @@ void cVideo::run(void)
SWFramebuffer *f = &buffers[buf_in];
if (f->size() < need)
f->resize(need);
avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
c->width, c->height);
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
c->width, c->height, 1);
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
rgbframe->data, rgbframe->linesize);
if (dec_w != c->width || dec_h != c->height) {
@@ -507,8 +640,18 @@ void cVideo::run(void)
f->width(c->width);
f->height(c->height);
int64_t vpts = av_frame_get_best_effort_timestamp(frame);
/* a/v delay determined experimentally :-) */
#if USE_OPENGL
if (v_format == VIDEO_FORMAT_MPEG2)
vpts += 90000*4/10; /* 400ms */
else
vpts += 90000*3/10; /* 300ms */
#endif
#if USE_CLUTTER
/* no idea why there's a difference between OpenGL and clutter rendering... */
if (v_format == VIDEO_FORMAT_MPEG2)
vpts += 90000*3/10; /* 300ms */
#endif
f->pts(vpts);
AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame);
f->AR(a);
@@ -527,53 +670,84 @@ void cVideo::run(void)
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,
av_frame_get_best_effort_timestamp(frame));
}
av_free_packet(&avpkt);
} else
lt_info("%s: got_frame: %d stillpicture: %d\n", __func__, got_frame, stillpicture);
still_m.unlock();
av_packet_unref(&avpkt);
}
sws_freeContext(convert);
out2:
avcodec_close(c);
avcodec_free_frame(&frame);
avcodec_free_frame(&rgbframe);
av_free(c);
av_frame_free(&frame);
av_frame_free(&rgbframe);
out:
avformat_close_input(&avfc);
av_free(pIOCtx->buffer);
av_free(pIOCtx);
/* reset output buffers */
bufpos = 0;
buf_num = 0;
buf_in = 0;
buf_out = 0;
still_m.lock();
if (!stillpicture) {
buf_num = 0;
buf_in = 0;
buf_out = 0;
}
still_m.unlock();
lt_info("======================== end decoder thread ================================\n");
}
static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh)
static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh, AVPixelFormat sfmt)
{
bool ret = false;
int len = 0;
struct SwsContext *scale = NULL;
AVFrame *sframe, *dframe;
scale = sws_getCachedContext(scale, sw, sh, PIX_FMT_RGB32, dw, dh, PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0);
scale = sws_getCachedContext(scale, sw, sh, sfmt, dw, dh, AV_PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0);
if (!scale) {
lt_info_c("%s: ERROR setting up SWS context\n", __func__);
return false;
return ret;
}
sframe = avcodec_alloc_frame();
dframe = avcodec_alloc_frame();
if (!sframe || !dframe) {
AVFrame *sframe = av_frame_alloc();
AVFrame *dframe = av_frame_alloc();
if (sframe && dframe) {
len = av_image_fill_arrays(sframe->data, sframe->linesize, &(src)[0], sfmt, sw, sh, 1);
if(len>-1)
ret = true;
if(ret && (len = av_image_fill_arrays(dframe->data, dframe->linesize, &(dst)[0], AV_PIX_FMT_RGB32, dw, dh, 1)<0))
ret = false;
if(ret && (len = sws_scale(scale, sframe->data, sframe->linesize, 0, sh, dframe->data, dframe->linesize)<0))
ret = false;
else
ret = true;
}else{
lt_info_c("%s: could not alloc sframe (%p) or dframe (%p)\n", __func__, sframe, dframe);
goto out;
ret = false;
}
avpicture_fill((AVPicture *)sframe, &(src[0]), PIX_FMT_RGB32, sw, sh);
avpicture_fill((AVPicture *)dframe, &(dst[0]), PIX_FMT_RGB32, dw, dh);
sws_scale(scale, sframe->data, sframe->linesize, 0, sh, dframe->data, dframe->linesize);
out:
avcodec_free_frame(&sframe);
avcodec_free_frame(&dframe);
sws_freeContext(scale);
if(sframe){
av_frame_free(&sframe);
sframe = NULL;
}
if(dframe){
av_frame_free(&dframe);
dframe = NULL;
}
if(scale){
sws_freeContext(scale);
scale = NULL;
}
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)
{
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);
@@ -581,8 +755,8 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
std::vector<unsigned char> *osd = NULL;
std::vector<unsigned char> s_osd; /* scaled OSD */
int vid_w = 0, vid_h = 0;
int osd_w = glfb->getOSDWidth();
int osd_h = glfb->getOSDHeight();
int osd_w = glfb_priv->getOSDWidth();
int osd_h = glfb_priv->getOSDHeight();
xres = osd_w;
yres = osd_h;
if (get_video) {
@@ -600,24 +774,42 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
xres = vid_w * a.num / a.den;
}
}
if(video.empty()){
get_video=false;
xres = osd_w;
yres = osd_h;
}
if (get_osd)
osd = glfb->getOSDBuffer();
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, xres, yres);
osd = glfb_priv->getOSDBuffer();
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, xres, yres, 1);
data = (unsigned char *)realloc(data, need); /* will be freed by caller */
if (data == NULL) /* out of memory? */
return false;
if (get_video) {
if (vid_w != xres || vid_h != yres) /* scale video into data... */
swscale(&video[0], data, vid_w, vid_h, xres, yres);
else /* get_video and no fancy scaling needed */
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
if (vid_w != xres || vid_h != yres){ /* scale video into data... */
#endif
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres,VDEC_PIXFMT);
if(!ret){
free(data);
return false;
}
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
}else{ /* get_video and no fancy scaling needed */
memcpy(data, &video[0], xres * yres * sizeof(uint32_t));
}
#endif
}
if (get_osd && (osd_w != xres || osd_h != yres)) {
/* rescale osd */
s_osd.resize(need);
swscale(&(*osd)[0], &s_osd[0], osd_w, osd_h, xres, yres);
bool ret = swscale(&(*osd)[0], &s_osd[0], osd_w, osd_h, xres, yres,AV_PIX_FMT_RGB32);
if(!ret){
free(data);
return false;
}
osd = &s_osd;
}
@@ -651,7 +843,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();

View File

@@ -1,220 +0,0 @@
#ifndef _VIDEO_TD_H
#define _VIDEO_TD_H
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include <vector>
#include <linux/dvb/video.h>
#include "../common/cs_types.h"
#include "dmx_lib.h"
extern "C" {
#include <libavutil/rational.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,
VIDEO_FORMAT_VC1,
VIDEO_FORMAT_JPEG,
VIDEO_FORMAT_GIF,
VIDEO_FORMAT_PNG
} 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_AUTO,
VIDEO_STD_1080P50, /* SPARK only */
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;
#define VDEC_MAXBUFS 0x30
class cVideo : public OpenThreads::Thread
{
friend class GLFramebuffer;
friend class cDemux;
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;
int64_t GetPTS(void);
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(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);
/* 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; };
void 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);
SWFramebuffer *getDecBuf(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;
VIDEO_STD v_std;
OpenThreads::Mutex buf_m;
DISPLAY_AR display_aspect;
DISPLAY_AR_MODE display_crop;
int output_h;
int pig_x;
int pig_y;
int pig_w;
int pig_h;
};
#endif

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);
void 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,10 +1,25 @@
/* public header file */
/*
* (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_LIB_H_
#define _AUDIO_LIB_H_
#ifndef __audio_hal__
#define __audio_hal__
#include <stdint.h>
#include "../common/cs_types.h"
#include <cs_types.h>
typedef enum
{
@@ -39,43 +54,21 @@ typedef enum
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;
bool thread_started;
int volume;
int64_t curr_pts;
void openDevice(void);
void closeDevice(void);
int do_mute(bool enable, bool remember);
void setBypassMode(bool disable);
public:
/* construct & destruct */
cAudio(void *, void *, void *);
~cAudio(void);
int64_t getPts() { return curr_pts; }
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); };
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; };
bool getMuteStatus(void) { return muted; };
/* start and stop audio */
int Start(void);
@@ -96,7 +89,10 @@ class cAudio
void SetSpdifDD(bool enable);
void ScheduleMute(bool On);
void EnableAnalogOut(bool enable);
int my_read(uint8_t *buf, int buf_size);
private:
bool muted;
int volume;
void *pdata;
};
#endif

View File

@@ -1,16 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/audio_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/audio_lib.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/audio_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/audio_lib.h"
#else
#include "../generic-pc/audio_lib.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif

View File

@@ -37,7 +37,16 @@ enum CA_MESSAGE_FLAGS {
CA_MESSAGE_HAS_PARAM4_INT = (1 << 10),
CA_MESSAGE_HAS_PARAM4_PTR = (1 << 11),
CA_MESSAGE_HAS_PARAM4_DATA = (1 << 12),
CA_MESSAGE_HAS_PARAM_LONG = (1 << 13),
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 {
@@ -70,7 +79,7 @@ typedef struct CA_MESSAGE {
uint8_t *Data[4];
uint32_t Param[4];
void *Ptr[4];
uint64_t ParamLong;
uint64_t ParamLong[4];
} Msg;
} CA_MESSAGE;
@@ -82,7 +91,7 @@ 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 = CA_SLOT_TYPE_ALL) { (void)SlotType; return true; };
bool SendMessage(const CA_MESSAGE *Msg);
void SetInitMask(enum CA_INIT_MASK InitMask);
int GetCAIDS(CaIdVector & /*Caids*/) { return 0; };

View File

@@ -1 +1 @@
#include "../common/ca.h"
#include "ca.h"

View File

@@ -1,16 +1,67 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/cs_api.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/cs_api.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/cs_api.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/cs_api.h"
#else
#include "../generic-pc/cs_api.h"
/* 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_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
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
inline void cs_api_init()
{
init_td_api();
};
inline void cs_api_exit()
{
shutdown_td_api();
};
#define cs_malloc_uncached malloc
#define cs_free_uncached free
// Callback function helpers
static inline void cs_register_messenger(cs_messenger) { return; };
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_

View File

@@ -1 +1 @@
#include "dmx_td.h"
#include "dmx_hal.h"

96
include/dmx_hal.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* (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 __dmx_hal__
#define __dmx_hal__
#include <cstdlib>
#include <vector>
#include <inttypes.h>
/* at least on td, config.h needs to be included before... */
#ifndef HAVE_TRIPLEDRAGON
#include <linux/dvb/dmx.h>
#else /* TRIPLEDRAGON */
extern "C" {
#include <hardware/xp/xp_osd_user.h>
}
#if defined DMX_FILTER_SIZE
#undef DMX_FILTER_SIZE
#endif
#define DMX_FILTER_SIZE FILTER_LENGTH
#endif /* TRIPLEDRAGON */
#include <cs_types.h>
#define MAX_DMX_UNITS 4
typedef enum
{
DMX_INVALID = 0,
DMX_VIDEO_CHANNEL = 1,
DMX_AUDIO_CHANNEL,
DMX_PES_CHANNEL,
DMX_PSI_CHANNEL,
DMX_PIP_CHANNEL,
DMX_TP_CHANNEL,
DMX_PCR_ONLY_CHANNEL
} DMX_CHANNEL_TYPE;
typedef struct
{
int fd;
unsigned short pid;
} pes_pids;
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);
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;
};
#endif //__dmx_hal__

View File

@@ -1,16 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/dmx_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/dmx_lib.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/dmx_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/dmx_lib.h"
#else
#include "../generic-pc/dmx_lib.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif

View File

@@ -1,10 +1,42 @@
#include <config.h>
#if HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/glfb.h"
#else
#include "../generic-pc/glfb.h"
#endif
#else
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
/*
Copyright 2010 Carsten Juttner <carjay@gmx.net>
Copyright 2012,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 __glfb__
#define __glfb__
#include <OpenThreads/Thread>
#include <vector>
#include <linux/fb.h> /* for screeninfo etc. */
class GLFramebuffer : public OpenThreads::Thread
{
public:
GLFramebuffer(int x, int y);
~GLFramebuffer();
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
void blit();
fb_var_screeninfo getScreenInfo() { return si; }
private:
fb_var_screeninfo si;
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
void run(); /* for OpenThreads::Thread */
void setup();
void blit_osd();
void *pdata; /* not yet used */
};
#endif

View File

@@ -30,11 +30,16 @@ typedef struct hw_caps
int has_YUV_cinch;
int can_shutdown;
int can_cec;
int can_ar_14_9; /* video drivers have 14:9 aspect ratio mode */
int can_ps_14_9; /* video drivers have 14:9 panscan mode */
int force_tuner_2G; /* force DVB-S2 even though driver may not advertise it */
display_type_t display_type;
int display_xres; /* x resolution or chars per line */
int display_yres;
int can_set_display_brightness;
char boxvendor[64];
char boxname[64];
char boxarch[64];
} hw_caps_t;
hw_caps_t *get_hwcaps(void);

View File

@@ -1,8 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/playback_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/playback_lib.h"
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif

View File

@@ -16,8 +16,12 @@ typedef struct {
typedef struct {
int blind;
int answerlen;
char enguiryText[MAX_MMI_TEXT_LEN];
} MMI_ENGUIRY_INFO;
char enquiryText[MAX_MMI_TEXT_LEN];
} MMI_ENQUIRY_INFO;
/* compat */
#define enguiryText enquiryText
#define MMI_ENGUIRY_INFO MMI_ENQUIRY_INFO
#endif // __MMI_H_

View File

@@ -1,3 +1 @@
/* playback_*.cpp uses off_t */
#include <config.h>
#include "playback_td.h"
#include "playback_hal.h"

66
include/playback_hal.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* (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>
/*
* 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 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);
//
cPlayback(int num = 0);
~cPlayback();
private:
PBPrivate *pd;
};
#endif

View File

@@ -1,16 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/playback_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/playback_libeplayer3.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/playback.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/playback.h"
#else
#include "../generic-pc/playback.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif

View File

@@ -1,16 +1,47 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/pwrmngr.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/pwrmngr.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/pwrmngr.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/pwrmngr.h"
#else
#include "../generic-pc/pwrmngr.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_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 __pwrmngr_hal__
#define __pwrmngr_hal__
class cCpuFreqManager
{
public:
cCpuFreqManager(void);
void Up(void);
void Down(void);
void Reset(void);
bool SetCpuFreq(unsigned long CpuFreq);
bool SetDelta(unsigned long Delta);
unsigned long GetCpuFreq(void);
unsigned long GetDelta(void);
};
class cPowerManager
{
public:
cPowerManager(void);
virtual ~cPowerManager();
bool Open(void);
void Close(void);
bool SetStandby(bool Active, bool Passive);
};
#endif

41
include/record_hal.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* (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

View File

@@ -1,16 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/record_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/record_lib.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/record_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/record_lib.h"
#else
#include "../generic-pc/record_lib.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif

1
include/video_cs.h Normal file
View File

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

View File

@@ -1,13 +1,26 @@
#ifndef _VIDEO_TD_H
#define _VIDEO_TD_H
/*
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 <linux/dvb/video.h>
#include "../common/cs_types.h"
#include "dmx_lib.h"
extern "C" {
#include <libavutil/rational.h>
}
#include <cs_types.h>
typedef enum {
ANALOG_SD_RGB_CINCH = 0x00,
@@ -24,11 +37,25 @@ typedef enum {
typedef enum {
VIDEO_FORMAT_MPEG2 = 0,
VIDEO_FORMAT_MPEG4,
VIDEO_FORMAT_MPEG4, /* H264 */
VIDEO_FORMAT_VC1,
VIDEO_FORMAT_JPEG,
VIDEO_FORMAT_GIF,
VIDEO_FORMAT_PNG
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 {
@@ -94,8 +121,9 @@ typedef enum {
VIDEO_STD_1080P30,
VIDEO_STD_1080P24,
VIDEO_STD_1080P25,
VIDEO_STD_1080P50,
VIDEO_STD_1080P60,
VIDEO_STD_AUTO,
VIDEO_STD_1080P50, /* SPARK only */
VIDEO_STD_MAX
} VIDEO_STD;
@@ -116,34 +144,14 @@ typedef enum
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
} VIDEO_CONTROL;
class cDemux;
class cPlayback;
class VDec;
#define VDEC_MAXBUFS 0x30
class cVideo
{
friend class GLFramebuffer;
friend class cPlayback;
friend class cDemux;
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;
int64_t GetPTS(void);
public:
/* constructor & destructor */
cVideo(int mode, void *, void *, unsigned int unit = 0);
@@ -158,7 +166,7 @@ class cVideo
int setAspectRatio(int aspect, int mode);
/* cropping mode */
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
int setCroppingMode(void);
/* get play state */
int getPlayState(void);
@@ -172,6 +180,8 @@ class cVideo
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);
@@ -196,20 +206,8 @@ class cVideo
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:
SWFramebuffer buffers[VDEC_MAXBUFS];
int dec_w, dec_h;
int dec_r;
bool w_h_changed;
bool thread_running;
VIDEO_FORMAT v_format;
VIDEO_STD v_std;
DISPLAY_AR display_aspect;
DISPLAY_AR_MODE display_crop;
int output_h;
int pig_x;
int pig_y;
int pig_w;
int pig_h;
VDec *vdec;
void *pdata;
};
#endif

View File

@@ -1,20 +0,0 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/video_td.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/video_lib.h"
#elif HAVE_AZBOX_HARDWARE
#include "../azbox/video_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../raspi/video_lib.h"
#else
#include "../generic-pc/video_lib.h"
#endif
#else
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
#endif
#if STB_HAL_VIDEO_HAS_GETSCREENIMAGE
#define SCREENSHOT 1
#endif

View File

@@ -1,37 +1,23 @@
AUTOMAKE_OPTIONS = subdir-objects
noinst_LTLIBRARIES = libeplayer3.la
CXXFLAGS = -Wall
AM_CPPFLAGS = -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
AM_CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
AM_CPPFLAGS += -I$(srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_CPPFLAGS = \
-I$(srcdir)/include
libeplayer3_la_SOURCES = \
input.cpp output.cpp manager.cpp player.cpp \
writer/writer.cpp \
writer/pes.cpp \
writer/misc.cpp
libeplayer3_la_SOURCES = \
container/container.c container/container_ffmpeg.c container/text_srt.c \
container/text_ssa.c container/container_ass.c \
manager/audio.c manager/manager.c manager/subtitle.c manager/video.c \
output/output_subtitle.c output/linuxdvb.c output/output.c \
playback/playback.c output/writer/writer.c output/writer/aac.c output/writer/wmv.c \
output/writer/ac3.c output/writer/divx.c output/writer/wma.c output/writer/pes.c \
output/writer/dts.c output/writer/mpeg2.c output/writer/mp3.c output/writer/misc.c \
output/writer/h264.c output/writer/h263.c output/writer/vc1.c output/writer/framebuffer.c \
output/writer/vorbis.c output/writer/flac.c output/writer/pcm.c
# writer/wmv.cpp writer/ac3.cpp writer/divx.cpp
# writer/dts.cpp writer/mpeg2.cpp writer/mp3.cpp
# writer/h264.cpp
# writer/h263.cpp writer/vc1.cpp writer/pcm.cpp writer/aac.cpp
AM_CFLAGS = -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
LIBEPLAYER3_LIBS = libeplayer3.la
# -lpthread -lavformat -lavcodec -lavutil -lswresample -lm
# get rid of many warnings. This is not my project, so fixing them is not
# top priority
AM_CFLAGS += \
-Wno-unused -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable \
-Wno-sign-compare -Wno-missing-field-initializers
# silence ffmpeg deprecation warnings
AM_CPPFLAGS += -Dattribute_deprecated=''
#libeplayer3_la_LIBADD = -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
LIBEPLAYER3_LIBS = libeplayer3.la -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
bin_PROGRAMS = eplayer3 meta
eplayer3_SOURCES = tools/eplayer2.c
eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
meta_SOURCES = tools/meta.c
meta_LDADD = $(LIBEPLAYER3_LIBS)

View File

@@ -1,3 +1,9 @@
This is a revised libeplayer3 version for Neutrino, rewritten in C++, with
various code parts (e.g. subtitle processing, non-working decoders) removed.
--martii
The original libeplayer3 README follows:
/*
* SCOPE:
* -------

View File

@@ -1,125 +0,0 @@
/*
* Main Container Handling.
*
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include <string.h>
#include "common.h"
#define CONTAINER_DEBUG
#ifdef CONTAINER_DEBUG
static short debug_level = 10;
#define container_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define container_printf(level, x...)
#endif
#ifndef CONTAINER_SILENT
#define container_err(x...) do { printf(x); } while (0)
#else
#define container_err(x...)
#endif
static const char FILENAME[] = "container.c";
static void printContainerCapabilities() {
int i, j;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
container_printf(10, "Capabilities: ");
for (i = 0; AvailableContainer[i] != NULL; i++)
for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++)
container_printf(10, "%s ", AvailableContainer[i]->Capabilities[j]);
container_printf(10, "\n");
}
static int selectContainer(Context_t *context, char * extension) {
int i, j;
int ret = -1;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
for (i = 0; AvailableContainer[i] != NULL; i++)
{
for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++)
if (!strcasecmp(AvailableContainer[i]->Capabilities[j], extension)) {
context->container->selectedContainer = AvailableContainer[i];
container_printf(10, "Selected Container: %s\n", context->container->selectedContainer->Name);
ret = 0;
break;
}
if (ret == 0)
break;
}
if (ret != 0) {
container_err("No Container found :-(\n");
}
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t* context = (Context_t*) _context;
int ret = 0;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
switch(command) {
case CONTAINER_ADD: {
ret = selectContainer(context, (char*) argument);
break;
}
case CONTAINER_CAPABILITIES: {
printContainerCapabilities();
break;
}
case CONTAINER_DEL: {
context->container->selectedContainer = NULL;
break;
}
default:
container_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command);
break;
}
return ret;
}
extern Container_t SrtContainer;
extern Container_t SsaContainer;
extern Container_t ASSContainer;
ContainerHandler_t ContainerHandler = {
"Output",
NULL,
&SrtContainer,
&SsaContainer,
&ASSContainer,
Command
};

View File

@@ -1,818 +0,0 @@
/*
* Container handling for subtitles handled by libass
* konfetti 2010; based on code from crow
*
* The subtitle handling as container is not a very proper solution, in
* a proper architecture this should be handled as subcontainer or something
* like that. But we dont want to make more effort as necessary here ;)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/poll.h>
#include <pthread.h>
#include <ass/ass.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define ASS_DEBUG
#ifdef ASS_DEBUG
static const char *FILENAME = "container_ass.c";
static short debug_level = 10;
#define ass_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define ass_printf(level, fmt, x...)
#endif
#ifndef ASS_SILENT
#define ass_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define ass_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_CONTAINER_ASS_NO_ERROR 0
#define cERR_CONTAINER_ASS_ERROR -1
#define ASS_RING_SIZE 5
#define ASS_FONT "/usr/share/fonts/FreeSans.ttf"
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct ass_s {
unsigned char* data;
int len;
unsigned char* extradata;
int extralen;
long long int pts;
float duration;
} ass_t;
typedef struct region_s
{
unsigned int x;
unsigned int y;
unsigned int w;
unsigned int h;
time_t undisplay;
struct region_s* next;
} region_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_mutex_t mutex;
static pthread_t PlayThread;
static int hasPlayThreadStarted = 0;
static unsigned char isContainerRunning = 0;
static ASS_Library *ass_library;
static ASS_Renderer *ass_renderer;
static float ass_font_scale = 0.7;
static float ass_line_spacing = 0.7;
static unsigned int screen_width = 0;
static unsigned int screen_height = 0;
static int shareFramebuffer = 0;
static int framebufferFD = -1;
static unsigned char* destination = NULL;
static int destStride = 0;
static int threeDMode =0;
static ASS_Track* ass_track = NULL;
static region_t* firstRegion = NULL;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
void ass_msg_callback(int level, const char *format, va_list va, void *ctx)
{
int n;
char *str;
va_list dst;
va_copy(dst, va);
n = vsnprintf(NULL, 0, format, va);
if (n > 0 && (str = malloc(n + 1))) {
vsnprintf(str, n + 1, format, dst);
ass_printf(100, "%s\n", str);
free(str);
}
}
static void getMutex(int line) {
ass_printf(150, "%d requesting mutex\n", line);
pthread_mutex_lock(&mutex);
ass_printf(150, "%d received mutex\n", line);
}
static void releaseMutex(int line) {
pthread_mutex_unlock(&mutex);
ass_printf(150, "%d released mutex\n", line);
}
/* ********************************* */
/* Region Undisplay handling */
/* ********************************* */
/* release and undisplay all saved regions
*/
void releaseRegions()
{
region_t* next, *old;
Writer_t* writer;
if (firstRegion == NULL)
return;
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
next = firstRegion;
while (next != NULL)
{
if (writer)
{
WriterFBCallData_t out;
ass_printf(100, "release: w %d h %d x %d y %d\n",
next->w, next->h, next->x, next->y);
out.fd = framebufferFD;
out.data = NULL;
out.Width = next->w;
out.Height = next->h;
out.x = next->x;
out.y = next->y;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + next->x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + next->y;
writer->writeData(&out);
}
}
old = next;
next = next->next;
free(old);
}
firstRegion = NULL;
}
/* check for regions which should be undisplayed.
* we are very tolerant on time here, because
* regions are also released when new regions are
* detected (see ETSI EN 300 743 Chapter Page Composition)
*/
void checkRegions()
{
#define cDeltaTime 2
region_t* next, *old, *prev;
Writer_t* writer;
time_t now = time(NULL);
if (firstRegion == NULL)
return;
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
prev = next = firstRegion;
while (next != NULL)
{
if (now > next->undisplay + cDeltaTime)
{
ass_printf(100, "undisplay: %ld > %ld\n", now, next->undisplay + cDeltaTime);
if (writer)
{
WriterFBCallData_t out;
ass_printf(100, "release: w %d h %d x %d y %d\n",
next->w, next->h, next->x, next->y);
out.fd = framebufferFD;
out.data = NULL;
out.Width = next->w;
out.Height = next->h;
out.x = next->x;
out.y = next->y;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + next->x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + next->y;
writer->writeData(&out);
}
}
old = next;
next = prev->next = next->next;
if (old == firstRegion)
firstRegion = next;
free(old);
} else
{
prev = next;
next = next->next;
}
}
}
/* store a display region for later release */
void storeRegion(unsigned int x, unsigned int y, unsigned int w, unsigned int h, time_t undisplay)
{
region_t* new;
ass_printf(100, "%d %d %d %d %ld\n", x, y, w, h, undisplay);
if (firstRegion == NULL)
{
firstRegion = malloc(sizeof(region_t));
new = firstRegion;
} else
{
new = firstRegion;
while (new->next != NULL)
new = new->next;
new->next = malloc(sizeof(region_t));
new = new->next;
}
new->next = NULL;
new->x = x;
new->y = y;
new->w = w;
new->h = h;
new->undisplay = undisplay;
}
/* **************************** */
/* Worker Thread */
/* **************************** */
static void ASSThread(Context_t *context) {
Writer_t* writer;
ass_printf(10, "\n");
while ( context->playback->isCreationPhase )
{
ass_err("Thread waiting for end of init phase...\n");
usleep(1000);
}
ass_printf(10, "Running!\n");
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
while ( context && context->playback && context->playback->isPlaying ) {
//IF MOVIE IS PAUSED, WAIT
if (context->playback->isPaused) {
ass_printf(20, "paused\n");
usleep(100000);
continue;
}
if (context->playback->isSeeking) {
ass_printf(10, "seeking\n");
usleep(100000);
continue;
}
if ((isContainerRunning) && (ass_track))
{
ASS_Image * img = NULL;
int change = 0;
unsigned long int playPts;
if (context && context->playback)
{
if (context->playback->Command(context, PLAYBACK_PTS, &playPts) < 0)
continue;
}
getMutex(__LINE__);
//FIXME: durch den sleep bleibt die cpu usage zw. 5 und 13%, ohne
// steigt sie bei Verwendung von subtiteln bis auf 95%.
// ich hoffe dadurch gehen keine subtitle verloren, wenn die playPts
// durch den sleep verschlafen wird. Besser w<>re es den n<>chsten
// subtitel zeitpunkt zu bestimmen und solange zu schlafen.
usleep(1000);
if(ass_renderer && ass_track)
img = ass_render_frame(ass_renderer, ass_track, playPts / 90.0, &change);
ass_printf(150, "img %p pts %lu %f\n", img, playPts, playPts / 90.0);
if(img != NULL && ass_renderer && ass_track)
{
/* the spec says, that if a new set of regions is present
* the complete display switches to the new state. So lets
* release the old regions on display.
*/
if (change != 0)
releaseRegions();
while (context && context->playback && context->playback->isPlaying &&
(img) && (change != 0))
{
WriterFBCallData_t out;
time_t now = time(NULL);
time_t undisplay = now + 10;
if (ass_track && ass_track->events)
{
undisplay = now + ass_track->events->Duration / 1000 + 0.5;
}
ass_printf(100, "w %d h %d s %d x %d y %d c %d chg %d now %ld und %ld\n",
img->w, img->h, img->stride,
img->dst_x, img->dst_y, img->color,
change, now, undisplay);
/* api docu said w and h can be zero which
* means image should not be rendered
*/
if ((img->w != 0) && (img->h != 0) && (writer))
{
out.fd = framebufferFD;
out.data = img->bitmap;
out.Width = img->w;
out.Height = img->h;
out.Stride = img->stride;
out.x = img->dst_x;
out.y = img->dst_y;
out.color = img->color;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
storeRegion(img->dst_x, img->dst_y,
img->w, img->h, undisplay);
if (shareFramebuffer)
{
if(context && context->playback && context->playback->isPlaying && writer){
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + img->dst_x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + img->dst_y;
writer->writeData(&out);
}
}
}
else
{
/* application does not want to share framebuffer,
* so there is hopefully installed an output callback
* in the subtitle output!
*/
SubtitleOut_t out;
out.type = eSub_Gfx;
if (ass_track->events)
{
/* fixme: check values */
out.pts = ass_track->events->Start * 90.0;
out.duration = ass_track->events->Duration / 1000.0;
} else
{
out.pts = playPts;
out.duration = 10.0;
}
out.u.gfx.data = img->bitmap;
out.u.gfx.Width = img->w;
out.u.gfx.Height = img->h;
out.u.gfx.x = img->dst_x;
out.u.gfx.y = img->dst_y;
if(context && context->playback && context->playback->isPlaying &&
context->output && context->output->subtitle)
context->output->subtitle->Write(context, &out);
}
}
/* Next image */
img = img->next;
}
}
else
{
/* noop */
}
releaseMutex(__LINE__);
} else
{
usleep(1000);
}
/* cleanup no longer used but not overwritten regions */
checkRegions();
} /* while */
hasPlayThreadStarted = 0;
ass_printf(10, "terminating\n");
}
/* **************************** */
/* Container part for ass */
/* **************************** */
int container_ass_init(Context_t *context)
{
int modefd;
char buf[16];
SubtitleOutputDef_t output;
ass_printf(10, ">\n");
ass_library = ass_library_init();
if (!ass_library) {
ass_err("ass_library_init failed!\n");
return cERR_CONTAINER_ASS_ERROR;
}
if (debug_level >= 100)
ass_set_message_cb(ass_library, ass_msg_callback, NULL);
ass_set_extract_fonts( ass_library, 1 );
ass_set_style_overrides( ass_library, NULL );
ass_renderer = ass_renderer_init(ass_library);
if (!ass_renderer) {
ass_err("ass_renderer_init failed!\n");
if (ass_library)
ass_library_done(ass_library);
ass_library = NULL;
return cERR_CONTAINER_ASS_ERROR;
}
context->output->subtitle->Command(context, OUTPUT_GET_SUBTITLE_OUTPUT, &output);
modefd=open("/proc/stb/video/3d_mode", O_RDWR);
if(modefd > 0){
read(modefd, buf, 15);
buf[15]='\0';
close(modefd);
}else threeDMode = 0;
if(strncmp(buf,"sbs",3)==0)threeDMode = 1;
else if(strncmp(buf,"tab",3)==0)threeDMode = 2;
else threeDMode = 0;
screen_width = output.screen_width;
screen_height = output.screen_height;
shareFramebuffer = output.shareFramebuffer;
framebufferFD = output.framebufferFD;
destination = output.destination;
destStride = output.destStride;
ass_printf(10, "width %d, height %d, share %d, fd %d, 3D %d\n",
screen_width, screen_height, shareFramebuffer, framebufferFD, threeDMode);
if(threeDMode == 0){
ass_set_frame_size(ass_renderer, screen_width, screen_height);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height), (int)(0.03 * screen_height) ,
(int)(0.03 * screen_width ), (int)(0.03 * screen_width ) );
}else if(threeDMode == 1){
ass_set_frame_size(ass_renderer, screen_width/2, screen_height);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height), (int)(0.03 * screen_height) ,
(int)(0.03 * screen_width/2 ), (int)(0.03 * screen_width/2 ) );
}else if(threeDMode == 2){
ass_set_frame_size(ass_renderer, screen_width, screen_height/2);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height/2), (int)(0.03 * screen_height/2) ,
(int)(0.03 * screen_width ), (int)(0.03 * screen_width ) );
}
ass_set_use_margins(ass_renderer, 0 );
ass_set_font_scale(ass_renderer, ass_font_scale);
ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT);
ass_set_line_spacing(ass_renderer, ass_line_spacing);
ass_set_fonts(ass_renderer, ASS_FONT, "Arial", 0, NULL, 1);
if(threeDMode == 0){
ass_set_aspect_ratio( ass_renderer, 1.0, 1.0);
}else if(threeDMode == 1){
ass_set_aspect_ratio( ass_renderer, 0.5, 1.0);
}else if(threeDMode == 2){
ass_set_aspect_ratio( ass_renderer, 1.0, 0.5);
}
isContainerRunning = 1;
return cERR_CONTAINER_ASS_NO_ERROR;
}
int container_ass_process_data(Context_t *context, SubtitleData_t* data)
{
int first_kiss;
ass_printf(20, ">\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
if (ass_track == NULL)
{
first_kiss = 1;
ass_track = ass_new_track(ass_library);
if (ass_track == NULL)
{
ass_err("error creating ass_track\n");
return cERR_CONTAINER_ASS_ERROR;
}
}
if ((data->extradata) && (first_kiss))
{
ass_printf(30,"processing private %d bytes\n",data->extralen);
ass_process_codec_private(ass_track, (char*) data->extradata, data->extralen);
ass_printf(30,"processing private done\n");
}
if (data->data)
{
ass_printf(30,"processing data %d bytes\n",data->len);
ass_process_data(ass_track, (char*) data->data, data->len);
ass_printf(30,"processing data done\n");
}
return cERR_CONTAINER_ASS_NO_ERROR;
}
static int container_ass_stop(Context_t *context) {
int ret = cERR_CONTAINER_ASS_NO_ERROR;
int wait_time = 20;
Writer_t* writer;
ass_printf(10, "\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 ) {
ass_printf(10, "Waiting for ass thread to terminate itself, will try another %d times\n", wait_time);
usleep(100000);
}
if (wait_time == 0) {
ass_err( "Timeout waiting for thread!\n");
ret = cERR_CONTAINER_ASS_ERROR;
}
getMutex(__LINE__);
releaseRegions();
if (ass_track)
ass_free_track(ass_track);
ass_track = NULL;
if (ass_renderer)
ass_renderer_done(ass_renderer);
ass_renderer = NULL;
if (ass_library)
ass_library_done(ass_library);
ass_library = NULL;
isContainerRunning = 0;
hasPlayThreadStarted = 0;
writer = getDefaultFramebufferWriter();
if (writer != NULL)
{
writer->reset();
}
releaseMutex(__LINE__);
ass_printf(10, "ret %d\n", ret);
return ret;
}
static int container_ass_switch_subtitle(Context_t* context, int* arg)
{
int error;
int ret = cERR_CONTAINER_ASS_NO_ERROR;
pthread_attr_t attr;
ass_printf(10, "\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
if ( context && context->playback && context->playback->isPlaying ) {
ass_printf(10, "is Playing\n");
}
else {
ass_printf(10, "is NOT Playing\n");
}
if (hasPlayThreadStarted == 0) {
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if((error = pthread_create(&PlayThread, &attr, (void *)&ASSThread, context)) != 0) {
ass_printf(10, "Error creating thread, error:%d:%s\n", error,strerror(error));
hasPlayThreadStarted = 0;
ret = cERR_CONTAINER_ASS_ERROR;
}
else {
ass_printf(10, "Created thread\n");
hasPlayThreadStarted = 1;
}
}
else {
ass_printf(10, "A thread already exists!\n");
ret = cERR_CONTAINER_ASS_ERROR;
}
getMutex(__LINE__);
releaseRegions();
/* free the track so extradata will be written next time
* process_data is called.
*/
if (ass_track)
ass_free_track(ass_track);
ass_track = NULL;
releaseMutex(__LINE__);
ass_printf(10, "exiting with value %d\n", ret);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument)
{
Context_t *context = (Context_t*) _context;
int ret = cERR_CONTAINER_ASS_NO_ERROR;
ass_printf(50, "Command %d\n", command);
switch(command)
{
case CONTAINER_INIT: {
ret = container_ass_init(context);
break;
}
case CONTAINER_STOP: {
ret = container_ass_stop(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = container_ass_switch_subtitle(context, (int*) argument);
break;
}
case CONTAINER_DATA: {
SubtitleData_t* data = (SubtitleData_t*) argument;
ret = container_ass_process_data(context, data);
break;
}
default:
ass_err("ContainerCmd %d not supported!\n", command);
ret = cERR_CONTAINER_ASS_ERROR;
break;
}
ass_printf(50, "exiting with value %d\n", ret);
return ret;
}
static char *ASS_Capabilities[] = {"ass", NULL };
Container_t ASSContainer = {
"ASS",
&Command,
ASS_Capabilities
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,490 +0,0 @@
/*
* subtitle handling for srt files.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SRT_DEBUG
#ifdef SRT_DEBUG
static short debug_level = 10;
#define srt_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define srt_printf(level, fmt, x...)
#endif
#ifndef SRT_SILENT
#define srt_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define srt_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_SRT_NO_ERROR 0
#define cERR_SRT_ERROR -1
#define TRACKWRAP 20
#define MAXLINELENGTH 80
static const char FILENAME[] = "text_srt.c";
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct {
char * File;
int Id;
} SrtTrack_t;
static pthread_t thread_sub;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static SrtTrack_t * Tracks;
static int TrackCount = 0;
static int CurrentTrack = -1; //no as default.
FILE * fsub = NULL;
static int hasThreadStarted = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
void data_to_manager(Context_t *context, char* Text, unsigned long long int Pts, double Duration)
{
srt_printf(20, "--> Text= \"%s\"\n", Text);
if( context &&
context->playback &&
context->playback->isPlaying){
int sl = strlen(Text)-1;
while(sl && (Text[sl]=='\n' || Text[sl]=='\r')) Text[sl--]='\0'; /*Delete last \n or \r */
unsigned char* line = text_to_ass(Text, Pts, Duration);
srt_printf(50,"Sub text is %s\n",Text);
srt_printf(50,"Sub line is %s\n",line);
SubtitleData_t data;
data.data = line;
data.len = strlen((char*)line);
data.extradata = DEFAULT_ASS_HEAD;
data.extralen = strlen(DEFAULT_ASS_HEAD);
data.pts = Pts*90;
data.duration = Duration;
context->container->assContainer->Command(context, CONTAINER_DATA, &data);
free(line);
}
srt_printf(20, "<-- Text= \"%s\"\n", Text);
}
/* ***************************** */
/* Worker Thread */
/* ***************************** */
static void* SrtSubtitleThread(void *data) {
int pos = 0;
char Data[MAXLINELENGTH];
unsigned long long int Pts = 0;
double Duration = 0;
char * Text = NULL;
Context_t *context = (Context_t*) data;
srt_printf(10, "\n");
while(context && context->playback && context->playback->isPlaying && fsub && fgets(Data, MAXLINELENGTH, fsub)) {
srt_printf(20, "pos=%d\n", pos);
if(pos == 0)
{
if(Data[0] == '\n' || Data[0] == '\0' || Data[0] == 13 /* ^M */)
continue; /* Empty line not allowed here */
pos++;
} else if(pos == 1)
{
int ret, horIni, minIni, secIni, milIni, horFim, minFim, secFim, milFim;
ret = sscanf(Data, "%d:%d:%d,%d --> %d:%d:%d,%d", &horIni, &minIni, &secIni, &milIni, &horFim, &minFim, &secFim, &milFim);
if (ret!=8) continue; /* Data is not in correct format */
Pts = (horIni*3600 + minIni*60 + secIni)*1000 + milIni;
Duration = ((horFim*3600 + minFim*60 + secFim) * 1000 + milFim - Pts) / 1000.0;
pos++;
} else if(pos == 2) {
srt_printf(20, "Data[0] = %d \'%c\'\n", Data[0], Data[0]);
if(Data[0] == '\n' || Data[0] == '\0' || Data[0] == 13 /* ^M */) {
if(Text == NULL)
Text = strdup(" \n"); /* better to display at least one character */
/*Hellmaster 1024 since we have waited, we have to check if we are still paying */
data_to_manager(context, Text, Pts, Duration);
free(Text);
Text = NULL;
pos = 0;
continue;
}
if(!Text) {
Text = strdup(Data);
} else {
int length = strlen(Text) /* \0 -> \n */ + strlen(Data) + 2 /* \0 */;
char * tmpText = strdup(Text);
free(Text);
Text = (char*)malloc(length);
strcpy(Text, tmpText);
strcat(Text, Data);
free(tmpText);
}
}
} /* while */
hasThreadStarted = 0;
if(Text) {
data_to_manager(context, Text, Pts, Duration);
free(Text);
Text = NULL;
}
srt_printf(0, "thread has ended\n");
return NULL;
}
/* ***************************** */
/* Functions */
/* ***************************** */
static void SrtManagerAdd(Context_t *context, SrtTrack_t track) {
srt_printf(10, "%s %d\n",track.File, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(SrtTrack_t) * TRACKWRAP);
}
if (TrackCount < TRACKWRAP) {
Tracks[TrackCount].File = strdup(track.File);
Tracks[TrackCount].Id = track.Id;
TrackCount++;
}
}
static char ** SrtManagerList(Context_t *context) {
char ** tracklist = NULL;
srt_printf(10, "\n");
if (Tracks != NULL) {
char help[256];
int i = 0, j = 0;
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
sprintf(help, "%d", Tracks[i].Id);
tracklist[j] = strdup(help);
tracklist[j+1] = strdup(Tracks[i].File);
}
tracklist[j] = NULL;
}
return tracklist;
}
static void SrtManagerDel(Context_t * context) {
int i = 0;
srt_printf(10, "\n");
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
if (Tracks[i].File != NULL)
free(Tracks[i].File);
Tracks[i].File = NULL;
}
free(Tracks);
Tracks = NULL;
}
TrackCount = 0;
CurrentTrack = -1;
}
static int SrtGetSubtitle(Context_t *context, char * Filename) {
struct dirent *dirzeiger;
DIR * dir;
int i = TEXTSRTOFFSET;
char * copyFilename = NULL;
char * FilenameExtension = NULL;
char * FilenameFolder = NULL;
char * FilenameShort = NULL;
srt_printf(10, "\n");
if (Filename == NULL)
{
srt_err("Filename NULL\n");
return cERR_SRT_ERROR;
}
srt_printf(10, "file: %s\n", Filename);
copyFilename = strdup(Filename);
if (copyFilename == NULL)
{
srt_err("copyFilename NULL\n");
return cERR_SRT_ERROR;
}
FilenameFolder = dirname(copyFilename);
srt_printf(10, "folder: %s\n", FilenameFolder);
getExtension(copyFilename, &FilenameExtension);
if (FilenameExtension == NULL)
{
srt_err("FilenameExtension NULL\n");
free(copyFilename);
return cERR_SRT_ERROR;
}
srt_printf(10, "ext: %s\n", FilenameExtension);
FilenameShort = basename(copyFilename);
/* cut extension */
FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = '\0';
srt_printf(10, "basename: %s\n", FilenameShort);
srt_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, FilenameShort, FilenameExtension);
if((dir = opendir(FilenameFolder)) != NULL) {
while((dirzeiger = readdir(dir)) != NULL) {
char subtitleFilename[PATH_MAX];
char *subtitleExtension = NULL;
srt_printf(20, "%s\n",(*dirzeiger).d_name);
strcpy(subtitleFilename, (*dirzeiger).d_name);
// Extension of Relativ Subtitle File Name
getExtension(subtitleFilename, &subtitleExtension);
if (subtitleExtension == NULL)
continue;
if (strcmp(subtitleExtension, "srt") != 0)
{
free(subtitleExtension);
continue;
}
/* cut extension */
subtitleFilename[strlen(subtitleFilename) - strlen(subtitleExtension) - 1] = '\0';
srt_printf(10, "%s %s\n", FilenameShort, subtitleFilename);
if (strncmp(FilenameShort, subtitleFilename,strlen(FilenameShort)) == 0)
{
char absSubtitleFileName[PATH_MAX];
/* found something of interest, so now make an absolut path name */
sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, subtitleFilename, subtitleExtension);
srt_printf(10, "SRT: %s [%s]\n", subtitleExtension, subtitleFilename);
srt_printf(10, "\t->%s\n", absSubtitleFileName);
SrtTrack_t SrtSubtitle = {
absSubtitleFileName,
i,
};
SrtManagerAdd(context, SrtSubtitle);
Track_t Subtitle = {
subtitleExtension,
"S_TEXT/SRT",
i++,
};
context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle);
}
free(subtitleExtension);
} /* while */
closedir(dir);
} /* if dir */
free(FilenameExtension);
free(copyFilename);
srt_printf(10, "<\n");
return cERR_SRT_NO_ERROR;
}
static int SrtOpenSubtitle(Context_t *context, int trackid) {
srt_printf(10, "\n");
if(trackid < TEXTSRTOFFSET || (trackid % TEXTSRTOFFSET) >= TrackCount) {
srt_err("trackid not for us\n");
return cERR_SRT_ERROR;
}
trackid %= TEXTSRTOFFSET;
srt_printf(10, "%s\n", Tracks[trackid].File);
fsub = fopen(Tracks[trackid].File, "rb");
srt_printf(10, "%s\n", fsub ? "fsub!=NULL" : "fsub==NULL");
if(!fsub)
{
srt_err("cannot open file %s\n", Tracks[trackid].File);
return cERR_SRT_ERROR;
}
return cERR_SRT_NO_ERROR;
}
static int SrtCloseSubtitle(Context_t *context) {
srt_printf(10, "\n");
if(fsub)
fclose(fsub);
/* this closes the thread! */
fsub = NULL;
hasThreadStarted = 0;
return cERR_SRT_NO_ERROR;
}
static int SrtSwitchSubtitle(Context_t *context, int* arg) {
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "arg:%d\n", *arg);
ret = SrtCloseSubtitle(context);
if (( (ret |= SrtOpenSubtitle(context, *arg)) == cERR_SRT_NO_ERROR) && (!hasThreadStarted))
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread_sub, &attr, &SrtSubtitleThread, context);
hasThreadStarted = 1;
}
return ret;
}
static int SrtDel(Context_t *context) {
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "\n");
ret = SrtCloseSubtitle(context);
SrtManagerDel(context);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "\n");
switch(command) {
case CONTAINER_INIT: {
char * filename = (char *)argument;
ret = SrtGetSubtitle(context, filename);
break;
}
case CONTAINER_DEL: {
ret = SrtDel(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = SrtSwitchSubtitle(context, (int*) argument);
break;
}
default:
srt_err("ConatinerCmd not supported! %d\n", command);
break;
}
srt_printf(10, "ret = %d\n", ret);
return 0;
}
static char *SrtCapabilities[] = { "srt", NULL };
Container_t SrtContainer = {
"SRT",
&Command,
SrtCapabilities
};

View File

@@ -1,492 +0,0 @@
/*
* subtitle handling for ssa files.
*
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SSA_DEBUG
#ifdef SSA_DEBUG
static short debug_level = 10;
#define ssa_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define ssa_printf(level, fmt, x...)
#endif
#ifndef SSA_SILENT
#define ssa_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define ssa_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_SSA_NO_ERROR 0
#define cERR_SSA_ERROR -1
#define TRACKWRAP 20
#define MAXLINELENGTH 1000
//Buffer size used in getLine function. Do not set to value less than 1 !!!
#define SSA_BUFFER_SIZE 14
static const char FILENAME[] = "text_ssa.c";
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct {
char * File;
int Id;
} SsaTrack_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_t thread_sub;
static SsaTrack_t * Tracks;
static int TrackCount = 0;
FILE * fssa = NULL;
static int hasThreadStarted = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
char *SSAgetLine()
{
char *strAux = NULL, *strInput;
char c[SSA_BUFFER_SIZE], ch;
int k, tam, tamAux;
k = tamAux = 0;
if(SSA_BUFFER_SIZE>0)
{
strInput = (char*)malloc(1*sizeof(char));
strInput[0]='\0';
while(tamAux!=1)
{
if((ch = fgetc(fssa))!=EOF)
{
ungetc(ch , fssa);
fgets(c, SSA_BUFFER_SIZE, fssa);
strAux = (char*)strchr(c,'\n');
tam = strlen(c);
if(strAux != NULL)
{
tamAux = strlen(strAux);
tam--;
}
k = k + tam;
strInput = (char*)realloc(strInput, (k+1)*sizeof(char));
if(k!=tam)
strncat(strInput, c, tam);
else
strncpy(strInput, c, tam);
strInput[k] = '\0';
}
else {
tamAux = 1;
fclose(fssa);
fssa = NULL;
}
}
}
return strInput;
}
/* ***************************** */
/* Worker Thread */
/* ***************************** */
static void* SsaSubtitleThread(void *data) {
Context_t *context = (Context_t*) data;
char * head =malloc(sizeof(char)*1);
ssa_printf(10, "\n");
head[0]='\0';
while ( context && context->playback && context->playback->isPlaying && fssa ) {
char *line = NULL;
do
{
line = SSAgetLine();
if(strncmp(line,"Dialogue: ",10)) {
int head_len = strlen(head);
int line_len = strlen(line);
head = realloc(head, line_len + head_len +2);
memcpy(head + head_len, line, sizeof(char)*line_len+1);
head[head_len + line_len] = '\n';
head[head_len + line_len + 1] = '\0';
}
} while (strncmp(line,"Dialogue: ",10)!=0 && fssa);
/*Hellmaster 1024 since we have waited, we have to check if we are still paying */
if( context &&
context->playback &&
context->playback->isPlaying) {
SubtitleData_t data;
data.data = (unsigned char*) line;
data.len = strlen(line);
data.extradata = (unsigned char*) head;
data.extralen = strlen(head);
data.pts = 0;
data.duration = 0.0;
context->container->assContainer->Command(context, CONTAINER_DATA, &data);
}
free(line);
line = NULL;
continue;
}
hasThreadStarted = 0;
if(head) {
free(head);
head = NULL;
}
ssa_printf(0, "thread has ended\n");
return NULL;
}
/* ***************************** */
/* Functions */
/* ***************************** */
static void SsaManagerAdd(Context_t *context, SsaTrack_t track) {
ssa_printf(10, "%s %d\n", track.File, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(SsaTrack_t) * TRACKWRAP);
}
if (TrackCount < TRACKWRAP) {
Tracks[TrackCount].File = strdup(track.File);
Tracks[TrackCount].Id = track.Id;
TrackCount++;
}
}
static char ** SsaManagerList(Context_t *context) {
char ** tracklist = NULL;
ssa_printf(10, "\n");
if (Tracks != NULL) {
char help[256];
int i = 0, j = 0;
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
sprintf(help, "%d", Tracks[i].Id);
tracklist[j] = strdup(help);
tracklist[j+1] = strdup(Tracks[i].File);
}
tracklist[j] = NULL;
}
return tracklist;
}
static void SsaManagerDel(Context_t * context) {
int i = 0;
ssa_printf(10, "\n");
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
if (Tracks[i].File != NULL)
free(Tracks[i].File);
Tracks[i].File = NULL;
}
free(Tracks);
Tracks = NULL;
}
TrackCount = 0;
}
static int SsaGetSubtitle(Context_t *context, char * Filename) {
struct dirent *dirzeiger;
DIR * dir;
int i = TEXTSSAOFFSET;
char * copyFilename = NULL;
char * FilenameExtension = NULL;
char * FilenameFolder = NULL;
char * FilenameShort = NULL;
ssa_printf(10, "\n");
if (Filename == NULL)
{
ssa_err("Filename NULL\n");
return cERR_SSA_ERROR;
}
ssa_printf(10, "file: %s\n", Filename);
copyFilename = strdup(Filename);
if (copyFilename == NULL)
{
ssa_err("copyFilename NULL\n");
return cERR_SSA_ERROR;
}
FilenameFolder = dirname(copyFilename);
ssa_printf(10, "folder: %s\n", FilenameFolder);
getExtension(copyFilename, &FilenameExtension);
if (FilenameExtension == NULL)
{
ssa_err("FilenameExtension NULL\n");
free(copyFilename);
return cERR_SSA_ERROR;
}
ssa_printf(10, "ext: %s\n", FilenameExtension);
FilenameShort = basename(copyFilename);
/* cut extension */
FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = '\0';
ssa_printf(10, "basename: %s\n", FilenameShort);
ssa_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, FilenameShort, FilenameExtension);
if((dir = opendir(FilenameFolder)) != NULL) {
while((dirzeiger = readdir(dir)) != NULL) {
char subtitleFilename[PATH_MAX];
char *subtitleExtension = NULL;
ssa_printf(20, "%s\n",(*dirzeiger).d_name);
strcpy(subtitleFilename, (*dirzeiger).d_name);
// Extension of Relativ Subtitle File Name
getExtension(subtitleFilename, &subtitleExtension);
if (subtitleExtension == NULL)
continue;
if ( strcmp(subtitleExtension, "ssa") != 0 && strcmp(subtitleExtension, "ass") != 0 )
{
free(subtitleExtension);
continue;
}
/* cut extension */
subtitleFilename[strlen(subtitleFilename) - strlen(subtitleExtension) - 1] = '\0';
ssa_printf(10, "%s %s\n", FilenameShort, subtitleFilename);
if (strncmp(FilenameShort, subtitleFilename,strlen(FilenameShort)) == 0)
{
char absSubtitleFileName[PATH_MAX];
/* found something of interest, so now make an absolut path name */
sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, subtitleFilename, subtitleExtension);
ssa_printf(10, "SSA: %s [%s]\n", subtitleExtension, subtitleFilename);
ssa_printf(10, "\t->%s\n", absSubtitleFileName);
SsaTrack_t SsaSubtitle = {
absSubtitleFileName,
i,
};
SsaManagerAdd(context, SsaSubtitle);
Track_t Subtitle = {
subtitleExtension,
"S_TEXT/SSA",
i++,
};
context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle);
}
free(subtitleExtension);
} /* while */
closedir(dir);
} /* if dir */
free(FilenameExtension);
free(copyFilename);
ssa_printf(10, "<\n");
return cERR_SSA_NO_ERROR;
}
static int SsaOpenSubtitle(Context_t *context, int trackid) {
ssa_printf(10, "\n");
if(trackid < TEXTSSAOFFSET || (trackid % TEXTSSAOFFSET) >= TrackCount ) {
ssa_err("trackid not for us\n");
return cERR_SSA_ERROR;
}
trackid %= TEXTSSAOFFSET;
ssa_printf(10, "%s\n", Tracks[trackid].File);
fssa = fopen(Tracks[trackid].File, "rb");
ssa_printf(10, "%s\n", fssa ? "fssa!=NULL" : "fssa==NULL");
if (!fssa)
{
ssa_err("cannot open file %s\n", Tracks[trackid].File);
return cERR_SSA_ERROR;
}
return cERR_SSA_NO_ERROR;
}
static int SsaCloseSubtitle(Context_t *context) {
ssa_printf(10, "\n");
if(fssa)
fclose(fssa);
/* this closes the thread! */
fssa = NULL;
hasThreadStarted = 0;
return cERR_SSA_NO_ERROR;
}
static int SsaSwitchSubtitle(Context_t *context, int* arg) {
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
ret = SsaCloseSubtitle(context);
if (((ret |= SsaOpenSubtitle(context, *arg)) == cERR_SSA_NO_ERROR) && (!hasThreadStarted))
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread_sub, &attr, &SsaSubtitleThread, context);
hasThreadStarted = 1;
}
return ret;
}
static int SsaDel(Context_t *context) {
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
ret = SsaCloseSubtitle(context);
SsaManagerDel(context);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
switch(command) {
case CONTAINER_INIT: {
char * filename = (char *)argument;
ret = SsaGetSubtitle(context, filename);
break;
}
case CONTAINER_DEL: {
ret = SsaDel(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = SsaSwitchSubtitle(context, (int*) argument);
break;
}
default:
ssa_err("ConatinerCmd not supported! %d\n", command);
break;
}
ssa_printf(10, "ret = %d\n", ret);
return 0;
}
static char *SsaCapabilities[] = { "ssa", NULL };
Container_t SsaContainer = {
"SSA",
&Command,
SsaCapabilities
};

View File

@@ -1,57 +0,0 @@
/*
* aac helper
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef acc_123
#define acc_123
#define AAC_HEADER_LENGTH 7
static inline int aac_get_sample_rate_index (uint32_t sample_rate)
{
if (96000 <= sample_rate)
return 0;
else if (88200 <= sample_rate)
return 1;
else if (64000 <= sample_rate)
return 2;
else if (48000 <= sample_rate)
return 3;
else if (44100 <= sample_rate)
return 4;
else if (32000 <= sample_rate)
return 5;
else if (24000 <= sample_rate)
return 6;
else if (22050 <= sample_rate)
return 7;
else if (16000 <= sample_rate)
return 8;
else if (12000 <= sample_rate)
return 9;
else if (11025 <= sample_rate)
return 10;
else if (8000 <= sample_rate)
return 11;
else if (7350 <= sample_rate)
return 12;
else
return 13;
}
#endif

View File

@@ -1,17 +0,0 @@
#ifndef COMMON_H_
#define COMMON_H_
#include "container.h"
#include "output.h"
#include "manager.h"
#include "playback.h"
#include <pthread.h>
typedef struct Context_s {
PlaybackHandler_t * playback;
ContainerHandler_t * container;
OutputHandler_t * output;
ManagerHandler_t * manager;
} Context_t;
#endif

View File

@@ -1,48 +0,0 @@
#ifndef CONTAINER_H_
#define CONTAINER_H_
#include <stdio.h>
typedef enum {
CONTAINER_INIT,
CONTAINER_ADD,
CONTAINER_CAPABILITIES,
CONTAINER_PLAY,
CONTAINER_STOP,
CONTAINER_SEEK,
CONTAINER_LENGTH,
CONTAINER_DEL,
CONTAINER_SWITCH_AUDIO,
CONTAINER_SWITCH_SUBTITLE,
CONTAINER_INFO,
CONTAINER_STATUS,
CONTAINER_LAST_PTS,
CONTAINER_DATA
} ContainerCmd_t;
typedef struct Container_s {
char * Name;
int (* Command) (/*Context_t*/void *, ContainerCmd_t, void *);
char ** Capabilities;
} Container_t;
extern Container_t FFMPEGContainer;
static Container_t * AvailableContainer[] = {
&FFMPEGContainer,
NULL
};
typedef struct ContainerHandler_s {
char * Name;
Container_t * selectedContainer;
Container_t * textSrtContainer;
Container_t * textSsaContainer;
Container_t * assContainer;
int (* Command) (/*Context_t*/void *, ContainerCmd_t, void *);
} ContainerHandler_t;
#endif

View File

@@ -1,21 +0,0 @@
#ifndef debug_123
#define debug_123
#include <stdio.h>
#include <errno.h>
static inline void Hexdump(unsigned char *Data, int length)
{
int k;
for (k = 0; k < length; k++)
{
printf("%02x ", Data[k]);
if (((k+1)&31)==0)
printf("\n");
}
printf("\n");
}
#endif

View File

@@ -1,45 +0,0 @@
#ifndef _ffmpeg_metadata_123
#define _ffmpeg_metadata_123
/* these file contains a list of metadata tags which can be used by applications
* to stream specific information. it maps the tags to ffmpeg specific tags.
*
* fixme: if we add other container for some resons later (maybe some other libs
* support better demuxing or something like this), then we should think on a
* more generic mechanism!
*/
/* metatdata map list:
*/
char* metadata_map[] =
{
/* our tags ffmpeg tag / id3v2 */
"Title", "TIT2",
"Title", "TT2",
"Artist", "TPE1",
"Artist", "TP1",
"AlbumArtist", "TPE2",
"AlbumArtist", "TP2",
"Album", "TALB",
"Album", "TAL",
"Year", "TDRL", /* fixme */
"Year", "TDRC", /* fixme */
"Comment", "unknown",
"Track", "TRCK",
"Track", "TRK",
"Copyright", "TCOP",
"Composer", "TCOM",
"Genre", "TCON",
"Genre", "TCO",
"EncodedBy", "TENC",
"EncodedBy", "TEN",
"Language", "TLAN",
"Performer", "TPE3",
"Performer", "TP3",
"Publisher", "TPUB",
"Encoder", "TSSE",
"Disc", "TPOS",
NULL
};
#endif

View File

@@ -0,0 +1,93 @@
/*
* input class
*
* Copyright (C) 2014 martii
*
* 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.
*/
#ifndef __INPUT_H__
#define __INPUT_H__
#include <stdint.h>
#include <string>
#include <vector>
#include <map>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
class Player;
class Track;
class Input
{
friend class Player;
friend class WriterPCM; // needs calcPts()
friend int interrupt_cb(void *arg);
private:
OpenThreads::Mutex mutex;
Track *videoTrack;
Track *audioTrack;
Track *subtitleTrack;
Track *teletextTrack;
int hasPlayThreadStarted;
int64_t seek_avts_abs;
int64_t seek_avts_rel;
bool isContainerRunning;
bool abortPlayback;
Player *player;
AVFormatContext *avfc;
uint64_t readCount;
int64_t calcPts(AVStream * stream, int64_t pts);
public:
Input();
~Input();
#if 0
bool ReadSubtitle(const char *filename, const char *format, int pid);
bool ReadSubtitles(const char *filename);
#endif
bool Init(const char *filename);
bool UpdateTracks();
bool Play();
bool Stop();
bool Seek(int64_t sec, bool absolute);
bool GetDuration(int64_t &duration);
bool SwitchAudio(Track *track);
bool SwitchSubtitle(Track *track);
bool SwitchTeletext(Track *track);
bool SwitchVideo(Track *track);
bool GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
bool GetReadCount(uint64_t &readcount);
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
};
#endif

View File

@@ -1,78 +1,100 @@
#ifndef MANAGER_H_
#define MANAGER_H_
/*
* manager class
*
* Copyright (C) 2014 martii
*
* 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.
*/
#ifndef __MANAGER_H__
#define __MANAGER_H__
#include <stdio.h>
#include <stdint.h>
typedef enum {
MANAGER_ADD,
MANAGER_LIST,
MANAGER_GET,
MANAGER_GETNAME,
MANAGER_SET,
MANAGER_GETENCODING,
MANAGER_DEL,
MANAGER_GET_TRACK,
} ManagerCmd_t;
#include <string>
#include <vector>
#include <map>
typedef enum {
eTypeES,
eTypePES
} eTrackTypeEplayer;
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
typedef struct Track_s {
char * Name;
char * Encoding;
int Id;
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
/* new field for ffmpeg - add at the end so no problem
* can occur with not changed srt saa container
*/
char* language;
class Player;
/* length of track */
long long int duration;
unsigned int frame_rate;
unsigned int TimeScale;
int version;
long long int pts;
struct Track
{
std::string title;
int pid;
AVStream *stream;
bool inactive;
bool hidden; // not part of currently selected program
bool is_static;
int ac3flags;
AVBitStreamFilterContext *bsfc;
int type, mag, page; // for teletext
Track() : pid(-1), stream(NULL), inactive(false), hidden(false), is_static(false), ac3flags(0), bsfc(NULL) {}
};
/* for later use: */
eTrackTypeEplayer type;
int width;
int height;
struct Program
{
int id;
std::string title;
std::vector<AVStream *> streams;
};
/* stream from ffmpeg */
void * stream;
/* codec extra data (header or some other stuff) */
void * extraData;
int extraSize;
class Manager
{
friend class Player;
uint8_t* aacbuf;
unsigned int aacbuflen;
int have_aacheader;
private:
Player *player;
OpenThreads::Mutex mutex;
std::map<int,Track*> videoTracks, audioTracks, subtitleTracks, teletextTracks;
std::map<int,Program> Programs;
void addTrack(std::map<int,Track*> &tracks, Track &track);
Track *getTrack(std::map<int,Track*> &tracks, int pid);
std::vector<Track> getTracks(std::map<int,Track*> &tracks);
public:
void addVideoTrack(Track &track);
void addAudioTrack(Track &track);
void addSubtitleTrack(Track &track);
void addTeletextTrack(Track &track);
void addProgram(Program &program);
/* If player2 or the elf do not support decoding of audio codec set this.
* AVCodec is than used for softdecoding and stream will be injected as PCM */
int inject_as_pcm;
int inject_raw_pcm;
} Track_t;
std::vector<Track> getVideoTracks();
std::vector<Track> getAudioTracks();
std::vector<Track> getSubtitleTracks();
std::vector<Track> getTeletextTracks();
std::vector<Program> getPrograms();
bool selectProgram(const int id);
typedef struct Manager_s {
char * Name;
int (* Command) (/*Context_t*/void *, ManagerCmd_t, void *);
char ** Capabilities;
Track *getVideoTrack(int pid);
Track *getAudioTrack(int pid);
Track *getSubtitleTrack(int pid);
Track *getTeletextTrack(int pid);
} Manager_t;
typedef struct ManagerHandler_s {
char * Name;
Manager_t * audio;
Manager_t * video;
Manager_t * subtitle;
} ManagerHandler_t;
void freeTrack(Track_t* track);
void copyTrack(Track_t* to, Track_t* from);
bool initTrackUpdate();
void clearTracks();
~Manager();
};
#endif

View File

@@ -1,136 +1,20 @@
#ifndef misc_123
#define misc_123
#include <dirent.h>
/* some useful things needed by many files ... */
/* ***************************** */
/* Types */
/* ***************************** */
#include <stdint.h>
typedef struct BitPacker_s
#define INVALID_PTS_VALUE 0x200000000ll
struct BitPacker_t
{
unsigned char* Ptr; /* write pointer */
unsigned int BitBuffer; /* bitreader shifter */
int Remaining; /* number of remaining in the shifter */
} BitPacker_t;
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define INVALID_PTS_VALUE 0x200000000ull
/*#define BIG_READS*/
#if defined (BIG_READS)
#define BLOCK_COUNT 8
#else
#define BLOCK_COUNT 1
#endif
#define TP_PACKET_SIZE 188
#define BD_TP_PACKET_SIZE 192
#define NUMBER_PACKETS (199*BLOCK_COUNT)
#define BUFFER_SIZE (TP_PACKET_SIZE*NUMBER_PACKETS)
#define PADDING_LENGTH (1024*BLOCK_COUNT)
/* subtitle hacks ->for file subtitles */
#define TEXTSRTOFFSET 100
#define TEXTSSAOFFSET 200
/* ***************************** */
/* Prototypes */
/* ***************************** */
uint8_t *Ptr; /* write pointer */
unsigned int BitBuffer; /* bitreader shifter */
int Remaining; /* number of remaining in the shifter */
};
void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length);
void FlushBits(BitPacker_t * ld);
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static inline void getExtension(char * FILENAMEname, char ** extension) {
int i = 0;
int stringlength;
if (extension == NULL)
return;
*extension = NULL;
if (FILENAMEname == NULL)
return;
stringlength = (int) strlen(FILENAMEname);
for (i = 0; stringlength - i > 0; i++) {
if (FILENAMEname[stringlength - i - 1] == '.') {
*extension = strdup(FILENAMEname+(stringlength - i));
break;
}
}
}
static inline void getUPNPExtension(char * FILENAMEname, char ** extension) {
char* str;
if (extension == NULL)
return;
*extension = NULL;
if (FILENAMEname == NULL)
return;
str = strstr(FILENAMEname, "ext=");
if (str != NULL)
{
*extension = strdup(str + strlen("ext=") + 1);
return;
}
*extension = NULL;
}
/* the function returns the base name */
static inline char * basename(char * name)
{
int i = 0;
int pos = 0;
while(name[i] != 0)
{
if(name[i] == '/')
pos = i;
i++;
}
if(name[pos] == '/')
pos++;
return name + pos;
}
/* the function returns the directry name */
static inline char * dirname(char * name)
{
static char path[100];
int i = 0;
int pos = 0;
while((name[i] != 0) && (i < sizeof(path)))
{
if(name[i] == '/')
pos = i;
path[i] = name[i];
i++;
}
path[i] = 0;
path[pos] = 0;
return path;
}
#endif

View File

@@ -1,79 +1,80 @@
#ifndef OUTPUT_H_
#define OUTPUT_H_
/*
* output class
*
* Copyright (C) 2014 martii
*
* 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.
*/
#include <stdio.h>
#ifndef __OUTPUT_H__
#define __OUTPUT_H__
typedef enum {
OUTPUT_INIT,
OUTPUT_ADD,
OUTPUT_DEL,
OUTPUT_CAPABILITIES,
OUTPUT_PLAY,
OUTPUT_STOP,
OUTPUT_PAUSE,
OUTPUT_OPEN,
OUTPUT_CLOSE,
OUTPUT_FLUSH,
OUTPUT_CONTINUE,
OUTPUT_FASTFORWARD,
OUTPUT_AVSYNC,
OUTPUT_CLEAR,
OUTPUT_PTS,
OUTPUT_SWITCH,
OUTPUT_SLOWMOTION,
OUTPUT_AUDIOMUTE,
OUTPUT_REVERSE,
OUTPUT_DISCONTINUITY_REVERSE,
OUTPUT_GET_FRAME_COUNT,
/* fixme: e2 */
OUTPUT_SUBTITLE_REGISTER_FUNCTION = 222,
OUTPUT_SUBTITLE_REGISTER_BUFFER = 223,
OUTPUT_GET_SUBTITLE_OUTPUT,
OUTPUT_SET_SUBTITLE_OUTPUT
} OutputCmd_t;
#include <stdint.h>
#include <string>
#include <vector>
#include <map>
typedef struct
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
#include "writer.h"
class Player;
class Output
{
unsigned char* data;
unsigned int len;
friend class Player;
unsigned char* extradata;
unsigned int extralen;
unsigned long long int pts;
float frameRate;
unsigned int timeScale;
unsigned int width;
unsigned int height;
char* type;
} AudioVideoOut_t;
typedef struct Output_s {
char * Name;
int (* Command) (/*Context_t*/void *, OutputCmd_t, void *);
int (* Write) (/*Context_t*/void *, void* privateData);
char ** Capabilities;
} Output_t;
extern Output_t LinuxDvbOutput;
extern Output_t SubtitleOutput;
static Output_t * AvailableOutput[] = {
&LinuxDvbOutput,
&SubtitleOutput,
NULL
private:
int videofd;
int audiofd;
Writer *videoWriter, *audioWriter;
OpenThreads::Mutex audioMutex, videoMutex;
AVStream *audioStream, *videoStream;
Player *player;
public:
Output();
~Output();
bool Open();
bool Close();
bool Play();
bool Stop();
bool Pause();
bool Continue();
bool Mute(bool);
bool Flush();
bool FastForward(int speed);
bool SlowMotion(int speed);
bool AVSync(bool);
bool Clear();
bool ClearAudio();
bool ClearVideo();
bool GetPts(int64_t &pts);
bool GetFrameCount(int64_t &framecount);
bool SwitchAudio(AVStream *stream);
bool SwitchVideo(AVStream *stream);
bool Write(AVStream *stream, AVPacket *packet, int64_t Pts);
};
typedef struct OutputHandler_s {
char * Name;
Output_t * audio;
Output_t * video;
Output_t * subtitle;
int (* Command) (/*Context_t*/void *, OutputCmd_t, void *);
} OutputHandler_t;
#endif

View File

@@ -1,33 +1,34 @@
#ifndef pes_123
#define pes_123
#define PES_MAX_HEADER_SIZE 64
#define PES_PRIVATE_DATA_FLAG 0x80
#define PES_PRIVATE_DATA_LENGTH 8
#define PES_LENGTH_BYTE_0 5
#define PES_LENGTH_BYTE_1 4
#define PES_FLAGS_BYTE 7
#define PES_EXTENSION_DATA_PRESENT 0x01
#define PES_HEADER_DATA_LENGTH_BYTE 8
#define PES_MIN_HEADER_SIZE 9
#define PES_START_CODE_RESERVED_4 0xfd
#define PES_VERSION_FAKE_START_CODE 0x31
#include <stdint.h>
#define PES_MAX_HEADER_SIZE 64
#define PES_PRIVATE_DATA_FLAG 0x80
#define PES_PRIVATE_DATA_LENGTH 8
#define PES_LENGTH_BYTE_0 5
#define PES_LENGTH_BYTE_1 4
#define PES_FLAGS_BYTE 7
#define PES_EXTENSION_DATA_PRESENT 0x01
#define PES_HEADER_DATA_LENGTH_BYTE 8
#define PES_START_CODE_RESERVED_4 0xfd
#define PES_VERSION_FAKE_START_CODE 0x31
#define MAX_PES_PACKET_SIZE 65400
#define MAX_PES_PACKET_SIZE 65535
/* start codes */
#define PCM_PES_START_CODE 0xbd
#define PRIVATE_STREAM_1_PES_START_CODE 0xbd
#define PCM_PES_START_CODE 0xbd
#define PRIVATE_STREAM_1_PES_START_CODE 0xbd
#define H263_VIDEO_PES_START_CODE 0xfe
#define H264_VIDEO_PES_START_CODE 0xe2
#define MPEG_VIDEO_PES_START_CODE 0xe0
#define MPEG_AUDIO_PES_START_CODE 0xc0
#define VC1_VIDEO_PES_START_CODE 0xfd
#define AAC_AUDIO_PES_START_CODE 0xcf
#define H264_VIDEO_PES_START_CODE 0xe2
#define MPEG_VIDEO_PES_START_CODE 0xe0
#define MPEG_AUDIO_PES_START_CODE 0xc0
#define VC1_VIDEO_PES_START_CODE 0xfd
#define AAC_AUDIO_PES_START_CODE 0xcf
int InsertPesHeader (unsigned char *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code);
int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size);
int InsertPesHeader(uint8_t *data, int size, uint8_t stream_id, int64_t pts, int pic_start_code);
int InsertVideoPrivateDataHeader(uint8_t *data, int payload_size);
#endif

View File

@@ -1,37 +0,0 @@
#ifndef PLAYBACK_H_
#define PLAYBACK_H_
#include <sys/types.h>
typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT} PlaybackCmd_t;
typedef struct PlaybackHandler_s {
char * Name;
int fd;
unsigned char isFile;
unsigned char isHttp;
unsigned char isUPNP;
unsigned char isPlaying;
unsigned char isPaused;
unsigned char isForwarding;
unsigned char isSeeking;
unsigned char isCreationPhase;
float BackWard;
int SlowMotion;
int Speed;
int AVSync;
unsigned char isVideo;
unsigned char isAudio;
unsigned char isSubtitle;
int (* Command) (/*Context_t*/void *, PlaybackCmd_t, void *);
char * uri;
off_t size;
unsigned char noprobe; /* hack: only minimal probing in av_find_stream_info */
} PlaybackHandler_t;
#endif

View File

@@ -0,0 +1,127 @@
/*
* player class
*
* Copyright (C) 2014 martii
*
* 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.
*/
#ifndef __PLAYER_H__
#define __PLAYER_H__
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
#include <pthread.h>
#include <stdint.h>
#include <string>
#include <vector>
#include <map>
#include "input.h"
#include "output.h"
#include "manager.h"
struct Chapter
{
std::string title;
int64_t start;
int64_t end;
};
class Player {
friend class Input;
friend class Output;
friend class Manager;
friend class cPlayback;
friend class WriterPCM;
friend int interrupt_cb(void *arg);
private:
Input input;
Output output;
Manager manager;
OpenThreads::Mutex chapterMutex;
std::vector<Chapter> chapters;
pthread_t playThread;
bool abortRequested;
bool isHttp;
bool isPaused;
bool isSlowMotion;
bool hasThreadStarted;
bool isForwarding;
bool isBackWard;
bool isPlaying;
int Speed;
uint64_t readCount;
std::string url;
bool noprobe; /* hack: only minimal probing in av_find_stream_info */
void SetChapters(std::vector<Chapter> &Chapters);
static void* playthread(void*);
public:
bool SwitchAudio(int pid);
bool SwitchVideo(int pid);
bool SwitchTeletext(int pid);
bool SwitchSubtitle(int pid);
int GetAudioPid();
int GetVideoPid();
int GetSubtitlePid();
int GetTeletextPid();
bool GetPts(int64_t &pts);
bool GetFrameCount(int64_t &framecount);
bool GetDuration(int64_t &duration);
bool GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
bool SlowMotion(int repeats);
bool FastBackward(int speed);
bool FastForward(int speed);
bool Open(const char *Url, bool noprobe = false);
bool Close();
bool Play();
bool Pause();
bool Continue();
bool Stop();
bool Seek(int64_t pos, bool absolute);
void RequestAbort();
bool GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
AVFormatContext *GetAVFormatContext() { return input.GetAVFormatContext(); }
void ReleaseAVFormatContext() { input.ReleaseAVFormatContext(); }
bool GetPrograms(std::vector<std::string> &keys, std::vector<std::string> &values);
bool SelectProgram(int key);
bool SelectProgram(std::string &key);
Player();
};
#endif

View File

@@ -1,324 +0,0 @@
/*
* stm_ioctls.h
*
* Copyright (C) STMicroelectronics Limited 2005. All rights reserved.
*
* Extensions to the LinuxDVB API (v3) implemented by the Havana implemenation.
*/
#ifndef H_STM_IOCTLS
#define H_STM_IOCTLS
/*
* Whenever a sequence of values is extended (define or enum) always add the new values
* So that old values are unchange to maintain binary compatibility.
*/
#define DVB_SPEED_NORMAL_PLAY 1000
#define DVB_SPEED_STOPPED 0
#define DVB_SPEED_REVERSE_STOPPED 0x80000000
#define DVB_FRAME_RATE_MULTIPLIER 1000
#define VIDEO_FULL_SCREEN (VIDEO_CENTER_CUT_OUT+1)
#define DMX_FILTER_BY_PRIORITY_LOW 0x00010000 /* These flags tell the transport pes filter whether to filter */
#define DMX_FILTER_BY_PRIORITY_HIGH 0x00020000 /* using the ts priority bit and, if so, whether to filter on */
#define DMX_FILTER_BY_PRIORITY_MASK 0x00030000 /* bit set or bit clear */
/*
* Extra events
*/
#define VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY 5 /*(VIDEO_EVENT_VSYNC+1)*/
#define VIDEO_EVENT_FRAME_DECODED_LATE (VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY+1)
#define VIDEO_EVENT_DATA_DELIVERED_LATE (VIDEO_EVENT_FRAME_DECODED_LATE+1)
#define VIDEO_EVENT_STREAM_UNPLAYABLE (VIDEO_EVENT_DATA_DELIVERED_LATE+1)
#define VIDEO_EVENT_TRICK_MODE_CHANGE (VIDEO_EVENT_STREAM_UNPLAYABLE+1)
#define VIDEO_EVENT_VSYNC_OFFSET_MEASURED (VIDEO_EVENT_TRICK_MODE_CHANGE+1)
#define VIDEO_EVENT_FATAL_ERROR (VIDEO_EVENT_VSYNC_OFFSET_MEASURED+1)
#define VIDEO_EVENT_OUTPUT_SIZE_CHANGED (VIDEO_EVENT_FATAL_ERROR+1)
#define VIDEO_EVENT_FATAL_HARDWARE_FAILURE (VIDEO_EVENT_OUTPUT_SIZE_CHANGED+1)
/*
* List of possible container types - used to select demux.. If stream_source is VIDEO_SOURCE_DEMUX
* then default is TRANSPORT, if stream_source is VIDEO_SOURCE_MEMORY then default is PES
*/
typedef enum {
STREAM_TYPE_NONE, /* Deprecated */
STREAM_TYPE_TRANSPORT,/* Use latest PTI driver so it can be Deprecated */
STREAM_TYPE_PES,
STREAM_TYPE_ES, /* Deprecated */
STREAM_TYPE_PROGRAM, /* Deprecated */
STREAM_TYPE_SYSTEM, /* Deprecated */
STREAM_TYPE_SPU, /* Deprecated */
STREAM_TYPE_NAVI, /* Deprecated */
STREAM_TYPE_CSS, /* Deprecated */
STREAM_TYPE_AVI, /* Deprecated */
STREAM_TYPE_MP3, /* Deprecated */
STREAM_TYPE_H264, /* Deprecated */
STREAM_TYPE_ASF, /* Needs work so it can be deprecated */
STREAM_TYPE_MP4, /* Deprecated */
STREAM_TYPE_RAW /* Deprecated */
} stream_type_t;
/*
* List of possible video encodings - used to select frame parser and codec.
*/
typedef enum {
VIDEO_ENCODING_AUTO,
VIDEO_ENCODING_MPEG1,
VIDEO_ENCODING_MPEG2,
VIDEO_ENCODING_MJPEG,
VIDEO_ENCODING_DIVX3,
VIDEO_ENCODING_DIVX4,
VIDEO_ENCODING_DIVX5,
VIDEO_ENCODING_MPEG4P2,
VIDEO_ENCODING_H264,
VIDEO_ENCODING_WMV,
VIDEO_ENCODING_VC1,
VIDEO_ENCODING_RAW,
VIDEO_ENCODING_H263,
VIDEO_ENCODING_FLV1,
VIDEO_ENCODING_VP6,
VIDEO_ENCODING_RMV,
VIDEO_ENCODING_DIVXHD,
VIDEO_ENCODING_AVS,
VIDEO_ENCODING_VP3,
VIDEO_ENCODING_THEORA,
VIDEO_ENCODING_COMPOCAP,
VIDEO_ENCODING_NONE,
VIDEO_ENCODING_PRIVATE
} video_encoding_t;
/*
* List of possible audio encodings - used to select frame parser and codec.
*/
typedef enum {
AUDIO_ENCODING_AUTO,
AUDIO_ENCODING_PCM,
AUDIO_ENCODING_LPCM,
AUDIO_ENCODING_MPEG1,
AUDIO_ENCODING_MPEG2,
AUDIO_ENCODING_MP3,
AUDIO_ENCODING_AC3,
AUDIO_ENCODING_DTS,
AUDIO_ENCODING_AAC,
AUDIO_ENCODING_WMA,
AUDIO_ENCODING_RAW,
AUDIO_ENCODING_LPCMA,
AUDIO_ENCODING_LPCMH,
AUDIO_ENCODING_LPCMB,
AUDIO_ENCODING_SPDIF, /*<! Data coming through SPDIF link :: compressed or PCM data */
AUDIO_ENCODING_DTS_LBR,
AUDIO_ENCODING_MLP,
AUDIO_ENCODING_RMA,
AUDIO_ENCODING_AVS,
AUDIO_ENCODING_VORBIS,
AUDIO_ENCODING_NONE,
AUDIO_ENCODING_PRIVATE
} audio_encoding_t;
/*
* List of possible sources for SP/DIF output.
*/
typedef enum audio_spdif_source {
AUDIO_SPDIF_SOURCE_PP, /*<! normal decoder output */
AUDIO_SPDIF_SOURCE_DEC, /*<! decoder output w/o post-proc */
AUDIO_SPDIF_SOURCE_ES, /*<! raw elementary stream data */
} audio_spdif_source_t;
typedef struct {
int x;
int y;
int width;
int height;
} video_window_t;
typedef enum
{
DVB_DISCONTINUITY_SKIP = 0x01,
DVB_DISCONTINUITY_CONTINUOUS_REVERSE = 0x02,
DVB_DISCONTINUITY_SURPLUS_DATA = 0x04
} dvb_discontinuity_t;
/*
* audio discontinuity
*/
typedef enum {
AUDIO_DISCONTINUITY_SKIP = DVB_DISCONTINUITY_SKIP,
AUDIO_DISCONTINUITY_CONTINUOUS_REVERSE = DVB_DISCONTINUITY_CONTINUOUS_REVERSE,
AUDIO_DISCONTINUITY_SURPLUS_DATA = DVB_DISCONTINUITY_SURPLUS_DATA,
} audio_discontinuity_t;
/*
* video discontinuity
*/
typedef enum {
VIDEO_DISCONTINUITY_SKIP = DVB_DISCONTINUITY_SKIP,
VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE = DVB_DISCONTINUITY_CONTINUOUS_REVERSE,
VIDEO_DISCONTINUITY_SURPLUS_DATA = DVB_DISCONTINUITY_SURPLUS_DATA,
} video_discontinuity_t;
#define DVB_TIME_NOT_BOUNDED 0xfedcba9876543210ULL
typedef struct dvb_play_interval_s {
unsigned long long start;
unsigned long long end;
}dvb_play_interval_t;
typedef dvb_play_interval_t video_play_interval_t;
typedef dvb_play_interval_t audio_play_interval_t;
typedef struct dvb_play_time_s {
unsigned long long system_time;
unsigned long long presentation_time;
unsigned long long pts;
}dvb_play_time_t;
typedef dvb_play_time_t video_play_time_t;
typedef dvb_play_time_t audio_play_time_t;
typedef struct dvb_play_info_s {
unsigned long long system_time;
unsigned long long presentation_time;
unsigned long long pts;
unsigned long long frame_count;
}dvb_play_info_t;
typedef dvb_play_info_t video_play_info_t;
typedef dvb_play_info_t audio_play_info_t;
typedef enum {
#define DVB_OPTION_VALUE_DISABLE 0
#define DVB_OPTION_VALUE_ENABLE 1
DVB_OPTION_TRICK_MODE_AUDIO = 0,
DVB_OPTION_PLAY_24FPS_VIDEO_AT_25FPS = 1,
#define DVB_OPTION_VALUE_VIDEO_CLOCK_MASTER 0
#define DVB_OPTION_VALUE_AUDIO_CLOCK_MASTER 1
#define DVB_OPTION_VALUE_SYSTEM_CLOCK_MASTER 2
DVB_OPTION_MASTER_CLOCK = 2,
DVB_OPTION_EXTERNAL_TIME_MAPPING = 3,
DVB_OPTION_EXTERNAL_TIME_MAPPING_VSYNC_LOCKED = 31,
DVB_OPTION_AV_SYNC = 4,
DVB_OPTION_DISPLAY_FIRST_FRAME_EARLY = 5,
DVB_OPTION_VIDEO_BLANK = 6,
DVB_OPTION_STREAM_ONLY_KEY_FRAMES = 7,
DVB_OPTION_STREAM_SINGLE_GROUP_BETWEEN_DISCONTINUITIES = 8,
DVB_OPTION_CLAMP_PLAYBACK_INTERVAL_ON_PLAYBACK_DIRECTION_CHANGE = 9,
#define DVB_OPTION_VALUE_PLAYOUT 0
#define DVB_OPTION_VALUE_DISCARD 1
DVB_OPTION_PLAYOUT_ON_TERMINATE = 10,
DVB_OPTION_PLAYOUT_ON_SWITCH = 11,
DVB_OPTION_PLAYOUT_ON_DRAIN = 12,
DVB_OPTION_VIDEO_ASPECT_RATIO = 13,
DVB_OPTION_VIDEO_DISPLAY_FORMAT = 14,
#define DVB_OPTION_VALUE_TRICK_MODE_AUTO 0
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_ALL 1
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_ALL_DEGRADE_NON_REFERENCE_FRAMES 2
#define DVB_OPTION_VALUE_TRICK_MODE_START_DISCARDING_NON_REFERENCE_FRAMES 3
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_REFERENCE_FRAMES_DEGRADE_NON_KEY_FRAMES 4
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_KEY_FRAMES 5
#define DVB_OPTION_VALUE_TRICK_MODE_DISCONTINUOUS_KEY_FRAMES 6
DVB_OPTION_TRICK_MODE_DOMAIN = 15,
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_NEVER 0
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_ALWAYS 1
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_AFTER_SYNCHRONIZE 2
DVB_OPTION_DISCARD_LATE_FRAMES = 16,
DVB_OPTION_VIDEO_START_IMMEDIATE = 17,
DVB_OPTION_REBASE_ON_DATA_DELIVERY_LATE = 18,
DVB_OPTION_REBASE_ON_FRAME_DECODE_LATE = 19,
DVB_OPTION_LOWER_CODEC_DECODE_LIMITS_ON_FRAME_DECODE_LATE = 20,
DVB_OPTION_H264_ALLOW_NON_IDR_RESYNCHRONIZATION = 21,
DVB_OPTION_MPEG2_IGNORE_PROGESSIVE_FRAME_FLAG = 22,
DVB_OPTION_AUDIO_SPDIF_SOURCE = 23,
DVB_OPTION_H264_ALLOW_BAD_PREPROCESSED_FRAMES = 24,
DVB_OPTION_CLOCK_RATE_ADJUSTMENT_LIMIT_2_TO_THE_N_PARTS_PER_MILLION = 25, /* Value = N */
DVB_OPTION_LIMIT_INPUT_INJECT_AHEAD = 26,
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_MPEG2 0
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_ATSC 1
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_DVB 2
DVB_OPTION_MPEG2_APPLICATION_TYPE = 27,
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_DISABLED 0
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_HALF 1
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_QUARTER 2
DVB_OPTION_DECIMATE_DECODER_OUTPUT = 28,
DVB_OPTION_PTS_FORWARD_JUMP_DETECTION_THRESHOLD = 29,
DVB_OPTION_H264_TREAT_DUPLICATE_DPB_AS_NON_REFERENCE_FRAME_FIRST = 30,
DVB_OPTION_PIXEL_ASPECT_RATIO_CORRECTION = 32,
DVB_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING = 33,
DVB_OPTION_PTS_SYMMETRIC_JUMP_DETECTION = 34,
DVB_OPTION_ALLOW_FRAME_DISCARD_AT_NORMAL_SPEED = 35,
/* OPTION_MAX must always be one greater than largest option - currently DVB_OPTION_ALLOW_FRAME_DISCARD_AT_NORMAL_SPEED */
DVB_OPTION_MAX = 35
} dvb_option_t;
// Legacy typo correction
#define DVP_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING DVB_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING
typedef dvb_option_t video_option_t;
/* Decoder commands */
#define VIDEO_CMD_PLAY (0)
#define VIDEO_CMD_STOP (1)
#define VIDEO_CMD_FREEZE (2)
#define VIDEO_CMD_CONTINUE (3)
#define VIDEO_CMD_SET_OPTION (4)
#define VIDEO_CMD_GET_OPTION (5)
/* Flags for VIDEO_CMD_FREEZE */
#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
/* Flags for VIDEO_CMD_STOP */
#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
/* Play input formats: */
/* The decoder has no special format requirements */
#define VIDEO_PLAY_FMT_NONE (0)
/* The decoder requires full GOPs */
#define VIDEO_PLAY_FMT_GOP (1)
/* ST specific video ioctls */
#define VIDEO_SET_ENCODING _IO('o', 81)
#define VIDEO_FLUSH _IO('o', 82)
#define VIDEO_SET_SPEED _IO('o', 83)
#define VIDEO_DISCONTINUITY _IO('o', 84)
#define VIDEO_STEP _IO('o', 85)
#define VIDEO_SET_PLAY_INTERVAL _IOW('o', 86, video_play_interval_t)
#define VIDEO_SET_SYNC_GROUP _IO('o', 87)
#define VIDEO_GET_PLAY_TIME _IOR('o', 88, video_play_time_t)
#define VIDEO_GET_PLAY_INFO _IOR('o', 89, video_play_info_t)
/* ST specific audio ioctls */
#define AUDIO_SET_ENCODING _IO('o', 70)
#define AUDIO_FLUSH _IO('o', 71)
#define AUDIO_SET_SPDIF_SOURCE _IO('o', 72)
#define AUDIO_SET_SPEED _IO('o', 73)
#define AUDIO_DISCONTINUITY _IO('o', 74)
#define AUDIO_SET_PLAY_INTERVAL _IOW('o', 75, audio_play_interval_t)
#define AUDIO_SET_SYNC_GROUP _IO('o', 76)
#define AUDIO_GET_PLAY_TIME _IOR('o', 77, audio_play_time_t)
#define AUDIO_GET_PLAY_INFO _IOR('o', 78, audio_play_info_t)
#endif /* H_DVB_STM_H */

View File

@@ -1,126 +0,0 @@
#ifndef _subtitle_123
#define _subtitle_123
/*
* Interface File for subtitle handling (container input and output).
*
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define DEFAULT_ASS_HEAD "[Script Info]\n\
Original Script: (c) 2008\n\
ScriptType: v4.00\n\
Synch Point: Side 1 0m00s\n\
Collisions: Normal\n\
Timer: 100.0000\n\n\
[V4 Styles]\n\
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\n\
Style: Default,Arial,26,16777215,0,16777215,0,0,0,2,2,2,2,20,20,10,0\n\n\
[Events]\n\
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\n\n"
static inline unsigned char* text_to_ass(char *text, long long int pts, double duration)
{
char buf[1024];
int x,pos=0;
for(x=0;x<strlen(text);x++){
if(text[x]=='\n'){
buf[pos++]='\\';
buf[pos++]='N';
}else if(text[x]!='\r')buf[pos++]=text[x];
}
buf[pos++]='\0';
int len = 80 + strlen(buf);
long long int end_pts = pts + (duration * 1000.0);
char* line = (char*)malloc( sizeof(char) * len );
int sc = pts / 10;
int ec = end_pts / 10;
int sh, sm, ss, eh, em, es;
sh = sc/360000; sc -= 360000*sh;
sm = sc/ 6000; sc -= 6000*sm;
ss = sc/ 100; sc -= 100*ss;
eh = ec/360000; ec -= 360000*eh;
em = ec/ 6000; ec -= 6000*em;
es = ec/ 100; ec -= 100*es;
snprintf(line,len,"Dialogue: Marked=0,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,Default,NTP,0000,0000,0000,!Effect,%s\n",
sh, sm, ss, sc, eh, em, es, ec, buf);
return (unsigned char*)line;
}
typedef enum
{
eSub_Gfx,
eSub_Txt
} SubType_t;
typedef struct
{
unsigned char* data;
int len;
} SubText_t;
typedef struct
{
unsigned char* data;
unsigned int Width;
unsigned int Height;
unsigned int Stride;
unsigned int x;
unsigned int y;
unsigned int color;
} SubGfx_t;
typedef struct
{
SubType_t type;
long long int pts;
float duration;
union
{
SubText_t text;
SubGfx_t gfx;
} u;
} SubtitleOut_t;
typedef struct
{
unsigned char* data;
int len;
unsigned char* extradata;
int extralen;
long long int pts;
float duration;
} SubtitleData_t;
typedef struct
{
unsigned char* destination;
unsigned int screen_width;
unsigned int screen_height;
unsigned int destStride;
int shareFramebuffer;
int framebufferFD;
} SubtitleOutputDef_t;
#endif

View File

@@ -1,110 +1,57 @@
#ifndef WRITER_H_
#define WRITER_H_
/*
* writer class headers
*
* Copyright (C) 2014 martii
*
* 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.
*/
#ifndef __WRITER_H__
#define __WRITER_H__
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
typedef enum { eNone, eAudio, eVideo, eGfx} eWriterType_t;
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
typedef struct {
int fd;
unsigned char* data;
unsigned int len;
unsigned long long int Pts;
unsigned char* private_data;
unsigned int private_size;
unsigned int FrameRate;
unsigned int FrameScale;
unsigned int Width;
unsigned int Height;
unsigned char Version;
} WriterAVCallData_t;
#include <linux/dvb/stm_ioctls.h>
typedef struct {
unsigned char* data;
unsigned int Width;
unsigned int Height;
unsigned int Stride;
unsigned int color;
#define AV_CODEC_ID_INJECTPCM AV_CODEC_ID_PCM_S16LE
unsigned int x; /* dst x ->given by ass */
unsigned int y; /* dst y ->given by ass */
class Player;
/* destination values if we use a shared framebuffer */
int fd;
unsigned int Screen_Width;
unsigned int Screen_Height;
unsigned char* destination;
unsigned int destStride;
} WriterFBCallData_t;
class Writer
{
protected:
int fd;
Player *player;
public:
static void Register(Writer *w, enum AVCodecID id, video_encoding_t encoding);
static void Register(Writer *w, enum AVCodecID id, audio_encoding_t encoding);
static video_encoding_t GetVideoEncoding(enum AVCodecID id);
static audio_encoding_t GetAudioEncoding(enum AVCodecID id);
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type);
typedef struct WriterCaps_s {
char* name;
eWriterType_t type;
char* textEncoding;
/* fixme: revise if this is an enum! */
int dvbEncoding;
} WriterCaps_t;
typedef struct Writer_s {
int (* reset) ();
int (* writeData) (void*);
int (* writeReverseData) (void*);
WriterCaps_t *caps;
} Writer_t;
extern Writer_t WriterAudioIPCM;
extern Writer_t WriterAudioPCM;
extern Writer_t WriterAudioMP3;
extern Writer_t WriterAudioMPEGL3;
extern Writer_t WriterAudioAC3;
extern Writer_t WriterAudioAAC;
extern Writer_t WriterAudioDTS;
extern Writer_t WriterAudioWMA;
extern Writer_t WriterAudioFLAC;
extern Writer_t WriterAudioVORBIS;
extern Writer_t WriterVideoMPEG2;
extern Writer_t WriterVideoMPEGH264;
extern Writer_t WriterVideoH264;
extern Writer_t WriterVideoWMV;
extern Writer_t WriterVideoDIVX;
extern Writer_t WriterVideoFOURCC;
extern Writer_t WriterVideoMSCOMP;
extern Writer_t WriterVideoH263;
extern Writer_t WriterVideoFLV;
extern Writer_t WriterVideoVC1;
extern Writer_t WriterFramebuffer;
static Writer_t * AvailableWriter[] = {
&WriterAudioIPCM,
&WriterAudioPCM,
&WriterAudioMP3,
&WriterAudioMPEGL3,
&WriterAudioAC3,
&WriterAudioAAC,
&WriterAudioDTS,
&WriterAudioWMA,
&WriterAudioFLAC,
&WriterAudioVORBIS,
&WriterVideoMPEG2,
&WriterVideoMPEGH264,
&WriterVideoH264,
&WriterVideoDIVX,
&WriterVideoFOURCC,
&WriterVideoMSCOMP,
&WriterVideoWMV,
&WriterVideoH263,
&WriterVideoFLV,
&WriterVideoVC1,
&WriterFramebuffer,
NULL
virtual void Init(int _fd, AVStream * /*stream*/, Player *_player ) { fd = _fd; player = _player; }
virtual bool Write(AVPacket *packet, int64_t pts);
};
Writer_t* getWriter(char* encoding);
Writer_t* getDefaultVideoWriter();
Writer_t* getDefaultAudioWriter();
Writer_t* getDefaultFramebufferWriter();
#endif

765
libeplayer3/input.cpp Normal file
View File

@@ -0,0 +1,765 @@
/*
* input class
*
* based on libeplayer3 container_ffmpeg.c, konfetti 2010; based on code from crow
*
* Copyright (C) 2014 martii
*
* 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.
*/
#define ENABLE_LOGGING 0
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "player.h"
#include "misc.h"
static const char *FILENAME = "eplayer/input.cpp";
#define averror(_err,_fun) ({ \
if (_err < 0) { \
char _error[512]; \
av_strerror(_err, _error, sizeof(_error)); \
fprintf(stderr, "%s %d: %s: %d (%s)\n", FILENAME, __LINE__, #_fun, _err, _error); \
} \
_err; \
})
Input::Input()
{
videoTrack = NULL;
audioTrack = NULL;
subtitleTrack = NULL;
teletextTrack = NULL;
hasPlayThreadStarted = 0;
seek_avts_abs = INT64_MIN;
seek_avts_rel = 0;
abortPlayback = false;
}
Input::~Input()
{
}
int64_t Input::calcPts(AVStream * stream, int64_t pts)
{
if (pts == AV_NOPTS_VALUE)
return INVALID_PTS_VALUE;
pts = av_rescale(90000ll * stream->time_base.num, pts, stream->time_base.den);
if (avfc->start_time != AV_NOPTS_VALUE)
pts -= av_rescale(90000ll, avfc->start_time, AV_TIME_BASE);
if (pts < 0)
return INVALID_PTS_VALUE;
return pts;
}
#if 0
// from neutrino-mp/lib/libdvbsubtitle/dvbsub.cpp
extern void dvbsub_write(AVSubtitle *, int64_t);
extern void dvbsub_ass_write(AVCodecContext *c, AVSubtitle *sub, int pid);
extern void dvbsub_ass_clear(void);
// from neutrino-mp/lib/lib/libtuxtxt/tuxtxt_common.h
extern void teletext_write(int pid, uint8_t *data, int size);
#endif
static std::string lastlog_message;
static unsigned int lastlog_repeats;
static void log_callback(void *ptr __attribute__ ((unused)), int lvl __attribute__ ((unused)), const char *format, va_list ap)
{
char m[1024];
if (sizeof(m) - 1 > (unsigned int) vsnprintf(m, sizeof(m), format, ap)) {
if (lastlog_message.compare(m) || lastlog_repeats > 999) {
if (lastlog_repeats)
fprintf(stderr, "last message repeated %u times\n", lastlog_repeats);
lastlog_message = m;
lastlog_repeats = 0;
fprintf(stderr, "%s", m);
} else
lastlog_repeats++;
}
}
static void logprintf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
log_callback(NULL, 0, format, ap);
va_end(ap);
}
bool Input::Play()
{
hasPlayThreadStarted = 1;
int64_t showtime = 0;
bool restart_audio_resampling = false;
bool bof = false;
// HACK: Dropping all video frames until the first audio frame was seen will keep player2 from stuttering.
// Oddly, this seems to be necessary for network streaming only ...
bool audioSeen = !audioTrack || !player->isHttp;
int reinit_audio = 0;
while (player->isPlaying && !player->abortRequested) {
//IF MOVIE IS PAUSED, WAIT
if (player->isPaused) {
// fprintf(stderr, "paused\n");
usleep(100000);
continue;
}
int seek_target_flag = 0;
int64_t seek_target = INT64_MIN; // in AV_TIME_BASE units
if (seek_avts_rel) {
if (avfc->iformat->flags & AVFMT_TS_DISCONT) {
if (avfc->bit_rate) {
seek_target_flag = AVSEEK_FLAG_BYTE;
seek_target = avio_tell(avfc->pb) + av_rescale(seek_avts_rel, avfc->bit_rate, 8 * AV_TIME_BASE);
}
} else {
int64_t pts;
if(player->output.GetPts(pts))
seek_target = av_rescale(pts, AV_TIME_BASE, 90000ll) + seek_avts_rel;
}
seek_avts_rel = 0;
} else if (seek_avts_abs != INT64_MIN) {
if (avfc->iformat->flags & AVFMT_TS_DISCONT) {
if (avfc->bit_rate) {
seek_target_flag = AVSEEK_FLAG_BYTE;
seek_target = av_rescale(seek_avts_abs, avfc->bit_rate, 8 * AV_TIME_BASE);
}
} else {
seek_target = seek_avts_abs;
}
seek_avts_abs = INT64_MIN;
} else if (player->isBackWard && av_gettime() >= showtime) {
player->output.ClearVideo();
if (bof) {
showtime = av_gettime();
usleep(100000);
continue;
}
seek_avts_rel = player->Speed * AV_TIME_BASE;
showtime = av_gettime() + 300000; //jump back every 300ms
continue;
} else {
bof = false;
}
if (seek_target > INT64_MIN) {
int res;
if (seek_target < 0)
seek_target = 0;
res = avformat_seek_file(avfc, -1, INT64_MIN, seek_target, INT64_MAX, seek_target_flag);
if (res < 0 && player->isBackWard)
bof = true;
seek_target = INT64_MIN;
restart_audio_resampling = true;
// clear streams
for (unsigned int i = 0; i < avfc->nb_streams; i++)
if (avfc->streams[i]->codec && avfc->streams[i]->codec->codec)
avcodec_flush_buffers(avfc->streams[i]->codec);
player->output.ClearAudio();
player->output.ClearVideo();
}
AVPacket packet;
av_init_packet(&packet);
int err = av_read_frame(avfc, &packet);
if (err == AVERROR(EAGAIN)) {
av_free_packet(&packet);
continue;
}
if (averror(err, av_read_frame)) // EOF?
break; // while
player->readCount += packet.size;
AVStream *stream = avfc->streams[packet.stream_index];
Track *_videoTrack = videoTrack;
Track *_audioTrack = audioTrack;
#if 0
Track *_subtitleTrack = subtitleTrack;
Track *_teletextTrack = teletextTrack;
#endif
if (_videoTrack && (_videoTrack->stream == stream)) {
int64_t pts = calcPts(stream, packet.pts);
if (audioSeen && !player->output.Write(stream, &packet, pts))
logprintf("writing data to %s device failed\n", "video");
} else if (_audioTrack && (_audioTrack->stream == stream)) {
if (restart_audio_resampling) {
restart_audio_resampling = false;
player->output.Write(stream, NULL, 0);
}
if (_audioTrack->bsfc) {
/* this code is more or less copied from ffmpeg.c */
AVBitStreamFilterContext *bsfc = _audioTrack->bsfc;
av_packet_split_side_data(&packet);
AVPacket new_pkt = packet;
AVCodecContext *avcc = stream->codec;
int a = av_bitstream_filter_filter(bsfc, avcc, NULL,
&new_pkt.data, &new_pkt.size,
packet.data, packet.size,
packet.flags & AV_PKT_FLAG_KEY);
if (a == 0 && new_pkt.data != packet.data) {
if (reinit_audio < 2)
reinit_audio++;
uint8_t *t = (uint8_t *)av_malloc(new_pkt.size + FF_INPUT_BUFFER_PADDING_SIZE);
if(t) {
memcpy(t, new_pkt.data, new_pkt.size);
memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
new_pkt.data = t;
new_pkt.buf = NULL;
a = 1;
} else {
/* TODO: what happens here? */
a = AVERROR(ENOMEM);
}
}
if (a > 0) {
packet.side_data = NULL;
packet.side_data_elems = 0;
av_free_packet(&packet);
new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size,
av_buffer_default_free, NULL, 0);
if (! new_pkt.buf)
logprintf("eplayer3:input %d no memory\n", __LINE__);
} else if (a < 0) {
logprintf("eplayer3:input: failed to open bitstream filter\n");
}
packet = new_pkt;
}
if (reinit_audio == 1) { /* only run once on start */
/* we need to reprogram the AAC header in Writer::Init()
* this is a cheap hack to do that */
logprintf("eplayer3:input: reset audio stream\n");
player->output.SwitchAudio(NULL);
player->output.SwitchAudio(stream);
}
if (!player->isBackWard) {
int64_t pts = calcPts(stream, packet.pts);
if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0))
logprintf("writing data to %s device failed\n", "audio");
}
audioSeen = true;
#if 0
} else if (_subtitleTrack && (_subtitleTrack->stream == stream)) {
if (stream->codec->codec) {
AVSubtitle sub;
memset(&sub, 0, sizeof(sub));
int got_sub_ptr = 0;
err = avcodec_decode_subtitle2(stream->codec, &sub, &got_sub_ptr, &packet);
averror(err, avcodec_decode_subtitle2);
if (got_sub_ptr && sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_TEXT: // FIXME?
case SUBTITLE_ASS:
dvbsub_ass_write(stream->codec, &sub, _subtitleTrack->pid);
break;
case SUBTITLE_BITMAP: {
int64_t pts = calcPts(stream, packet.pts);
dvbsub_write(&sub, pts);
// avsubtitle_free() will be called by handler
break;
}
default:
break;
}
}
}
} else if (_teletextTrack && (_teletextTrack->stream == stream)) {
if (packet.data && packet.size > 1)
teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1);
#endif
}
av_free_packet(&packet);
} /* while */
if (player->abortRequested)
player->output.Clear();
else
player->output.Flush();
#if 0
dvbsub_ass_clear();
#endif
abortPlayback = true;
hasPlayThreadStarted = false;
return true;
}
/*static*/ int interrupt_cb(void *arg)
{
Player *player = (Player *) arg;
bool res = player->input.abortPlayback || player->abortRequested;
if (res)
fprintf(stderr, "%s %s %d: abort requested (%d/%d)\n", FILENAME, __func__, __LINE__, player->input.abortPlayback, player->abortRequested);
return res;
}
static int lock_callback(void **mutex, enum AVLockOp op)
{
switch (op) {
case AV_LOCK_CREATE:
*mutex = (void *) new OpenThreads::Mutex;
return !*mutex;
case AV_LOCK_DESTROY:
delete static_cast<OpenThreads::Mutex *>(*mutex);
*mutex = NULL;
return 0;
case AV_LOCK_OBTAIN:
static_cast<OpenThreads::Mutex *>(*mutex)->lock();
return 0;
case AV_LOCK_RELEASE:
static_cast<OpenThreads::Mutex *>(*mutex)->unlock();
return 0;
default:
return -1;
}
}
#if 0
bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
{
const char *lastDot = strrchr(filename, '.');
if (!lastDot)
return false;
char subfile[strlen(filename) + strlen(format)];
strcpy(subfile, filename);
strcpy(subfile + (lastDot + 1 - filename), format);
if (access(subfile, R_OK))
return false;
AVFormatContext *subavfc = avformat_alloc_context();
int err = avformat_open_input(&subavfc, subfile, av_find_input_format(format), 0);
if (averror(err, avformat_open_input)) {
avformat_free_context(subavfc);
return false;
}
avformat_find_stream_info(subavfc, NULL);
if (subavfc->nb_streams != 1) {
avformat_free_context(subavfc);
return false;
}
AVCodecContext *c = subavfc->streams[0]->codec;
AVCodec *codec = avcodec_find_decoder(c->codec_id);
if (!codec) {
avformat_free_context(subavfc);
return false;
}
err = avcodec_open2(c, codec, NULL);
if (averror(err, avcodec_open2)) {
avformat_free_context(subavfc);
return false;
}
AVPacket packet;
av_init_packet(&packet);
while (av_read_frame(subavfc, &packet) > -1) {
AVSubtitle sub;
memset(&sub, 0, sizeof(sub));
int got_sub = 0;
avcodec_decode_subtitle2(c, &sub, &got_sub, &packet);
if (got_sub)
dvbsub_ass_write(c, &sub, pid);
av_free_packet(&packet);
}
avcodec_close(c);
avformat_close_input(&subavfc);
avformat_free_context(subavfc);
Track track;
track.title = format;
track.is_static = 1;
track.pid = pid;
player->manager.addSubtitleTrack(track);
return true;
}
bool Input::ReadSubtitles(const char *filename) {
if (strncmp(filename, "file://", 7))
return false;
filename += 7;
bool ret = false;
ret |= ReadSubtitle(filename, "srt", 0xFFFF);
ret |= ReadSubtitle(filename, "ass", 0xFFFE);
ret |= ReadSubtitle(filename, "ssa", 0xFFFD);
return ret;
}
#endif
bool Input::Init(const char *filename)
{
bool find_info = true;
abortPlayback = false;
av_lockmgr_register(lock_callback);
#if ENABLE_LOGGING
av_log_set_callback(log_callback);
#endif
if (!filename) {
fprintf(stderr, "filename NULL\n");
return false;
}
fprintf(stderr, "%s %s %d: %s\n", FILENAME, __func__, __LINE__, filename);
avcodec_register_all();
av_register_all();
avformat_network_init();
videoTrack = NULL;
audioTrack = NULL;
subtitleTrack = NULL;
teletextTrack = NULL;
//again:
avfc = avformat_alloc_context();
avfc->interrupt_callback.callback = interrupt_cb;
avfc->interrupt_callback.opaque = (void *) player;
AVDictionary *options = NULL;
av_dict_set(&options, "auth_type", "basic", 0);
int err = avformat_open_input(&avfc, filename, NULL, &options);
av_dict_free(&options);
if (averror(err, avformat_open_input)) {
avformat_free_context(avfc);
return false;
}
avfc->iformat->flags |= AVFMT_SEEK_TO_PTS;
avfc->flags = AVFMT_FLAG_GENPTS;
if (player->noprobe) {
#if (LIBAVFORMAT_VERSION_MAJOR < 55) || \
(LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR < 43) || \
(LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR == 43 && LIBAVFORMAT_VERSION_MICRO < 100)
avfc->max_analyze_duration = 1;
#else
avfc->max_analyze_duration2 = 1;
#endif
avfc->probesize = 131072;
}
/* only call avformat_find_stream_info if no AAC
* stream is present to speed up playback start
* TODO: do we need avformat_find_stream_info at all? */
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
if (avfc->streams[i]->codec->codec_id == AV_CODEC_ID_AAC)
find_info = false;
}
if (find_info)
err = avformat_find_stream_info(avfc, NULL);
#if 0
/* old code: we did retry if noprobe failed. Is this still needed? */
if (averror(err, avformat_find_stream_info)) {
avformat_close_input(&avfc);
if (player->noprobe) {
player->noprobe = false;
goto again;
}
return false;
}
#endif
bool res = UpdateTracks();
if (!videoTrack && !audioTrack) {
avformat_close_input(&avfc);
return false;
}
if (videoTrack)
player->output.SwitchVideo(videoTrack->stream);
if (audioTrack)
player->output.SwitchAudio(audioTrack->stream);
#if 0
ReadSubtitles(filename);
#endif
return res;
}
bool Input::UpdateTracks()
{
if (abortPlayback)
return true;
std::vector<Chapter> chapters;
for (unsigned int i = 0; i < avfc->nb_chapters; i++) {
AVChapter *ch = avfc->chapters[i];
AVDictionaryEntry* title = av_dict_get(ch->metadata, "title", NULL, 0);
Chapter chapter;
chapter.title = title ? title->value : "";
chapter.start = av_rescale(ch->time_base.num * AV_TIME_BASE, ch->start, ch->time_base.den);
chapter.end = av_rescale(ch->time_base.num * AV_TIME_BASE, ch->end, ch->time_base.den);
chapters.push_back(chapter);
}
player->SetChapters(chapters);
player->manager.initTrackUpdate();
av_dump_format(avfc, 0, player->url.c_str(), 0);
bool use_index_as_pid = false;
for (unsigned int n = 0; n < avfc->nb_streams; n++) {
AVStream *stream = avfc->streams[n];
Track track;
track.stream = stream;
AVDictionaryEntry *lang = av_dict_get(stream->metadata, "language", NULL, 0);
track.title = lang ? lang->value : "";
if (!use_index_as_pid)
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_AUDIO:
case AVMEDIA_TYPE_SUBTITLE:
if (!stream->id)
use_index_as_pid = true;
default:
break;
}
track.pid = use_index_as_pid ? n + 1: stream->id;
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
player->manager.addVideoTrack(track);
if (!videoTrack)
videoTrack = player->manager.getVideoTrack(track.pid);
break;
case AVMEDIA_TYPE_AUDIO:
switch(stream->codec->codec_id) {
case AV_CODEC_ID_MP2:
track.ac3flags = 9;
break;
case AV_CODEC_ID_MP3:
track.ac3flags = 4;
break;
case AV_CODEC_ID_AC3:
track.ac3flags = 1;
break;
case AV_CODEC_ID_EAC3:
track.ac3flags = 7;
break;
case AV_CODEC_ID_DTS:
track.ac3flags = 6;
break;
case AV_CODEC_ID_AAC:
track.ac3flags = 5;
track.bsfc = av_bitstream_filter_init("aac_adtstoasc");
logprintf("adding AAC STREAM %d, bsfc: %p (aac_adtstoasc)\n",
track.pid, track.bsfc);
break;
default:
track.ac3flags = 0;
}
player->manager.addAudioTrack(track);
if (!audioTrack)
audioTrack = player->manager.getAudioTrack(track.pid);
break;
case AVMEDIA_TYPE_SUBTITLE:
if (stream->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
std::string l = lang ? lang->value : "";
uint8_t *data = stream->codec->extradata;
int size = stream->codec->extradata_size;
if (size > 0 && 2 * size - 1 == (int) l.length())
for (int i = 0; i < size; i += 2) {
track.title = l.substr(i * 2, 3);
track.type = data[i] >> 3;
track.mag = data[i] & 7;
track.page = data[i + 1];
player->manager.addTeletextTrack(track);
}
} else {
if (!stream->codec->codec) {
stream->codec->codec = avcodec_find_decoder(stream->codec->codec_id);
if (!stream->codec->codec)
fprintf(stderr, "avcodec_find_decoder failed for subtitle track %d\n", n);
else {
int err = avcodec_open2(stream->codec, stream->codec->codec, NULL);
if (averror(err, avcodec_open2))
stream->codec->codec = NULL;
}
}
if (stream->codec->codec)
player->manager.addSubtitleTrack(track);
}
break;
default:
fprintf(stderr, "not handled or unknown codec_type %d\n", stream->codec->codec_type);
break;
}
}
for (unsigned int n = 0; n < avfc->nb_programs; n++) {
AVProgram *p = avfc->programs[n];
if (p->nb_stream_indexes) {
AVDictionaryEntry *name = av_dict_get(p->metadata, "name", NULL, 0);
Program program;
program.title = name ? name->value : "";
program.id = p->id;
for (unsigned m = 0; m < p->nb_stream_indexes; m++)
program.streams.push_back(avfc->streams[p->stream_index[m]]);
player->manager.addProgram(program);
}
}
return true;
}
bool Input::Stop()
{
abortPlayback = true;
while (hasPlayThreadStarted != 0)
usleep(100000);
if (avfc) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
for (unsigned int i = 0; i < avfc->nb_streams; i++)
avcodec_close(avfc->streams[i]->codec);
avformat_close_input(&avfc);
}
avformat_network_deinit();
return true;
}
AVFormatContext *Input::GetAVFormatContext()
{
mutex.lock();
if (avfc)
return avfc;
mutex.unlock();
return NULL;
}
void Input::ReleaseAVFormatContext()
{
if (avfc)
mutex.unlock();
}
bool Input::Seek(int64_t avts, bool absolute)
{
if (absolute)
seek_avts_abs = avts, seek_avts_rel = 0;
else
seek_avts_abs = INT64_MIN, seek_avts_rel = avts;
return true;
}
bool Input::GetDuration(int64_t &duration)
{
if (avfc) {
duration = avfc->duration;
return true;
}
duration = 0;
return false;
}
bool Input::SwitchAudio(Track *track)
{
audioTrack = track;
player->output.SwitchAudio(track ? track->stream : NULL);
// player->Seek(-5000, false);
return true;
}
bool Input::SwitchSubtitle(Track *track)
{
subtitleTrack = track;
return true;
}
bool Input::SwitchTeletext(Track *track)
{
teletextTrack = track;
return true;
}
bool Input::SwitchVideo(Track *track)
{
videoTrack = track;
player->output.SwitchVideo(track ? track->stream : NULL);
return true;
}
bool Input::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
{
keys.clear();
values.clear();
if (avfc) {
AVDictionaryEntry *tag = NULL;
if (avfc->metadata)
while ((tag = av_dict_get(avfc->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
keys.push_back(tag->key);
values.push_back(tag->value);
}
if (videoTrack)
while ((tag = av_dict_get(videoTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
keys.push_back(tag->key);
values.push_back(tag->value);
}
if (audioTrack)
while ((tag = av_dict_get(audioTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
keys.push_back(tag->key);
values.push_back(tag->value);
}
}
return true;
}
bool Input::GetReadCount(uint64_t &readcount)
{
readcount = readCount;
return true;
}

275
libeplayer3/manager.cpp Normal file
View File

@@ -0,0 +1,275 @@
/*
* manager class
*
* Copyright (C) 2014 martii
*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include "manager.h"
#include "player.h"
void Manager::addTrack(std::map<int,Track*> &tracks, Track &track)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = tracks.find(track.pid);
if (it == tracks.end()) {
Track *t = new Track;
*t = track;
tracks[track.pid] = t;
} else {
/* this should be handled by Track() itself, instead of special casing here... */
if ((*it->second).bsfc) {
fprintf(stderr, "eplayer3:%s: closing bsf %p\n", __func__, (*it->second).bsfc);
av_bitstream_filter_close((*it->second).bsfc);
}
*it->second = track;
}
}
void Manager::addVideoTrack(Track &track)
{
addTrack(videoTracks, track);
}
void Manager::addAudioTrack(Track &track)
{
addTrack(audioTracks, track);
}
void Manager::addSubtitleTrack(Track &track)
{
addTrack(subtitleTracks, track);
}
void Manager::addTeletextTrack(Track &track)
{
addTrack(teletextTracks, track);
}
std::vector<Track> Manager::getTracks(std::map<int,Track*> &tracks)
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for(std::map<int,Track*>::iterator it = tracks.begin(); it != tracks.end(); ++it)
if (!it->second->inactive && !it->second->hidden)
res.push_back(*it->second);
return res;
}
std::vector<Track> Manager::getVideoTracks()
{
return getTracks(videoTracks);
}
std::vector<Track> Manager::getAudioTracks()
{
return getTracks(audioTracks);
}
std::vector<Track> Manager::getSubtitleTracks()
{
return getTracks(subtitleTracks);
}
std::vector<Track> Manager::getTeletextTracks()
{
return getTracks(teletextTracks);
}
Track *Manager::getTrack(std::map<int,Track*> &tracks, int pid)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = tracks.find(pid);
if (it != tracks.end() && !it->second->inactive)
return it->second;
return NULL;
}
Track *Manager::getVideoTrack(int pid)
{
return getTrack(videoTracks, pid);
}
Track *Manager::getAudioTrack(int pid)
{
return getTrack(audioTracks, pid);
}
Track *Manager::getSubtitleTrack(int pid)
{
return getTrack(subtitleTracks, pid);
}
Track *Manager::getTeletextTrack(int pid)
{
return getTrack(teletextTracks, pid);
}
bool Manager::initTrackUpdate()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
it->second->inactive = !it->second->is_static;
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
it->second->inactive = !it->second->is_static;
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
it->second->inactive = !it->second->is_static;
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
it->second->inactive = !it->second->is_static;
return true;
}
void Manager::addProgram(Program &program)
{
Programs[program.id] = program;
}
std::vector<Program> Manager::getPrograms(void)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::vector<Program> res;
for (std::map<int,Program>::iterator it = Programs.begin(); it != Programs.end(); ++it)
res.push_back(it->second);
return res;
}
bool Manager::selectProgram(const int id)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Program>::iterator i = Programs.find(id);
if (i != Programs.end()) {
// mark all tracks as hidden
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
it->second->hidden = true;
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
it->second->hidden = true;
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
it->second->hidden = true;
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
it->second->hidden = true;
// unhide tracks that are part of the selected program
for (unsigned int j = 0; j < i->second.streams.size(); j++) {
AVStream *stream = i->second.streams[j];
bool h = true;
for (std::map<int,Track*>::iterator it = audioTracks.begin(); h && (it != audioTracks.end()); ++it)
if (stream == it->second->stream)
h = it->second->hidden = false;
if (!h)
continue;
for (std::map<int, Track*>::iterator it = videoTracks.begin(); h && (it != videoTracks.end()); ++it)
if (stream == it->second->stream)
h = it->second->hidden = false;
if (!h)
continue;
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); h && (it != subtitleTracks.end()); ++it)
if (stream == it->second->stream)
h = it->second->hidden = false;
if (!h)
continue;
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); h && (it != teletextTracks.end()); ++it)
if (stream == it->second->stream)
h = it->second->hidden = false;
}
// tell ffmpeg what we're interested in
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
if (it->second->hidden || it->second->inactive) {
it->second->stream->discard = AVDISCARD_ALL;
} else {
it->second->stream->discard = AVDISCARD_NONE;
player->input.SwitchAudio(it->second);
}
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
if (it->second->hidden || it->second->inactive) {
it->second->stream->discard = AVDISCARD_ALL;
} else {
it->second->stream->discard = AVDISCARD_NONE;
player->input.SwitchVideo(it->second);
}
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
if (it->second->hidden || it->second->inactive) {
it->second->stream->discard = AVDISCARD_ALL;
} else {
it->second->stream->discard = AVDISCARD_NONE;
player->input.SwitchSubtitle(it->second);
}
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
if (it->second->hidden || it->second->inactive) {
it->second->stream->discard = AVDISCARD_ALL;
} else {
it->second->stream->discard = AVDISCARD_NONE;
player->input.SwitchTeletext(it->second);
}
return true;
}
return false;
}
void Manager::clearTracks()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it) {
/* see comment in addTrack() :-) */
if (it->second->bsfc) {
fprintf(stderr, "eplayer3:%s: closing bsf %p\n", __func__, it->second->bsfc);
av_bitstream_filter_close(it->second->bsfc);
}
delete it->second;
}
audioTracks.clear();
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
delete it->second;
videoTracks.clear();
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
delete it->second;
subtitleTracks.clear();
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
delete it->second;
teletextTracks.clear();
Programs.clear();
}
Manager::~Manager()
{
clearTracks();
}

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