mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 23:12:44 +02:00
Merge branch 'master' of https://github.com/TangoCash/libstb-hal-cst-next.git into mpx
update version 1.0.1
Conflicts:
include/hardware_caps.h
libarmbox/hardware_caps.c
libduckbox/hardware_caps.c
libspark/hardware_caps.c
Origin commit data
------------------
Branch: master
Commit: 0040c0d0af
Author: Thilo Graf <dbt@novatux.de>
Date: 2017-11-06 (Mon, 06 Nov 2017)
------------------
This commit was generated by Migit
This commit is contained in:
51
ChangeLog
51
ChangeLog
@@ -1,3 +1,54 @@
|
|||||||
|
2017-11-06 Thilo Graf <dbt@novatux.de>
|
||||||
|
|
||||||
|
Merge branch 'master' of https://github.com/TangoCash/libstb-hal-cst-next.git into mpx
|
||||||
|
update version 1.0.1
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
include/hardware_caps.h
|
||||||
|
libarmbox/hardware_caps.c
|
||||||
|
libduckbox/hardware_caps.c
|
||||||
|
libspark/hardware_caps.c
|
||||||
|
|
||||||
|
2017-11-06 max_10 <max_10@gmx.de>
|
||||||
|
|
||||||
|
ci: armbox fix cpu load
|
||||||
|
|
||||||
|
2017-11-05 TangoCash <eric@loxat.de>
|
||||||
|
|
||||||
|
fix compile #2
|
||||||
|
|
||||||
|
fix compile
|
||||||
|
|
||||||
|
2017-11-05 max_10 <max_10@gmx.de>
|
||||||
|
|
||||||
|
armbox: add dvbci (thx DboxOldie)
|
||||||
|
|
||||||
|
2017-11-05 TangoCash <eric@loxat.de>
|
||||||
|
|
||||||
|
armbox: tryfix cec
|
||||||
|
|
||||||
|
Merge branch 'master' of github.com:Duckbox-Developers/libstb-hal-cst-next
|
||||||
|
|
||||||
|
ci: let stbhal handle close
|
||||||
|
|
||||||
|
2017-11-04 TangoCash <eric@loxat.de>
|
||||||
|
|
||||||
|
gstreamer playback, cleanup, fix real pid handling
|
||||||
|
|
||||||
|
2017-11-03 TangoCash <eric@loxat.de>
|
||||||
|
|
||||||
|
gstreamer playback, avoid segfault
|
||||||
|
|
||||||
|
gstreamer playback, fix possible segfault #2
|
||||||
|
|
||||||
|
gstreamer playback, fix possible segfault
|
||||||
|
|
||||||
|
update generic gstreamer
|
||||||
|
|
||||||
|
Merge branch 'master' of github.com:Duckbox-Developers/libstb-hal-cst-next
|
||||||
|
|
||||||
|
align
|
||||||
|
|
||||||
2017-11-02 Thilo Graf <dbt@novatux.de>
|
2017-11-02 Thilo Graf <dbt@novatux.de>
|
||||||
|
|
||||||
version 1.0.0-mpx
|
version 1.0.0-mpx
|
||||||
|
@@ -54,7 +54,8 @@ libstb_hal_la_LIBADD += \
|
|||||||
endif
|
endif
|
||||||
if BOXTYPE_ARMBOX
|
if BOXTYPE_ARMBOX
|
||||||
libstb_hal_test_LDADD += -lasound
|
libstb_hal_test_LDADD += -lasound
|
||||||
SUBDIRS += libarmbox
|
SUBDIRS += libarmbox libdvbci
|
||||||
libstb_hal_la_LIBADD += \
|
libstb_hal_la_LIBADD += \
|
||||||
libarmbox/libarmbox.la
|
libarmbox/libarmbox.la \
|
||||||
|
libdvbci/libdvbci.la
|
||||||
endif
|
endif
|
||||||
|
@@ -9,13 +9,24 @@ AM_CXXFLAGS += \
|
|||||||
-I $(top_srcdir)/libdvbci
|
-I $(top_srcdir)/libdvbci
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BOXTYPE_ARMBOX
|
||||||
|
AM_CXXFLAGS += \
|
||||||
|
-I $(top_srcdir)/include \
|
||||||
|
-I $(top_srcdir)/libdvbci
|
||||||
|
endif
|
||||||
|
|
||||||
if BOXTYPE_DUCKBOX
|
if BOXTYPE_DUCKBOX
|
||||||
libcommon_la_SOURCES = \
|
libcommon_la_SOURCES = \
|
||||||
ca_ci.cpp
|
ca_ci.cpp
|
||||||
else
|
else
|
||||||
|
if BOXTYPE_ARMBOX
|
||||||
|
libcommon_la_SOURCES = \
|
||||||
|
ca_ci.cpp
|
||||||
|
else
|
||||||
libcommon_la_SOURCES = \
|
libcommon_la_SOURCES = \
|
||||||
ca.cpp
|
ca.cpp
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
libcommon_la_SOURCES += \
|
libcommon_la_SOURCES += \
|
||||||
lt_debug.cpp \
|
lt_debug.cpp \
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* dummy functions to implement ca_cs.h interface
|
* dummy functions to implement ca_cs.h interface
|
||||||
*/
|
*/
|
||||||
#if HAVE_DUCKBOX_HARDWARE
|
#if HAVE_DUCKBOX_HARDWARE || HAVE_ARM_HARDWARE
|
||||||
#include "ca_ci.h"
|
#include "ca_ci.h"
|
||||||
#else
|
#else
|
||||||
#ifndef __CA_LIBTRIPLE_H_
|
#ifndef __CA_LIBTRIPLE_H_
|
||||||
|
962
common/ca_ci.cpp
962
common/ca_ci.cpp
File diff suppressed because it is too large
Load Diff
@@ -194,8 +194,10 @@ typedef struct
|
|||||||
|
|
||||||
bool ccmgr_ready;
|
bool ccmgr_ready;
|
||||||
|
|
||||||
|
char ci_dev[32];
|
||||||
char name[512];
|
char name[512];
|
||||||
|
|
||||||
|
bool newPids;
|
||||||
bool newCapmt;
|
bool newCapmt;
|
||||||
bool multi;
|
bool multi;
|
||||||
bool recordUse[CI_MAX_MULTI];
|
bool recordUse[CI_MAX_MULTI];
|
||||||
@@ -212,6 +214,8 @@ typedef struct
|
|||||||
CaIdVector cam_caids;
|
CaIdVector cam_caids;
|
||||||
std::priority_queue<queueData> sendqueue;
|
std::priority_queue<queueData> sendqueue;
|
||||||
|
|
||||||
|
std::vector<u16> pids;
|
||||||
|
|
||||||
bSIDVector bsids;
|
bSIDVector bsids;
|
||||||
unsigned char lastKey[32];
|
unsigned char lastKey[32];
|
||||||
unsigned char scrambled;
|
unsigned char scrambled;
|
||||||
@@ -237,6 +241,38 @@ private:
|
|||||||
cCA(void);
|
cCA(void);
|
||||||
/// Private data for the CA module
|
/// Private data for the CA module
|
||||||
CS_CA_PDATA *privateData;
|
CS_CA_PDATA *privateData;
|
||||||
|
/// set inputs with tuner letter in tsmux
|
||||||
|
void setInputs();
|
||||||
|
/// write ci info file to /tmp
|
||||||
|
void write_ci_info(int slot, CaIdVector caids);
|
||||||
|
/// delete ci info file
|
||||||
|
void del_ci_info(int slot);
|
||||||
|
/// extract audio / video pids from capmt
|
||||||
|
void extractPids(eDVBCISlot* slot);
|
||||||
|
/// ci module is detected
|
||||||
|
void ci_inserted(eDVBCISlot* slot);
|
||||||
|
/// ci module is removed
|
||||||
|
void ci_removed(eDVBCISlot* slot);
|
||||||
|
/// decode the tpdu tag
|
||||||
|
void process_tpdu(eDVBCISlot* slot, unsigned char tpdu_tag, __u8* data, int asn_data_length, int con_id);
|
||||||
|
/// set flag of running ci record to false
|
||||||
|
bool StopRecordCI( u64 TP, u16 SID, u8 source, u32 calen);
|
||||||
|
/// set flag of running ci live-tv to false
|
||||||
|
bool StopLiveCI( u64 TP, u16 SID, u8 source, u32 calen);
|
||||||
|
/// find an unused ci slot for use with service
|
||||||
|
SlotIt FindFreeSlot(u64 tpid, u8 source, u16 sid, ca_map_t camap, u8 scrambled);
|
||||||
|
/// get slot iterator by slot number
|
||||||
|
SlotIt GetSlot(unsigned int slot);
|
||||||
|
/// send buffered capmt to ci modul
|
||||||
|
bool SendCaPMT(eDVBCISlot* slot);
|
||||||
|
/// send a dummy capmt to ci for deactivating
|
||||||
|
bool SendNullPMT(eDVBCISlot* slot);
|
||||||
|
/// set ci source
|
||||||
|
void setSource(eDVBCISlot* slot);
|
||||||
|
/// set demux source
|
||||||
|
void setInputSource(eDVBCISlot* slot, bool ci);
|
||||||
|
/// check if data in queue
|
||||||
|
bool checkQueueSize(eDVBCISlot* slot);
|
||||||
enum CA_INIT_MASK initMask;
|
enum CA_INIT_MASK initMask;
|
||||||
int num_slots;
|
int num_slots;
|
||||||
bool init;
|
bool init;
|
||||||
@@ -246,7 +282,9 @@ private:
|
|||||||
pthread_t slot_thread;
|
pthread_t slot_thread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// sh4 unused
|
||||||
bool Init(void);
|
bool Init(void);
|
||||||
|
/// init ci and start the loop
|
||||||
cCA(int Slots);
|
cCA(int Slots);
|
||||||
/// Returns the number of CI slots
|
/// Returns the number of CI slots
|
||||||
uint32_t GetNumberCISlots(void);
|
uint32_t GetNumberCISlots(void);
|
||||||
@@ -260,17 +298,23 @@ public:
|
|||||||
bool SendMessage(const CA_MESSAGE *Msg);
|
bool SendMessage(const CA_MESSAGE *Msg);
|
||||||
/// Sets which modules to initialize. It is only
|
/// Sets which modules to initialize. It is only
|
||||||
/// possible to change this once!
|
/// possible to change this once!
|
||||||
|
/// sh4 unused
|
||||||
void SetInitMask(enum CA_INIT_MASK InitMask);
|
void SetInitMask(enum CA_INIT_MASK InitMask);
|
||||||
/// Sets the frequency (in Hz) of the TS stream input (only valid for CI)
|
/// Sets the frequency (in Hz) of the TS stream input (only valid for CI)
|
||||||
void SetTSClock(u32 /*Speed*/) { return; };
|
/// sh4 unused
|
||||||
|
void SetTSClock(u32 Speed);
|
||||||
/// Start the CA module
|
/// Start the CA module
|
||||||
|
/// sh4 unused
|
||||||
bool Start(void);
|
bool Start(void);
|
||||||
/// Stops the CA module
|
/// Stops the CA module
|
||||||
|
/// sh4 unused
|
||||||
void Stop(void);
|
void Stop(void);
|
||||||
/// Notify that the GUI is ready to receive messages
|
/// Notify that the GUI is ready to receive messages
|
||||||
/// (CA messages coming from a module)
|
/// (CA messages coming from a module)
|
||||||
|
/// sh4 unused
|
||||||
void Ready(bool Set);
|
void Ready(bool Set);
|
||||||
/// Resets a module (if possible)
|
/// Resets a module (if possible)
|
||||||
|
/// sh4 unused
|
||||||
void ModuleReset(enum CA_SLOT_TYPE, uint32_t Slot);
|
void ModuleReset(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||||
/// Checks if a module is present
|
/// Checks if a module is present
|
||||||
bool ModulePresent(enum CA_SLOT_TYPE, uint32_t Slot);
|
bool ModulePresent(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||||
@@ -285,29 +329,20 @@ public:
|
|||||||
/// Notify the module we closed the menu
|
/// Notify the module we closed the menu
|
||||||
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
|
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||||
/// Get the supported CAIDs
|
/// Get the supported CAIDs
|
||||||
// int GetCAIDS(CaIdVector & /*Caids*/) { return 0; };
|
|
||||||
int GetCAIDS(CaIdVector &Caids);
|
int GetCAIDS(CaIdVector &Caids);
|
||||||
/// Send a CA-PMT object and Raw unparsed PMT to the CA layer
|
/// Send a CA-PMT object and Raw unparsed PMT to the CA layer
|
||||||
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL,
|
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL,
|
||||||
unsigned char scrambled = 0, ca_map_t camap = std::set<int>(), int mode = 0, bool enabled = false);
|
unsigned char scrambled = 0, ca_map_t camap = std::set<int>(), int mode = 0, bool enabled = false);
|
||||||
|
/// sh4 unused
|
||||||
bool StopRecordCI( u64 TP, u16 SID, u8 source, u32 calen);
|
|
||||||
bool StopLiveCI( u64 TP, u16 SID, u8 source, u32 calen);
|
|
||||||
SlotIt FindFreeSlot(u64 tpid, u8 source, u16 sid, ca_map_t camap, unsigned char scrambled);
|
|
||||||
SlotIt GetSlot(unsigned int slot);
|
|
||||||
bool SendDateTime(void);
|
bool SendDateTime(void);
|
||||||
bool SendCaPMT(eDVBCISlot* slot);
|
/// the main loop
|
||||||
void slot_pollthread(void *c);
|
void slot_pollthread(void *c);
|
||||||
void setSource(eDVBCISlot* slot);
|
/// check if current channel uses any ci module
|
||||||
bool checkQueueSize(eDVBCISlot* slot);
|
|
||||||
void process_tpdu(eDVBCISlot* slot, unsigned char tpdu_tag, __u8* data, int asn_data_length, int con_id);
|
|
||||||
|
|
||||||
bool checkChannelID(u64 chanID);
|
bool checkChannelID(u64 chanID);
|
||||||
|
/// set checking for live-tv use ci to true
|
||||||
void setCheckLiveSlot(int check);
|
void setCheckLiveSlot(int check);
|
||||||
bool SendNullPMT(eDVBCISlot* slot);
|
/// as the name says
|
||||||
bool CheckCerts(void);
|
bool CheckCerts(void);
|
||||||
void Test(int slot, CaIdVector caids);
|
|
||||||
void DelTest(int slot);
|
|
||||||
/// Virtual destructor
|
/// Virtual destructor
|
||||||
virtual ~cCA();
|
virtual ~cCA();
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libstb-hal], [1.0.0])
|
AC_INIT([libstb-hal], [1.0.1])
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
@@ -36,7 +36,9 @@ if ENABLE_GSTREAMER_10
|
|||||||
libgeneric_la_SOURCES += \
|
libgeneric_la_SOURCES += \
|
||||||
playback_gst_10.cpp
|
playback_gst_10.cpp
|
||||||
AM_LDFLAGS += \
|
AM_LDFLAGS += \
|
||||||
-lgstreamer-1.0
|
-lgstreamer-1.0 \
|
||||||
|
-lgsttag-1.0 \
|
||||||
|
-lgstmpegts-1.0
|
||||||
else
|
else
|
||||||
libgeneric_la_SOURCES += \
|
libgeneric_la_SOURCES += \
|
||||||
playback.cpp
|
playback.cpp
|
||||||
|
@@ -131,6 +131,11 @@ void cPlayback::SetTitle(int /*title*/)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t cPlayback::GetReadCount(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cPlayback::cPlayback(int /*num*/)
|
cPlayback::cPlayback(int /*num*/)
|
||||||
{
|
{
|
||||||
printf("%s:%s\n", FILENAME, __func__);
|
printf("%s:%s\n", FILENAME, __func__);
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
STATE_STOP,
|
STATE_STOP,
|
||||||
STATE_PLAY,
|
STATE_PLAY,
|
||||||
STATE_PAUSE,
|
STATE_PAUSE,
|
||||||
@@ -35,21 +36,25 @@ typedef enum {
|
|||||||
STATE_SLOW
|
STATE_SLOW
|
||||||
} playstate_t;
|
} playstate_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
PLAYMODE_TS = 0,
|
PLAYMODE_TS = 0,
|
||||||
PLAYMODE_FILE,
|
PLAYMODE_FILE,
|
||||||
} playmode_t;
|
} playmode_t;
|
||||||
|
|
||||||
|
struct AVFormatContext;
|
||||||
|
|
||||||
class cPlayback
|
class cPlayback
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool playing;
|
bool playing, first;
|
||||||
|
bool decoders_closed;
|
||||||
|
|
||||||
int mSpeed;
|
int mSpeed;
|
||||||
int mAudioStream;
|
int mAudioStream;
|
||||||
|
int init_jump;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
playstate_t playstate;
|
playstate_t playstate;
|
||||||
|
|
||||||
cPlayback(int);
|
cPlayback(int);
|
||||||
@@ -71,6 +76,9 @@ class cPlayback
|
|||||||
bool GetSpeed(int &speed) const;
|
bool GetSpeed(int &speed) const;
|
||||||
bool GetPosition(int &position, int &duration);
|
bool GetPosition(int &position, int &duration);
|
||||||
void GetPts(uint64_t &pts);
|
void GetPts(uint64_t &pts);
|
||||||
|
int GetAPid(void);
|
||||||
|
int GetVPid(void);
|
||||||
|
int GetSubtitlePid(void);
|
||||||
bool SetPosition(int position, bool absolute = false);
|
bool SetPosition(int position, bool absolute = false);
|
||||||
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
|
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
|
||||||
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
|
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
|
||||||
@@ -81,6 +89,11 @@ class cPlayback
|
|||||||
uint64_t GetReadCount(void);
|
uint64_t GetReadCount(void);
|
||||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||||
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
|
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
|
||||||
|
AVFormatContext *GetAVFormatContext();
|
||||||
|
void ReleaseAVFormatContext();
|
||||||
|
std::string extra_headers;
|
||||||
|
std::string user_agent;
|
||||||
|
|
||||||
//
|
//
|
||||||
~cPlayback();
|
~cPlayback();
|
||||||
void getMeta();
|
void getMeta();
|
||||||
|
@@ -46,29 +46,39 @@
|
|||||||
static const char * FILENAME = "[playback.cpp]";
|
static const char * FILENAME = "[playback.cpp]";
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/tag/tag.h>
|
||||||
|
#include <gst/mpegts/mpegts.h>
|
||||||
#include <gst/pbutils/missing-plugins.h>
|
#include <gst/pbutils/missing-plugins.h>
|
||||||
#include <gst/video/videooverlay.h>
|
#include <gst/video/videooverlay.h>
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GST_PLAY_FLAG_VIDEO = 0x00000001,
|
GST_PLAY_FLAG_VIDEO = (1 << 0),
|
||||||
GST_PLAY_FLAG_AUDIO = 0x00000002,
|
GST_PLAY_FLAG_AUDIO = (1 << 1),
|
||||||
GST_PLAY_FLAG_TEXT = 0x00000004,
|
GST_PLAY_FLAG_TEXT = (1 << 2),
|
||||||
GST_PLAY_FLAG_VIS = 0x00000008,
|
GST_PLAY_FLAG_VIS = (1 << 3),
|
||||||
GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010,
|
GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
|
||||||
GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020,
|
GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
|
||||||
GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040,
|
GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
|
||||||
GST_PLAY_FLAG_DOWNLOAD = 0x00000080,
|
GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
|
||||||
GST_PLAY_FLAG_BUFFERING = 0x000000100
|
GST_PLAY_FLAG_BUFFERING = (1 << 8),
|
||||||
|
GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
|
||||||
|
GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10),
|
||||||
|
GST_PLAY_FLAG_FORCE_FILTERS = (1 << 11),
|
||||||
} GstPlayFlags;
|
} GstPlayFlags;
|
||||||
|
|
||||||
|
|
||||||
GstElement * m_gst_playbin = NULL;
|
GstElement * m_gst_playbin = NULL;
|
||||||
GstElement * audioSink = NULL;
|
GstElement * audioSink = NULL;
|
||||||
GstElement * videoSink = NULL;
|
GstElement * videoSink = NULL;
|
||||||
|
|
||||||
gchar * uri = NULL;
|
gchar * uri = NULL;
|
||||||
GstTagList * m_stream_tags = 0;
|
GstTagList * m_stream_tags = NULL;
|
||||||
static int end_eof = 0;
|
static int end_eof = 0;
|
||||||
|
#define HTTP_TIMEOUT 30
|
||||||
|
// taken from record.h
|
||||||
|
#define REC_MAX_APIDS 20
|
||||||
|
int real_apids[REC_MAX_APIDS];
|
||||||
|
|
||||||
extern GLFramebuffer *glfb;
|
extern GLFramebuffer *glfb;
|
||||||
|
|
||||||
@@ -78,6 +88,108 @@ gint match_sinktype(const GValue *velement, const gchar *type)
|
|||||||
return strcmp(g_type_name(G_OBJECT_TYPE(element)), type);
|
return strcmp(g_type_name(G_OBJECT_TYPE(element)), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetPids()
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < REC_MAX_APIDS; i++) {
|
||||||
|
real_apids[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMpegTsSection(GstMpegtsSection* section)
|
||||||
|
{
|
||||||
|
resetPids();
|
||||||
|
int cnt = 0;
|
||||||
|
if (section->section_type == GST_MPEGTS_SECTION_PMT) {
|
||||||
|
const GstMpegtsPMT* pmt = gst_mpegts_section_get_pmt(section);
|
||||||
|
for (guint i = 0; i < pmt->streams->len; ++i) {
|
||||||
|
const GstMpegtsPMTStream* stream = static_cast<const GstMpegtsPMTStream*>(g_ptr_array_index(pmt->streams, i));
|
||||||
|
if (stream->stream_type == 0x05 || stream->stream_type >= 0x80) {
|
||||||
|
lt_info_c( "%s:%s Audio Stream pid: %d\n", FILENAME, __FUNCTION__, stream->pid);
|
||||||
|
real_apids[cnt] = stream->pid;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data)
|
||||||
|
{
|
||||||
|
GstElement *source = NULL;
|
||||||
|
cPlayback *_this = (cPlayback*)user_data;
|
||||||
|
g_object_get(object, "source", &source, NULL);
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "timeout") != 0)
|
||||||
|
{
|
||||||
|
GstElementFactory *factory = gst_element_get_factory(source);
|
||||||
|
if (factory)
|
||||||
|
{
|
||||||
|
const gchar *sourcename = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
|
||||||
|
if (!strcmp(sourcename, "souphttpsrc"))
|
||||||
|
{
|
||||||
|
g_object_set(G_OBJECT(source), "timeout", HTTP_TIMEOUT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0)
|
||||||
|
{
|
||||||
|
g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL);
|
||||||
|
}
|
||||||
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0 && !_this->user_agent.empty())
|
||||||
|
{
|
||||||
|
g_object_set(G_OBJECT(source), "user-agent", _this->user_agent.c_str(), NULL);
|
||||||
|
}
|
||||||
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0 && !_this->extra_headers.empty())
|
||||||
|
{
|
||||||
|
GstStructure *extras = gst_structure_new_empty("extras");
|
||||||
|
size_t pos = 0;
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string name, value;
|
||||||
|
size_t start = pos;
|
||||||
|
size_t len = std::string::npos;
|
||||||
|
pos = _this->extra_headers.find('=', pos);
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
len = pos - start;
|
||||||
|
pos++;
|
||||||
|
name = _this->extra_headers.substr(start, len);
|
||||||
|
start = pos;
|
||||||
|
len = std::string::npos;
|
||||||
|
pos = _this->extra_headers.find('&', pos);
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
len = pos - start;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
value = _this->extra_headers.substr(start, len);
|
||||||
|
}
|
||||||
|
if (!name.empty() && !value.empty())
|
||||||
|
{
|
||||||
|
GValue header;
|
||||||
|
lt_info_c( "%s:%s setting extra-header '%s:%s'\n", FILENAME, __FUNCTION__, name.c_str(), value.c_str());
|
||||||
|
memset(&header, 0, sizeof(GValue));
|
||||||
|
g_value_init(&header, G_TYPE_STRING);
|
||||||
|
g_value_set_string(&header, value.c_str());
|
||||||
|
gst_structure_set_value(extras, name.c_str(), &header);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lt_info_c( "%s:%s Invalid header format %s\n", FILENAME, __FUNCTION__, _this->extra_headers.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gst_structure_n_fields(extras) > 0)
|
||||||
|
{
|
||||||
|
g_object_set(G_OBJECT(source), "extra-headers", extras, NULL);
|
||||||
|
}
|
||||||
|
gst_structure_free(extras);
|
||||||
|
}
|
||||||
|
gst_object_unref(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
||||||
{
|
{
|
||||||
gchar * sourceName;
|
gchar * sourceName;
|
||||||
@@ -148,33 +260,65 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
|||||||
result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
|
result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
if (m_stream_tags && gst_tag_list_is_equal(m_stream_tags, result))
|
||||||
|
{
|
||||||
|
gst_tag_list_unref(tags);
|
||||||
|
gst_tag_list_unref(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (m_stream_tags)
|
if (m_stream_tags)
|
||||||
gst_tag_list_free(m_stream_tags);
|
gst_tag_list_unref(m_stream_tags);
|
||||||
m_stream_tags = result;
|
m_stream_tags = gst_tag_list_copy(result);
|
||||||
|
gst_tag_list_unref(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
|
const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
|
||||||
if ( gv_image )
|
if ( gv_image )
|
||||||
{
|
{
|
||||||
GstBuffer *buf_image;
|
GstBuffer *buf_image;
|
||||||
buf_image = gst_value_get_buffer (gv_image);
|
GstSample *sample;
|
||||||
|
sample = (GstSample *)g_value_get_boxed(gv_image);
|
||||||
|
buf_image = gst_sample_get_buffer(sample);
|
||||||
int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||||
if(fd >= 0)
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
GstMapInfo Info;
|
guint8 *data;
|
||||||
gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ));
|
gsize size;
|
||||||
int ret = write(fd, Info.data, Info.size);
|
GstMapInfo map;
|
||||||
|
gst_buffer_map(buf_image, &map, GST_MAP_READ);
|
||||||
|
data = map.data;
|
||||||
|
size = map.size;
|
||||||
|
int ret = write(fd, data, size);
|
||||||
|
gst_buffer_unmap(buf_image, &map);
|
||||||
close(fd);
|
close(fd);
|
||||||
gst_buffer_unmap(buf_image, &Info);
|
lt_info_c("%s:%s - /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__, ret);
|
||||||
lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret);
|
|
||||||
}
|
}
|
||||||
//FIXME: how shall playback handle this event???
|
|
||||||
}
|
}
|
||||||
gst_tag_list_free(tags);
|
gst_tag_list_unref(tags);
|
||||||
lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event???
|
lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event???
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_MESSAGE_ELEMENT:
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-window-handle"))
|
||||||
|
{
|
||||||
|
// set window id
|
||||||
|
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID());
|
||||||
|
|
||||||
|
// reshape window
|
||||||
|
gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight());
|
||||||
|
|
||||||
|
// sync frames
|
||||||
|
gst_video_overlay_expose(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
GstMpegtsSection* section = gst_message_parse_mpegts_section(msg);
|
||||||
|
if (section) {
|
||||||
|
processMpegTsSection(section);
|
||||||
|
gst_mpegts_section_unref(section);
|
||||||
|
}
|
||||||
|
}
|
||||||
case GST_MESSAGE_STATE_CHANGED:
|
case GST_MESSAGE_STATE_CHANGED:
|
||||||
{
|
{
|
||||||
if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
|
if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
|
||||||
@@ -197,6 +341,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
|||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
{
|
{
|
||||||
GstIterator *children;
|
GstIterator *children;
|
||||||
|
GValue r = { 0, };
|
||||||
|
|
||||||
if (audioSink)
|
if (audioSink)
|
||||||
{
|
{
|
||||||
gst_object_unref(GST_OBJECT(audioSink));
|
gst_object_unref(GST_OBJECT(audioSink));
|
||||||
@@ -209,16 +355,27 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
|||||||
videoSink = NULL;
|
videoSink = NULL;
|
||||||
}
|
}
|
||||||
children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
|
children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
|
||||||
GValue r = G_VALUE_INIT;
|
|
||||||
gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink");
|
if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink"))
|
||||||
|
{
|
||||||
audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
|
audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
|
||||||
g_value_unset (&r);
|
g_value_unset (&r);
|
||||||
gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink");
|
lt_info_c( "%s %s - audio sink created\n", FILENAME, __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_iterator_free(children);
|
||||||
|
children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
|
||||||
|
|
||||||
|
if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink"))
|
||||||
|
{
|
||||||
videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
|
videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
|
||||||
g_value_unset (&r);
|
g_value_unset (&r);
|
||||||
|
lt_info_c( "%s %s - video sink created\n", FILENAME, __FUNCTION__);
|
||||||
|
}
|
||||||
gst_iterator_free(children);
|
gst_iterator_free(children);
|
||||||
|
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
{
|
{
|
||||||
} break;
|
} break;
|
||||||
@@ -237,29 +394,14 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
|||||||
gst_object_unref(GST_OBJECT(videoSink));
|
gst_object_unref(GST_OBJECT(videoSink));
|
||||||
videoSink = NULL;
|
videoSink = NULL;
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
{
|
{
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
case GST_MESSAGE_ELEMENT:
|
|
||||||
{
|
|
||||||
if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-window-handle"))
|
|
||||||
{
|
|
||||||
// set window id
|
|
||||||
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID());
|
|
||||||
|
|
||||||
// reshape window
|
|
||||||
gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight());
|
|
||||||
|
|
||||||
// sync frames
|
|
||||||
gst_video_overlay_expose(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -295,18 +437,24 @@ cPlayback::cPlayback(int num)
|
|||||||
|
|
||||||
playing = false;
|
playing = false;
|
||||||
playstate = STATE_STOP;
|
playstate = STATE_STOP;
|
||||||
|
decoders_closed = false;
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cPlayback::~cPlayback()
|
cPlayback::~cPlayback()
|
||||||
{
|
{
|
||||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||||
//FIXME: all deleting stuff is done in Close()
|
//FIXME: all deleting stuff is done in Close()
|
||||||
|
if (m_stream_tags)
|
||||||
|
gst_tag_list_unref(m_stream_tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Used by Fileplay
|
//Used by Fileplay
|
||||||
bool cPlayback::Open(playmode_t PlayMode)
|
bool cPlayback::Open(playmode_t PlayMode)
|
||||||
{
|
{
|
||||||
lt_info("%s: PlayMode %d\n", __func__, PlayMode);
|
lt_info("%s: PlayMode %d\n", __func__, PlayMode);
|
||||||
|
|
||||||
|
init_jump = -1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,9 +475,6 @@ void cPlayback::Close(void)
|
|||||||
lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__);
|
lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_stream_tags)
|
|
||||||
gst_tag_list_free(m_stream_tags);
|
|
||||||
|
|
||||||
// close gst
|
// close gst
|
||||||
if (m_gst_playbin)
|
if (m_gst_playbin)
|
||||||
{
|
{
|
||||||
@@ -354,7 +499,9 @@ void cPlayback::Close(void)
|
|||||||
lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__);
|
lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__);
|
||||||
|
|
||||||
m_gst_playbin = NULL;
|
m_gst_playbin = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start
|
// start
|
||||||
@@ -367,16 +514,32 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
|
|||||||
{
|
{
|
||||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||||
|
|
||||||
|
if (!headers.empty())
|
||||||
|
extra_headers = headers;
|
||||||
|
else
|
||||||
|
extra_headers.clear();
|
||||||
|
|
||||||
|
resetPids();
|
||||||
|
|
||||||
mAudioStream = 0;
|
mAudioStream = 0;
|
||||||
|
init_jump = -1;
|
||||||
|
|
||||||
|
gst_tag_list_unref(m_stream_tags);
|
||||||
|
m_stream_tags = NULL;
|
||||||
|
|
||||||
|
unlink("/tmp/.id3coverart");
|
||||||
|
|
||||||
//create playback path
|
//create playback path
|
||||||
char file[400] = {""};
|
|
||||||
bool isHTTP = false;
|
bool isHTTP = false;
|
||||||
|
|
||||||
if(!strncmp("http://", filename, 7))
|
if(!strncmp("http://", filename, 7))
|
||||||
{
|
{
|
||||||
isHTTP = true;
|
isHTTP = true;
|
||||||
}
|
}
|
||||||
|
else if(!strncmp("https://", filename, 8))
|
||||||
|
{
|
||||||
|
isHTTP = true;
|
||||||
|
}
|
||||||
else if(!strncmp("file://", filename, 7))
|
else if(!strncmp("file://", filename, 7))
|
||||||
{
|
{
|
||||||
isHTTP = false;
|
isHTTP = false;
|
||||||
@@ -397,18 +560,20 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
|
|||||||
{
|
{
|
||||||
isHTTP = true;
|
isHTTP = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
strcat(file, "file://");
|
|
||||||
|
|
||||||
strcat(file, filename);
|
|
||||||
|
|
||||||
if (isHTTP)
|
if (isHTTP)
|
||||||
uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true);
|
uri = g_strdup_printf ("%s", filename);
|
||||||
else
|
else
|
||||||
uri = g_filename_to_uri(filename, NULL, NULL);
|
uri = g_filename_to_uri(filename, NULL, NULL);
|
||||||
|
|
||||||
lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename);
|
lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename);
|
||||||
|
|
||||||
|
guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | \
|
||||||
|
GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO;
|
||||||
|
|
||||||
|
/* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */
|
||||||
|
int m_buffer_size = 5*1024*1024;
|
||||||
|
|
||||||
// create gst pipeline
|
// create gst pipeline
|
||||||
m_gst_playbin = gst_element_factory_make ("playbin", "playbin");
|
m_gst_playbin = gst_element_factory_make ("playbin", "playbin");
|
||||||
|
|
||||||
@@ -416,26 +581,40 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
|
|||||||
{
|
{
|
||||||
lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__);
|
lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__);
|
||||||
|
|
||||||
guint flags;
|
if(isHTTP)
|
||||||
g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL);
|
{
|
||||||
/* avoid video conversion, let the (hardware) sinks handle that */
|
g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), this);
|
||||||
flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
|
|
||||||
/* volume control is done by hardware */
|
// set buffer size
|
||||||
flags &= ~GST_PLAY_FLAG_SOFT_VOLUME;
|
g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL);
|
||||||
|
g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL);
|
||||||
|
flags |= GST_PLAY_FLAG_BUFFERING;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL);
|
||||||
|
|
||||||
g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL);
|
g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL);
|
||||||
g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL);
|
|
||||||
|
|
||||||
//gstbus handler
|
//gstbus handler
|
||||||
GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) );
|
GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) );
|
||||||
gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL);
|
gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL);
|
||||||
gst_object_unref(bus);
|
gst_object_unref(bus);
|
||||||
|
|
||||||
|
first = true;
|
||||||
|
|
||||||
// state playing
|
// state playing
|
||||||
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
|
if(isHTTP)
|
||||||
|
{
|
||||||
|
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING);
|
||||||
|
playstate = STATE_PLAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PAUSED);
|
||||||
|
playstate = STATE_PAUSE;
|
||||||
|
}
|
||||||
|
|
||||||
playing = true;
|
playing = true;
|
||||||
playstate = STATE_PLAY;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -447,12 +626,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
|
|||||||
|
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
// set buffer size
|
|
||||||
/* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */
|
|
||||||
int m_buffer_size = 5*1024*1024;
|
|
||||||
//g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL);
|
|
||||||
g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,7 +669,7 @@ bool cPlayback::Stop(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPlayback::SetAPid(int pid , bool /*ac3*/)
|
bool cPlayback::SetAPid(int pid, bool /*ac3*/)
|
||||||
{
|
{
|
||||||
lt_info("%s: pid %i\n", __func__, pid);
|
lt_info("%s: pid %i\n", __func__, pid);
|
||||||
|
|
||||||
@@ -514,25 +687,17 @@ bool cPlayback::SetAPid(int pid , bool /*ac3*/)
|
|||||||
|
|
||||||
void cPlayback::trickSeek(int ratio)
|
void cPlayback::trickSeek(int ratio)
|
||||||
{
|
{
|
||||||
bool validposition = false;
|
GstFormat fmt = GST_FORMAT_TIME;
|
||||||
gint64 pos = 0;
|
gint64 pos = 0;
|
||||||
int position;
|
|
||||||
int duration;
|
|
||||||
|
|
||||||
if( GetPosition(position, duration) )
|
|
||||||
{
|
|
||||||
validposition = true;
|
|
||||||
pos = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
|
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
|
||||||
|
|
||||||
if (validposition)
|
if (gst_element_query_position(m_gst_playbin, fmt, &pos))
|
||||||
{
|
{
|
||||||
if(ratio >= 0.0)
|
if(ratio >= 0.0)
|
||||||
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1);
|
gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1);
|
||||||
else
|
else
|
||||||
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
|
gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,6 +739,12 @@ bool cPlayback::SetSpeed(int speed)
|
|||||||
//
|
//
|
||||||
playstate = STATE_REW;
|
playstate = STATE_REW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (init_jump > -1)
|
||||||
|
{
|
||||||
|
SetPosition(init_jump,true);
|
||||||
|
init_jump = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpeed = speed;
|
mSpeed = speed;
|
||||||
@@ -624,13 +795,21 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
|||||||
{
|
{
|
||||||
//position
|
//position
|
||||||
GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
|
GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
|
||||||
|
|
||||||
gint64 pts = 0;
|
gint64 pts = 0;
|
||||||
unsigned long long int sec = 0;
|
if (audioSink || videoSink)
|
||||||
|
{
|
||||||
gst_element_query_position(m_gst_playbin, fmt, &pts);
|
g_signal_emit_by_name(audioSink ? audioSink : videoSink, "get-decoder-time", &pts);
|
||||||
|
if (!GST_CLOCK_TIME_IS_VALID(pts))
|
||||||
|
{
|
||||||
|
lt_info( "%s - %d failed\n", __FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!gst_element_query_position(m_gst_playbin, fmt, &pts))
|
||||||
|
lt_info( "%s - %d failed\n", __FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
position = pts / 1000000.0;
|
position = pts / 1000000.0;
|
||||||
|
|
||||||
// duration
|
// duration
|
||||||
GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs
|
GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs
|
||||||
double length = 0;
|
double length = 0;
|
||||||
@@ -651,19 +830,32 @@ 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, playing);
|
||||||
|
|
||||||
if(playing == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
gint64 time_nanoseconds;
|
gint64 time_nanoseconds;
|
||||||
gint64 pos;
|
gint64 pos;
|
||||||
GstFormat fmt = GST_FORMAT_TIME;
|
GstFormat fmt = GST_FORMAT_TIME;
|
||||||
|
GstState state;
|
||||||
|
|
||||||
if(m_gst_playbin)
|
if(m_gst_playbin)
|
||||||
|
{
|
||||||
|
gst_element_get_state(m_gst_playbin, &state, NULL, GST_CLOCK_TIME_NONE);
|
||||||
|
|
||||||
|
if ( (state == GST_STATE_PAUSED) && first)
|
||||||
|
{
|
||||||
|
init_jump = position;
|
||||||
|
first = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!absolute)
|
||||||
{
|
{
|
||||||
gst_element_query_position(m_gst_playbin, fmt, &pos);
|
gst_element_query_position(m_gst_playbin, fmt, &pos);
|
||||||
time_nanoseconds = pos + (position * 1000000.0);
|
time_nanoseconds = pos + (position * 1000000.0);
|
||||||
if(time_nanoseconds < 0)
|
if(time_nanoseconds < 0)
|
||||||
time_nanoseconds = 0;
|
time_nanoseconds = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_nanoseconds = position * 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
|
gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
|
||||||
}
|
}
|
||||||
@@ -678,32 +870,34 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
|||||||
if(m_gst_playbin)
|
if(m_gst_playbin)
|
||||||
{
|
{
|
||||||
gint i, n_audio = 0;
|
gint i, n_audio = 0;
|
||||||
//GstStructure * structure = NULL;
|
|
||||||
|
|
||||||
// get audio
|
// get audio
|
||||||
g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
|
g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
|
||||||
printf("%s: %d audio\n", __FUNCTION__, n_audio);
|
lt_info("%s: %d audio\n", __FUNCTION__, n_audio);
|
||||||
|
|
||||||
if(n_audio == 0)
|
if(n_audio == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
language->clear();
|
||||||
|
|
||||||
for (i = 0; i < n_audio; i++)
|
for (i = 0; i < n_audio; i++)
|
||||||
{
|
{
|
||||||
// apids
|
// apids
|
||||||
apids[i]=i;
|
apids[i]= real_apids[i] ? real_apids[i] : i;
|
||||||
|
|
||||||
GstPad * pad = 0;
|
GstPad * pad = 0;
|
||||||
g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
|
g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
|
||||||
|
|
||||||
GstCaps * caps = gst_pad_get_current_caps(pad);
|
GstCaps * caps = gst_pad_get_current_caps(pad);
|
||||||
|
gst_object_unref(pad);
|
||||||
|
|
||||||
if (!caps)
|
if (!caps)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
||||||
//const gchar *g_type = gst_structure_get_name(structure);
|
GstTagList * tags = NULL;
|
||||||
|
gchar * g_lang = NULL;
|
||||||
//if (!structure)
|
gchar * g_codec = NULL;
|
||||||
//return atUnknown;
|
|
||||||
//ac3flags[0] = 0;
|
|
||||||
|
|
||||||
// ac3flags
|
// ac3flags
|
||||||
if ( gst_structure_has_name (structure, "audio/mpeg"))
|
if ( gst_structure_has_name (structure, "audio/mpeg"))
|
||||||
@@ -711,23 +905,11 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
|||||||
gint mpegversion, layer = -1;
|
gint mpegversion, layer = -1;
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
|
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
|
||||||
//return atUnknown;
|
|
||||||
ac3flags[i] = 0;
|
ac3flags[i] = 0;
|
||||||
|
|
||||||
switch (mpegversion)
|
switch (mpegversion)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
/*
|
|
||||||
{
|
|
||||||
gst_structure_get_int (structure, "layer", &layer);
|
|
||||||
if ( layer == 3 )
|
|
||||||
return atMP3;
|
|
||||||
else
|
|
||||||
return atMPEG;
|
|
||||||
ac3flags[0] = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
ac3flags[i] = 4;
|
ac3flags[i] = 4;
|
||||||
case 2:
|
case 2:
|
||||||
//return atAAC;
|
//return atAAC;
|
||||||
@@ -751,9 +933,29 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
|||||||
ac3flags[i] = 0;
|
ac3flags[i] = 0;
|
||||||
|
|
||||||
gst_caps_unref(caps);
|
gst_caps_unref(caps);
|
||||||
}
|
|
||||||
|
|
||||||
// numpids
|
//(ac3flags[i] > 2) ? ac3flags[i] = 1 : ac3flags[i] = 0;
|
||||||
|
|
||||||
|
g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags);
|
||||||
|
if (tags && GST_IS_TAG_LIST(tags))
|
||||||
|
{
|
||||||
|
if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
|
||||||
|
{
|
||||||
|
std::string slang;
|
||||||
|
if (gst_tag_check_language_code(g_lang))
|
||||||
|
slang = gst_tag_get_language_name(g_lang);
|
||||||
|
else
|
||||||
|
slang = g_lang;
|
||||||
|
if (slang.empty())
|
||||||
|
language[i] = "unk";
|
||||||
|
else
|
||||||
|
language[i] = slang.c_str();
|
||||||
|
lt_info("%s: language:%s\n", __FUNCTION__, language[i].c_str());
|
||||||
|
g_free(g_lang);
|
||||||
|
}
|
||||||
|
gst_tag_list_free(tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
*numpida=i;
|
*numpida=i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,6 +1002,62 @@ void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::str
|
|||||||
{
|
{
|
||||||
keys.clear();
|
keys.clear();
|
||||||
values.clear();
|
values.clear();
|
||||||
|
if (gst_tag_list_is_empty (m_stream_tags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (guint i = 0, icnt = gst_tag_list_n_tags(m_stream_tags); i < icnt; i++)
|
||||||
|
{
|
||||||
|
const gchar *name = gst_tag_list_nth_tag_name(m_stream_tags, i);
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (guint j = 0, jcnt = gst_tag_list_get_tag_size(m_stream_tags, name); j < jcnt; j++)
|
||||||
|
{
|
||||||
|
const GValue *val;
|
||||||
|
|
||||||
|
val = gst_tag_list_get_value_index(m_stream_tags, name, j);
|
||||||
|
|
||||||
|
if (G_VALUE_HOLDS_STRING(val))
|
||||||
|
{
|
||||||
|
keys.push_back(name);
|
||||||
|
values.push_back(g_value_get_string(val));
|
||||||
|
}
|
||||||
|
else if (G_VALUE_HOLDS_UINT(val))
|
||||||
|
{
|
||||||
|
char buffer [50];
|
||||||
|
keys.push_back(name);
|
||||||
|
sprintf (buffer, "%u", g_value_get_uint(val));
|
||||||
|
values.push_back(buffer);
|
||||||
|
}
|
||||||
|
else if (G_VALUE_HOLDS_DOUBLE(val))
|
||||||
|
{
|
||||||
|
char buffer [50];
|
||||||
|
keys.push_back(name);
|
||||||
|
sprintf (buffer, "%f", g_value_get_double(val));
|
||||||
|
values.push_back(buffer);
|
||||||
|
}
|
||||||
|
else if (G_VALUE_HOLDS_BOOLEAN(val))
|
||||||
|
{
|
||||||
|
keys.push_back(name);
|
||||||
|
values.push_back(g_value_get_boolean(val) ? "true" : "false");
|
||||||
|
}
|
||||||
|
else if (GST_VALUE_HOLDS_DATE_TIME(val))
|
||||||
|
{
|
||||||
|
GstDateTime *dt = (GstDateTime *) g_value_get_boxed(val);
|
||||||
|
keys.push_back(name);
|
||||||
|
values.push_back(gst_date_time_to_iso8601_string(dt));
|
||||||
|
}
|
||||||
|
else if (G_VALUE_HOLDS(val, G_TYPE_DATE))
|
||||||
|
{
|
||||||
|
keys.push_back(name);
|
||||||
|
values.push_back(gst_value_serialize(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("%s:%s %d tags found\n", FILENAME, __func__, (int)keys.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
|
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
|
||||||
@@ -830,3 +1088,33 @@ uint64_t cPlayback::GetReadCount()
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cPlayback::GetAPid(void)
|
||||||
|
{
|
||||||
|
gint current_audio = 0;
|
||||||
|
g_object_get (m_gst_playbin, "current-audio", ¤t_audio, NULL);
|
||||||
|
lt_info("%s: %d audio\n", __FUNCTION__, current_audio);
|
||||||
|
return current_audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cPlayback::GetVPid(void)
|
||||||
|
{
|
||||||
|
gint current_video = 0;
|
||||||
|
g_object_get (m_gst_playbin, "current-video", ¤t_video, NULL);
|
||||||
|
lt_info("%s: %d video\n", __FUNCTION__, current_video);
|
||||||
|
return current_video;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cPlayback::GetSubtitlePid(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFormatContext *cPlayback::GetAVFormatContext()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cPlayback::ReleaseAVFormatContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@@ -36,8 +36,8 @@ typedef struct hw_caps
|
|||||||
display_type_t display_type;
|
display_type_t display_type;
|
||||||
int display_xres; /* x resolution or chars per line */
|
int display_xres; /* x resolution or chars per line */
|
||||||
int display_yres;
|
int display_yres;
|
||||||
int display_can_deepstandby;
|
|
||||||
int display_can_set_brightness;
|
int display_can_set_brightness;
|
||||||
|
int display_can_deepstandby;
|
||||||
char boxvendor[64];
|
char boxvendor[64];
|
||||||
char boxname[64];
|
char boxname[64];
|
||||||
char boxarch[64];
|
char boxarch[64];
|
||||||
|
@@ -40,7 +40,7 @@ inline void cs_api_exit()
|
|||||||
#define cs_free_uncached free
|
#define cs_free_uncached free
|
||||||
|
|
||||||
// Callback function helpers
|
// Callback function helpers
|
||||||
static inline void cs_register_messenger(cs_messenger) { return; };
|
void cs_register_messenger(cs_messenger messenger);
|
||||||
static inline void cs_deregister_messenger(void) { return; };
|
static inline void cs_deregister_messenger(void) { return; };
|
||||||
//cs_messenger cs_get_messenger(void);
|
//cs_messenger cs_get_messenger(void);
|
||||||
|
|
||||||
|
@@ -29,12 +29,11 @@ hw_caps_t *get_hwcaps(void)
|
|||||||
memset(&caps, 0, sizeof(hw_caps_t));
|
memset(&caps, 0, sizeof(hw_caps_t));
|
||||||
|
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
caps.has_CI = 0;
|
caps.has_CI = 1;
|
||||||
caps.can_cec = 1;
|
caps.can_cec = 1;
|
||||||
caps.can_shutdown = 1;
|
caps.can_shutdown = 1;
|
||||||
caps.display_xres = 16;
|
caps.display_xres = 16;
|
||||||
caps.display_type = HW_DISPLAY_LINE_TEXT;
|
caps.display_type = HW_DISPLAY_LINE_TEXT;
|
||||||
caps.display_can_deepstandby = 0;
|
|
||||||
caps.display_can_set_brightness = 1;
|
caps.display_can_set_brightness = 1;
|
||||||
caps.has_HDMI = 1;
|
caps.has_HDMI = 1;
|
||||||
strcpy(caps.boxvendor, "AX-Technologies");
|
strcpy(caps.boxvendor, "AX-Technologies");
|
||||||
|
@@ -30,7 +30,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
|
|
||||||
#include "dmx_lib.h"
|
|
||||||
#include "audio_lib.h"
|
#include "audio_lib.h"
|
||||||
#include "video_lib.h"
|
#include "video_lib.h"
|
||||||
|
|
||||||
@@ -42,11 +41,9 @@
|
|||||||
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_PLAYBACK, NULL, args)
|
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_PLAYBACK, NULL, args)
|
||||||
#define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args)
|
#define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args)
|
||||||
|
|
||||||
static const char * FILENAME = "[playback.cpp]";
|
static const char * FILENAME = "[playback_gst.cpp]";
|
||||||
extern cVideo * videoDecoder;
|
extern cVideo * videoDecoder;
|
||||||
extern cAudio * audioDecoder;
|
extern cAudio * audioDecoder;
|
||||||
extern cDemux * audioDemux;
|
|
||||||
extern cDemux * videoDemux;
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/tag/tag.h>
|
#include <gst/tag/tag.h>
|
||||||
@@ -111,7 +108,7 @@ void processMpegTsSection(GstMpegtsSection* section)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data)
|
void playbinNotifySource(GObject *object, GParamSpec *param_spec, gpointer user_data)
|
||||||
{
|
{
|
||||||
GstElement *source = NULL;
|
GstElement *source = NULL;
|
||||||
cPlayback *_this = (cPlayback*)user_data;
|
cPlayback *_this = (cPlayback*)user_data;
|
||||||
@@ -189,7 +186,7 @@ void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
GstBusSyncReply Gst_bus_call(GstBus *bus, GstMessage *msg, gpointer user_data)
|
||||||
{
|
{
|
||||||
gchar * sourceName;
|
gchar * sourceName;
|
||||||
|
|
||||||
@@ -672,13 +669,19 @@ bool cPlayback::SetAPid(int pid, bool /*ac3*/)
|
|||||||
{
|
{
|
||||||
lt_info("%s: pid %i\n", __func__, pid);
|
lt_info("%s: pid %i\n", __func__, pid);
|
||||||
|
|
||||||
int current_audio;
|
int to_audio = pid;
|
||||||
|
|
||||||
if(pid != mAudioStream)
|
for (unsigned int i = 0; i < REC_MAX_APIDS; i++) {
|
||||||
|
if (real_apids[i])
|
||||||
|
if (real_apids[i] == pid)
|
||||||
|
to_audio = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(to_audio != mAudioStream)
|
||||||
{
|
{
|
||||||
g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL);
|
g_object_set (G_OBJECT (m_gst_playbin), "current-audio", to_audio, NULL);
|
||||||
printf("%s: switched to audio stream %i\n", __FUNCTION__, pid);
|
printf("%s: switched to audio stream %i\n", __FUNCTION__, to_audio);
|
||||||
mAudioStream = pid;
|
mAudioStream = to_audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -901,12 +904,11 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
|||||||
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
||||||
GstTagList * tags = NULL;
|
GstTagList * tags = NULL;
|
||||||
gchar * g_lang = NULL;
|
gchar * g_lang = NULL;
|
||||||
gchar * g_codec = NULL;
|
|
||||||
|
|
||||||
// ac3flags
|
// ac3flags
|
||||||
if ( gst_structure_has_name (structure, "audio/mpeg"))
|
if ( gst_structure_has_name (structure, "audio/mpeg"))
|
||||||
{
|
{
|
||||||
gint mpegversion, layer = -1;
|
gint mpegversion;
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
|
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
|
||||||
ac3flags[i] = 0;
|
ac3flags[i] = 0;
|
||||||
@@ -945,7 +947,15 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
|||||||
{
|
{
|
||||||
if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
|
if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
|
||||||
{
|
{
|
||||||
language[i] = std::string(gst_tag_get_language_name(g_lang)).c_str();
|
std::string slang;
|
||||||
|
if (gst_tag_check_language_code(g_lang))
|
||||||
|
slang = gst_tag_get_language_name(g_lang);
|
||||||
|
else
|
||||||
|
slang = g_lang;
|
||||||
|
if (slang.empty())
|
||||||
|
language[i] = "unk";
|
||||||
|
else
|
||||||
|
language[i] = slang.c_str();
|
||||||
lt_info("%s: language:%s\n", __FUNCTION__, language[i].c_str());
|
lt_info("%s: language:%s\n", __FUNCTION__, language[i].c_str());
|
||||||
g_free(g_lang);
|
g_free(g_lang);
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1100,7 @@ int cPlayback::GetAPid(void)
|
|||||||
gint current_audio = 0;
|
gint current_audio = 0;
|
||||||
g_object_get (m_gst_playbin, "current-audio", ¤t_audio, NULL);
|
g_object_get (m_gst_playbin, "current-audio", ¤t_audio, NULL);
|
||||||
lt_info("%s: %d audio\n", __FUNCTION__, current_audio);
|
lt_info("%s: %d audio\n", __FUNCTION__, current_audio);
|
||||||
return current_audio;
|
return real_apids[current_audio] ? real_apids[current_audio] : current_audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cPlayback::GetVPid(void)
|
int cPlayback::GetVPid(void)
|
||||||
|
@@ -994,8 +994,10 @@ void cVideo::SetCECState(bool state)
|
|||||||
usleep(10000);
|
usleep(10000);
|
||||||
message.address = 0x0f; /* broadcast */
|
message.address = 0x0f; /* broadcast */
|
||||||
message.data[0] = CEC_MSG_ACTIVE_SOURCE;
|
message.data[0] = CEC_MSG_ACTIVE_SOURCE;
|
||||||
message.data[1] = ((((int)physicalAddress >> 12) & 0xf) << 4) + (((int)physicalAddress >> 8) & 0xf);
|
//message.data[1] = ((((int)physicalAddress >> 12) & 0xf) << 4) + (((int)physicalAddress >> 8) & 0xf);
|
||||||
message.data[2] = ((((int)physicalAddress >> 4) & 0xf) << 4) + (((int)physicalAddress >> 0) & 0xf);
|
//message.data[2] = ((((int)physicalAddress >> 4) & 0xf) << 4) + (((int)physicalAddress >> 0) & 0xf);
|
||||||
|
message.data[1] = physicalAddress[0];
|
||||||
|
message.data[2] = physicalAddress[1];
|
||||||
message.length = 3;
|
message.length = 3;
|
||||||
SendCECMessage(message);
|
SendCECMessage(message);
|
||||||
}
|
}
|
||||||
|
@@ -3,25 +3,106 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <linux/dvb/ca.h>
|
#include <linux/dvb/ca.h>
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "descrambler.h"
|
#include "descrambler.h"
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
static const char * FILENAME = "[descrambler]";
|
static const char * FILENAME = "[descrambler]";
|
||||||
|
|
||||||
static const char *descrambler_filename = "/dev/dvb/adapter0/ca3";
|
|
||||||
static int desc_fd = -1;
|
static int desc_fd = -1;
|
||||||
static int desc_user_count = 0;
|
static int desc_user_count = 0;
|
||||||
|
|
||||||
|
#if HAVE_ARM_HARDWARE
|
||||||
|
|
||||||
|
//static const char *descrambler_filename = "/dev/dvb/adapter0/ca0";
|
||||||
|
//static const char *descrambler_filename = "/dev/dvb/adapter0/ca1";
|
||||||
|
static const char *descrambler_filename = "/dev/ciplus_ca0";
|
||||||
|
|
||||||
|
enum ca_descr_data_type {
|
||||||
|
CA_DATA_IV,
|
||||||
|
CA_DATA_KEY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ca_descr_parity {
|
||||||
|
CA_PARITY_EVEN,
|
||||||
|
CA_PARITY_ODD,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ca_descr_data {
|
||||||
|
unsigned int index;
|
||||||
|
enum ca_descr_parity parity;
|
||||||
|
enum ca_descr_data_type data_type;
|
||||||
|
unsigned int length;
|
||||||
|
unsigned char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CA_SET_DESCR_DATA _IOW('o', 137, struct ca_descr_data)
|
||||||
|
//#define CA_SET_DESCR_DATA _IOW('o', 10, struct ca_descr_data)
|
||||||
|
|
||||||
|
int descrambler_set_key(int index, int parity, unsigned char *data)
|
||||||
|
{
|
||||||
|
struct ca_descr_data d;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("%s -> %s %s\n", FILENAME, __FUNCTION__, descrambler_filename);
|
||||||
|
|
||||||
|
if (descrambler_open())
|
||||||
|
{
|
||||||
|
printf("Complete Data-> Index: (%d) Parity: (%d) -> ", index, parity);
|
||||||
|
hexdump(data, 32);
|
||||||
|
|
||||||
|
d.index = index;
|
||||||
|
d.parity = (ca_descr_parity)parity;
|
||||||
|
d.data_type = CA_DATA_KEY;
|
||||||
|
d.length = 16;
|
||||||
|
d.data = data;
|
||||||
|
|
||||||
|
printf("AES Index: (%d) Parity: (%d) -> ", d.index, d.parity);
|
||||||
|
hexdump(d.data, 16);
|
||||||
|
|
||||||
|
ret = ioctl(desc_fd, CA_SET_DESCR_DATA, &d);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
printf("CA_SET_DESCR_DATA (AES) index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
d.index = index;
|
||||||
|
d.parity = (ca_descr_parity)parity;
|
||||||
|
d.data_type = CA_DATA_IV;
|
||||||
|
d.length = 16;
|
||||||
|
d.data = data + 16;
|
||||||
|
|
||||||
|
printf("IV Index: (%d) Parity: (%d) -> ", d.index, d.parity);
|
||||||
|
hexdump(d.data, 16);
|
||||||
|
|
||||||
|
ret = ioctl(desc_fd, CA_SET_DESCR_DATA, &d);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
printf("CA_SET_DESCR_DATA (IV) index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
descrambler_close();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static const char *descrambler_filename = "/dev/dvb/adapter0/ca3";
|
||||||
|
|
||||||
/* Byte 0 to 15 are AES Key, Byte 16 to 31 are IV */
|
/* Byte 0 to 15 are AES Key, Byte 16 to 31 are IV */
|
||||||
|
|
||||||
int descrambler_set_key(int index, int parity, unsigned char *data)
|
int descrambler_set_key(int index, int parity, unsigned char *data)
|
||||||
{
|
{
|
||||||
struct ca_descr_data d;
|
struct ca_descr_data d;
|
||||||
|
|
||||||
printf("%s -> %s\n", FILENAME, __FUNCTION__);
|
printf("%s -> %s %s\n", FILENAME, __FUNCTION__, descrambler_filename);
|
||||||
|
|
||||||
index |= 0x100;
|
index |= 0x100;
|
||||||
|
|
||||||
@@ -32,37 +113,55 @@ int descrambler_set_key(int index, int parity, unsigned char *data)
|
|||||||
d.data_type = CA_DATA_KEY;
|
d.data_type = CA_DATA_KEY;
|
||||||
d.length = 32;
|
d.length = 32;
|
||||||
d.data = data;
|
d.data = data;
|
||||||
|
#if 0
|
||||||
|
printf("Index: %d Parity: (%d) -> ", d.index, d.parity);
|
||||||
|
hexdump(d.data, 32);
|
||||||
|
#endif
|
||||||
|
if (ioctl(desc_fd, CA_SET_DESCR_DATA, &d))
|
||||||
|
{
|
||||||
|
printf("CA_SET_DESCR_DATA index=%d parity=%d (errno=%d %s)\n", index, parity, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
printf("Index: %d Parity: (%d) -> ", d.index, d.parity);
|
printf("Index: %d Parity: (%d) -> ", d.index, d.parity);
|
||||||
hexdump(d.data, 32);
|
hexdump(d.data, 32);
|
||||||
|
|
||||||
if (ioctl(desc_fd, CA_SET_DESCR_DATA, &d))
|
|
||||||
{
|
|
||||||
//printf("CA_SET_DESCR_DATA\n");
|
|
||||||
}
|
|
||||||
descrambler_close();
|
descrambler_close();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* we don't use this for sh4 ci cam ! */
|
||||||
|
|
||||||
/* we don't use this for ci cam ! */
|
|
||||||
/*
|
|
||||||
int descrambler_set_pid(int index, int enable, int pid)
|
int descrambler_set_pid(int index, int enable, int pid)
|
||||||
{
|
{
|
||||||
struct ca_pid p;
|
struct ca_pid p;
|
||||||
|
#if HAVE_ARM_HARDWARE
|
||||||
|
unsigned int flags = 0x80;
|
||||||
|
|
||||||
|
if (index)
|
||||||
|
flags |= 0x40;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
p.index = index;
|
flags |= 0x20;
|
||||||
else
|
|
||||||
p.index = -1;
|
|
||||||
|
|
||||||
|
p.index = flags;
|
||||||
p.pid = pid;
|
p.pid = pid;
|
||||||
|
#else
|
||||||
|
p.index = index;
|
||||||
|
if (enable)
|
||||||
|
p.pid = pid;
|
||||||
|
else
|
||||||
|
p.pid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ioctl(desc_fd, CA_SET_PID, &p))
|
printf("CA_SET_PID pid=0x%04x index=0x%04x\n", p.pid, p.index);
|
||||||
printf("CA_SET_PID\n");
|
if (ioctl(desc_fd, CA_SET_PID, &p) == -1)
|
||||||
|
printf("CA_SET_PID pid=0x%04x index=0x%04x (errno=%d %s)\n", p.pid, p.index, errno, strerror(errno));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
bool descrambler_open(void)
|
bool descrambler_open(void)
|
||||||
{
|
{
|
||||||
@@ -74,12 +173,6 @@ bool descrambler_open(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void descrambler_close(void)
|
|
||||||
{
|
|
||||||
close(desc_fd);
|
|
||||||
desc_fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int descrambler_init(void)
|
int descrambler_init(void)
|
||||||
{
|
{
|
||||||
desc_user_count++;
|
desc_user_count++;
|
||||||
@@ -87,6 +180,12 @@ int descrambler_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void descrambler_close(void)
|
||||||
|
{
|
||||||
|
close(desc_fd);
|
||||||
|
desc_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
void descrambler_deinit(void)
|
void descrambler_deinit(void)
|
||||||
{
|
{
|
||||||
desc_user_count--;
|
desc_user_count--;
|
||||||
|
@@ -6,7 +6,7 @@ void descrambler_deinit(void);
|
|||||||
bool descrambler_open(void);
|
bool descrambler_open(void);
|
||||||
void descrambler_close(void);
|
void descrambler_close(void);
|
||||||
int descrambler_set_key(int index, int parity, unsigned char *data);
|
int descrambler_set_key(int index, int parity, unsigned char *data);
|
||||||
/* we don't use this for ci cam ! */
|
/* we don't use this for sh4 ci cam ! */
|
||||||
//int descrambler_set_pid(int index, int enable, int pid);
|
int descrambler_set_pid(int index, int enable, int pid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1347,6 +1347,38 @@ void eDVBCIContentControlManagerSession::resendKey(eDVBCISlot *tslot)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (!tslot->SidBlackListed && (tslot->recordUse[0] || tslot->liveUse[0]))
|
if (!tslot->SidBlackListed && (tslot->recordUse[0] || tslot->liveUse[0]))
|
||||||
|
{
|
||||||
|
#if HAVE_ARM_HARDWARE
|
||||||
|
if (slot->newPids)
|
||||||
|
{
|
||||||
|
if (slot->pids.size())
|
||||||
|
{
|
||||||
|
if (descrambler_open())
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < slot->pids.size(); i++)
|
||||||
|
descrambler_set_pid((int)tslot->slot, 1, (int) slot->pids[i]);
|
||||||
|
descrambler_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slot->newPids = false;
|
||||||
|
}
|
||||||
|
descrambler_set_key((int)tslot->slot, tslot->lastParity, tslot->lastKey);
|
||||||
|
#else
|
||||||
|
if (slot->newPids)
|
||||||
|
{
|
||||||
|
if (slot->pids.size())
|
||||||
|
{
|
||||||
|
if (descrambler_open())
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < slot->pids.size(); i++)
|
||||||
|
descrambler_set_pid((int)tslot->slot, 1, (int) slot->pids[i]);
|
||||||
|
descrambler_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slot->newPids = false;
|
||||||
|
}
|
||||||
descrambler_set_key((int)tslot->source, tslot->lastParity, tslot->lastKey);
|
descrambler_set_key((int)tslot->source, tslot->lastParity, tslot->lastKey);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,6 +51,7 @@ int eDVBCIMMISession::receivedAPDU(const unsigned char *tag, const void *data, i
|
|||||||
pMsg->MsgId = CA_MESSAGE_MSG_MMI_CLOSE;
|
pMsg->MsgId = CA_MESSAGE_MSG_MMI_CLOSE;
|
||||||
pMsg->SlotType = CA_SLOT_TYPE_CI;
|
pMsg->SlotType = CA_SLOT_TYPE_CI;
|
||||||
pMsg->Slot = slot->slot;
|
pMsg->Slot = slot->slot;
|
||||||
|
stopMMI();
|
||||||
cCA::GetInstance()->SendMessage(pMsg);
|
cCA::GetInstance()->SendMessage(pMsg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#define SLMS 256
|
#define SLMS 256
|
||||||
|
|
||||||
#define ROOT_CERT "/etc/pem/root.pem"
|
#define ROOT_CERT "/etc/ssl/certs/root.pem"
|
||||||
#define CUSTOMER_CERT "/etc/pem/customer.pem"
|
#define CUSTOMER_CERT "/etc/ssl/certs/customer.pem"
|
||||||
#define DEVICE_CERT "/etc/pem/device.pem"
|
#define DEVICE_CERT "/etc/ssl/certs/device.pem"
|
||||||
|
|
||||||
class eDVBCISession
|
class eDVBCISession
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user