media: dvb: Add events API for demux
user-space programs using demux require to be notified on several kinds of events such new PES event, new section event, new recording-chunk event and other error events. demux API was extended to meet this requirement Change-Id: I768b6acde346139e194a3e6637b6fc0fc9648446 Signed-off-by: Hamad Kadmany <hkadmany@codeaurora.org>
This commit is contained in:
committed by
Stephen Boyd
parent
9ddbbe478f
commit
24dffcb5c8
@@ -64,6 +64,8 @@
|
||||
|
||||
enum dmx_success {
|
||||
DMX_OK = 0, /* Received Ok */
|
||||
DMX_OK_PES_END, /* Received ok, data reached end of PES packet */
|
||||
DMX_OK_PCR, /* Received OK, data with new PCR/STC pair */
|
||||
DMX_LENGTH_ERROR, /* Incorrect length */
|
||||
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
|
||||
DMX_CRC_ERROR, /* Incorrect CRC */
|
||||
@@ -72,6 +74,41 @@ enum dmx_success {
|
||||
DMX_MISSED_ERROR /* Receiver missed packet */
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
* struct dmx_data_ready: Parameters for event notification callback.
|
||||
* Event notification notifies demux device that data is written
|
||||
* and available in the device's output buffer or provides
|
||||
* notification on errors and other events. In the latter case
|
||||
* data_length is zero.
|
||||
*/
|
||||
struct dmx_data_ready {
|
||||
enum dmx_success status;
|
||||
|
||||
/*
|
||||
* data_length may be 0 in case of DMX_OK_PES_END
|
||||
* and in non-DMX_OK_XXX events. In DMX_OK_PES_END,
|
||||
* data_length is for data comming after the end of PES.
|
||||
*/
|
||||
int data_length;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int start_gap;
|
||||
int actual_length;
|
||||
int disc_indicator_set;
|
||||
int pes_length_mismatch;
|
||||
u64 stc;
|
||||
} pes_end;
|
||||
|
||||
struct {
|
||||
u64 pcr;
|
||||
u64 stc;
|
||||
int disc_indicator_set;
|
||||
} pcr;
|
||||
};
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* TS packet reception */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -123,6 +160,10 @@ enum dmx_ts_pes
|
||||
#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0
|
||||
#define DMX_TS_PES_PCR DMX_TS_PES_PCR0
|
||||
|
||||
struct dmx_ts_feed;
|
||||
typedef int (*dmx_ts_data_ready_cb)(
|
||||
struct dmx_ts_feed *source,
|
||||
struct dmx_data_ready *dmx_data_ready);
|
||||
|
||||
struct dmx_ts_feed {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
@@ -141,6 +182,8 @@ struct dmx_ts_feed {
|
||||
int (*get_decoder_buff_status)(
|
||||
struct dmx_ts_feed *feed,
|
||||
struct dmx_buffer_status *dmx_buffer_status);
|
||||
int (*data_ready_cb)(struct dmx_ts_feed *feed,
|
||||
dmx_ts_data_ready_cb callback);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -155,6 +198,11 @@ struct dmx_section_filter {
|
||||
void* priv; /* Pointer to private data of the API client */
|
||||
};
|
||||
|
||||
struct dmx_section_feed;
|
||||
typedef int (*dmx_section_data_ready_cb)(
|
||||
struct dmx_section_filter *source,
|
||||
struct dmx_data_ready *dmx_data_ready);
|
||||
|
||||
struct dmx_section_feed {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
struct dmx_demux* parent; /* Back-pointer */
|
||||
@@ -177,6 +225,8 @@ struct dmx_section_feed {
|
||||
struct dmx_section_filter* filter);
|
||||
int (*start_filtering) (struct dmx_section_feed* feed);
|
||||
int (*stop_filtering) (struct dmx_section_feed* feed);
|
||||
int (*data_ready_cb)(struct dmx_section_feed *feed,
|
||||
dmx_section_data_ready_cb callback);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,35 @@ struct dmxdev_feed {
|
||||
struct list_head next;
|
||||
};
|
||||
|
||||
struct dmxdev_events_queue {
|
||||
#define DMX_EVENT_QUEUE_SIZE 500 /* number of events */
|
||||
/*
|
||||
* indices used to manage events queue.
|
||||
* read_index advanced when relevent data is read
|
||||
* from the buffer.
|
||||
* notified_index is the index from which next events
|
||||
* are returned.
|
||||
* read_index <= notified_index <= write_index
|
||||
*
|
||||
* If user reads the data without getting the respective
|
||||
* event first, the read/notified indices are updated
|
||||
* automatically to reflect the actual data that exist
|
||||
* in the buffer.
|
||||
*/
|
||||
u32 read_index;
|
||||
u32 write_index;
|
||||
u32 notified_index;
|
||||
|
||||
/* Bytes read by user without having respective event in the queue */
|
||||
u32 bytes_read_no_event;
|
||||
|
||||
/* internal tracking of PES and recording events */
|
||||
u32 current_event_data_size;
|
||||
u32 current_event_start_offset;
|
||||
|
||||
struct dmx_filter_event queue[DMX_EVENT_QUEUE_SIZE];
|
||||
};
|
||||
|
||||
struct dmxdev_filter {
|
||||
union {
|
||||
struct dmx_section_filter *sec;
|
||||
@@ -78,6 +107,8 @@ struct dmxdev_filter {
|
||||
struct dmx_pes_filter_params pes;
|
||||
} params;
|
||||
|
||||
struct dmxdev_events_queue events;
|
||||
|
||||
enum dmxdev_type type;
|
||||
enum dmxdev_state state;
|
||||
struct dmxdev *dev;
|
||||
@@ -88,6 +119,8 @@ struct dmxdev_filter {
|
||||
/* relevent for decoder PES */
|
||||
unsigned long pes_buffer_size;
|
||||
|
||||
u32 rec_chunk_size;
|
||||
|
||||
/* only for sections */
|
||||
struct timer_list timer;
|
||||
int todo;
|
||||
@@ -107,8 +140,7 @@ struct dmxdev {
|
||||
int capabilities;
|
||||
#define DMXDEV_CAP_DUPLEX 0x1
|
||||
#define DMXDEV_CAP_PULL_MODE 0x2
|
||||
#define DMXDEV_CAP_PCR_EXTRACTION 0x4
|
||||
#define DMXDEV_CAP_INDEXING 0x8
|
||||
#define DMXDEV_CAP_INDEXING 0x4
|
||||
|
||||
enum dmx_playback_mode_t playback_mode;
|
||||
dmx_source_t source;
|
||||
@@ -120,6 +152,8 @@ struct dmxdev {
|
||||
struct dmx_frontend *dvr_orig_fe;
|
||||
|
||||
struct dvb_ringbuffer dvr_buffer;
|
||||
struct dmxdev_events_queue dvr_output_events;
|
||||
|
||||
struct dvb_ringbuffer dvr_input_buffer;
|
||||
struct workqueue_struct *dvr_input_workqueue;
|
||||
|
||||
|
||||
@@ -145,8 +145,15 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
|
||||
|
||||
/* PUSI ? */
|
||||
if (buf[1] & 0x40) {
|
||||
feed->peslen = 0xfffa;
|
||||
if (feed->pusi_seen)
|
||||
/* We had seen PUSI before, this means
|
||||
* that previous PES can be closed now.
|
||||
*/
|
||||
feed->cb.ts(NULL, 0, NULL, 0,
|
||||
&feed->feed.ts, DMX_OK_PES_END);
|
||||
|
||||
feed->pusi_seen = 1;
|
||||
feed->peslen = 0;
|
||||
}
|
||||
|
||||
if (feed->pusi_seen == 0)
|
||||
@@ -204,6 +211,11 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
|
||||
if (dvb_demux_performancecheck)
|
||||
demux->total_crc_time +=
|
||||
dvb_dmx_calc_time_delta(pre_crc_time);
|
||||
|
||||
/* Notify on CRC error */
|
||||
feed->cb.sec(NULL, 0, NULL, 0,
|
||||
&f->filter, DMX_CRC_ERROR);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1053,6 +1065,25 @@ static int dmx_ts_feed_decoder_buff_status(struct dmx_ts_feed *ts_feed,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dmx_ts_feed_data_ready_cb(struct dmx_ts_feed *feed,
|
||||
dmx_ts_data_ready_cb callback)
|
||||
{
|
||||
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
|
||||
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
|
||||
|
||||
mutex_lock(&dvbdmx->mutex);
|
||||
|
||||
if (dvbdmxfeed->state == DMX_STATE_GO) {
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dvbdmxfeed->data_ready_cb.ts = callback;
|
||||
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dmx_ts_set_indexing_params(
|
||||
struct dmx_ts_feed *ts_feed,
|
||||
struct dmx_indexing_video_params *params)
|
||||
@@ -1084,7 +1115,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
|
||||
feed->cb.ts = callback;
|
||||
feed->demux = demux;
|
||||
feed->pid = 0xffff;
|
||||
feed->peslen = 0xfffa;
|
||||
feed->peslen = 0;
|
||||
feed->buffer = NULL;
|
||||
memset(&feed->indexing_params, 0,
|
||||
sizeof(struct dmx_indexing_video_params));
|
||||
@@ -1105,6 +1136,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
|
||||
(*ts_feed)->set = dmx_ts_feed_set;
|
||||
(*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
|
||||
(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
|
||||
(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
|
||||
|
||||
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
|
||||
feed->state = DMX_STATE_FREE;
|
||||
@@ -1312,6 +1344,26 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int dmx_section_feed_data_ready_cb(struct dmx_section_feed *feed,
|
||||
dmx_section_data_ready_cb callback)
|
||||
{
|
||||
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
|
||||
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
|
||||
|
||||
mutex_lock(&dvbdmx->mutex);
|
||||
|
||||
if (dvbdmxfeed->state == DMX_STATE_GO) {
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dvbdmxfeed->data_ready_cb.sec = callback;
|
||||
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
|
||||
struct dmx_section_filter *filter)
|
||||
{
|
||||
@@ -1381,6 +1433,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
|
||||
(*feed)->start_filtering = dmx_section_feed_start_filtering;
|
||||
(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
|
||||
(*feed)->release_filter = dmx_section_feed_release_filter;
|
||||
(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
|
||||
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return 0;
|
||||
|
||||
@@ -78,6 +78,11 @@ struct dvb_demux_feed {
|
||||
dmx_section_cb sec;
|
||||
} cb;
|
||||
|
||||
union {
|
||||
dmx_ts_data_ready_cb ts;
|
||||
dmx_section_data_ready_cb sec;
|
||||
} data_ready_cb;
|
||||
|
||||
struct dvb_demux *demux;
|
||||
void *priv;
|
||||
int type;
|
||||
|
||||
@@ -111,6 +111,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
|
||||
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
|
||||
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
|
||||
|
||||
/* advance write ptr by <num> bytes */
|
||||
#define DVB_RINGBUFFER_PUSH(rbuf, num) \
|
||||
((rbuf)->pwrite = (((rbuf)->pwrite+(num))%(rbuf)->size))
|
||||
|
||||
/*
|
||||
** read <len> bytes from ring buffer into <buf>
|
||||
** <usermem> specifies whether <buf> resides in user space
|
||||
|
||||
@@ -33,16 +33,6 @@
|
||||
sizeof(struct mpq_streambuffer_packet_header) + \
|
||||
sizeof(struct mpq_adapter_video_meta_data)))
|
||||
|
||||
/*
|
||||
* PCR/STC information length saved in ring-buffer.
|
||||
* PCR / STC are saved in ring-buffer in the following form:
|
||||
* <8 bit flags><64 bits of STC> <64bits of PCR>
|
||||
* STC and PCR values are in 27MHz.
|
||||
* The current flags that are defined:
|
||||
* 0x00000001: discontinuity_indicator
|
||||
*/
|
||||
#define PCR_STC_LEN 17
|
||||
|
||||
|
||||
/* Number of demux devices, has default of linux configuration */
|
||||
static int mpq_demux_device_num = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
|
||||
@@ -1906,10 +1896,9 @@ int mpq_dmx_process_pcr_packet(
|
||||
struct dvb_demux_feed *feed,
|
||||
const u8 *buf)
|
||||
{
|
||||
int i;
|
||||
u64 pcr;
|
||||
u64 stc;
|
||||
u8 output[PCR_STC_LEN];
|
||||
struct dmx_data_ready data;
|
||||
struct mpq_demux *mpq_demux = feed->demux->priv;
|
||||
const struct ts_packet_header *ts_header;
|
||||
const struct ts_adaptation_field *adaptation_field;
|
||||
@@ -1960,17 +1949,13 @@ int mpq_dmx_process_pcr_packet(
|
||||
stc += buf[188];
|
||||
stc *= 256; /* convert from 105.47 KHZ to 27MHz */
|
||||
|
||||
output[0] = adaptation_field->discontinuity_indicator;
|
||||
data.data_length = 0;
|
||||
data.pcr.pcr = pcr;
|
||||
data.pcr.stc = stc;
|
||||
data.pcr.disc_indicator_set = adaptation_field->discontinuity_indicator;
|
||||
data.status = DMX_OK_PCR;
|
||||
feed->data_ready_cb.ts(&feed->feed.ts, &data);
|
||||
|
||||
for (i = 1; i <= 8; i++)
|
||||
output[i] = (stc >> ((8-i) << 3)) & 0xFF;
|
||||
|
||||
for (i = 9; i <= 16; i++)
|
||||
output[i] = (pcr >> ((16-i) << 3)) & 0xFF;
|
||||
|
||||
feed->cb.ts(output, PCR_STC_LEN,
|
||||
NULL, 0,
|
||||
&feed->feed.ts, DMX_OK);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mpq_dmx_process_pcr_packet);
|
||||
|
||||
@@ -641,7 +641,6 @@ static int mpq_tsif_dmx_init(
|
||||
mpq_demux->dmxdev.capabilities =
|
||||
DMXDEV_CAP_DUPLEX |
|
||||
DMXDEV_CAP_PULL_MODE |
|
||||
DMXDEV_CAP_PCR_EXTRACTION |
|
||||
DMXDEV_CAP_INDEXING;
|
||||
|
||||
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
|
||||
|
||||
@@ -752,7 +752,6 @@ static int mpq_tspp_dmx_init(
|
||||
mpq_demux->dmxdev.capabilities =
|
||||
DMXDEV_CAP_DUPLEX |
|
||||
DMXDEV_CAP_PULL_MODE |
|
||||
DMXDEV_CAP_PCR_EXTRACTION |
|
||||
DMXDEV_CAP_INDEXING;
|
||||
|
||||
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
|
||||
|
||||
@@ -139,7 +139,6 @@ static int mpq_tspp_dmx_init(
|
||||
mpq_demux->dmxdev.capabilities =
|
||||
DMXDEV_CAP_DUPLEX |
|
||||
DMXDEV_CAP_PULL_MODE |
|
||||
DMXDEV_CAP_PCR_EXTRACTION |
|
||||
DMXDEV_CAP_INDEXING;
|
||||
|
||||
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
|
||||
#define DMX_FILTER_SIZE 16
|
||||
|
||||
/* Min recording chunk upon which event is generated */
|
||||
#define DMX_REC_BUFF_CHUNK_MIN_SIZE (100*188)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_OUT_DECODER, /* Streaming directly to decoder. */
|
||||
@@ -135,7 +138,6 @@ struct dmx_indexing_video_params {
|
||||
enum dmx_indexing_video_profile profile;
|
||||
};
|
||||
|
||||
|
||||
struct dmx_pes_filter_params
|
||||
{
|
||||
__u16 pid;
|
||||
@@ -144,6 +146,18 @@ struct dmx_pes_filter_params
|
||||
dmx_pes_type_t pes_type;
|
||||
__u32 flags;
|
||||
|
||||
/*
|
||||
* The following configures when the event
|
||||
* DMX_EVENT_NEW_REC_CHUNK will be triggered.
|
||||
* When new recorded data is received with size
|
||||
* equal or larger than this value a new event
|
||||
* will be triggered. This is relevent when
|
||||
* output is DMX_OUT_TS_TAP or DMX_OUT_TSDEMUX_TAP,
|
||||
* size must be at least DMX_REC_BUFF_CHUNK_MIN_SIZE
|
||||
* and smaller than buffer size.
|
||||
*/
|
||||
__u32 rec_chunk_size;
|
||||
|
||||
struct dmx_indexing_video_params video_params;
|
||||
};
|
||||
|
||||
@@ -170,6 +184,129 @@ struct dmx_buffer_status {
|
||||
int error;
|
||||
};
|
||||
|
||||
/* Events associated with each demux filter */
|
||||
enum dmx_event {
|
||||
/* New PES packet is ready to be consumed */
|
||||
DMX_EVENT_NEW_PES,
|
||||
|
||||
/* New section is ready to be consumed */
|
||||
DMX_EVENT_NEW_SECTION,
|
||||
|
||||
/* New recording chunk is ready to be consumed */
|
||||
DMX_EVENT_NEW_REC_CHUNK,
|
||||
|
||||
/* New PCR value is ready */
|
||||
DMX_EVENT_NEW_PCR,
|
||||
|
||||
/* Overflow */
|
||||
DMX_EVENT_BUFFER_OVERFLOW,
|
||||
|
||||
/* Section was dropped due to CRC error */
|
||||
DMX_EVENT_SECTION_CRC_ERROR,
|
||||
|
||||
/* End-of-stream, no more data from this filter */
|
||||
DMX_EVENT_EOS
|
||||
};
|
||||
|
||||
/* Flags passed in filter events */
|
||||
|
||||
/* Continuity counter error was detected */
|
||||
#define DMX_FILTER_CC_ERROR 0x01
|
||||
|
||||
/* Discontinuity indicator was set */
|
||||
#define DMX_FILTER_DISCONTINUITY_INDEICATOR 0x02
|
||||
|
||||
/* PES legnth in PES header is not correct */
|
||||
#define DMX_FILTER_PES_LENGTH_ERROR 0x04
|
||||
|
||||
|
||||
/* PES info associated with DMX_EVENT_NEW_PES event */
|
||||
struct dmx_pes_event_info {
|
||||
/* Offset at which PES information starts */
|
||||
__u32 base_offset;
|
||||
|
||||
/*
|
||||
* Start offset at which PES data
|
||||
* from the stream starts.
|
||||
* Equal to base_offset if PES data
|
||||
* starts from the beginning.
|
||||
*/
|
||||
__u32 start_offset;
|
||||
|
||||
/* Total length holding the PES information */
|
||||
__u32 total_length;
|
||||
|
||||
/* Actual length holding the PES data */
|
||||
__u32 actual_length;
|
||||
|
||||
/* Local receiver timestamp in 27MHz */
|
||||
__u64 stc;
|
||||
|
||||
/* Flags passed in filter events */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/* Section info associated with DMX_EVENT_NEW_SECTION event */
|
||||
struct dmx_section_event_info {
|
||||
/* Offset at which section information starts */
|
||||
__u32 base_offset;
|
||||
|
||||
/*
|
||||
* Start offset at which section data
|
||||
* from the stream starts.
|
||||
* Equal to base_offset if section data
|
||||
* starts from the beginning.
|
||||
*/
|
||||
__u32 start_offset;
|
||||
|
||||
/* Total length holding the section information */
|
||||
__u32 total_length;
|
||||
|
||||
/* Actual length holding the section data */
|
||||
__u32 actual_length;
|
||||
|
||||
/* Flags passed in filter events */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/* Recording info associated with DMX_EVENT_NEW_REC_CHUNK event */
|
||||
struct dmx_rec_chunk_event_info {
|
||||
/* Offset at which recording chunk starts */
|
||||
__u32 offset;
|
||||
|
||||
/* Size of recording chunk in bytes */
|
||||
__u32 size;
|
||||
};
|
||||
|
||||
/* PCR info associated with DMX_EVENT_NEW_PCR event */
|
||||
struct dmx_pcr_event_info {
|
||||
/* Local timestamp in 27MHz
|
||||
* when PCR packet was received
|
||||
*/
|
||||
__u64 stc;
|
||||
|
||||
/* PCR value in 27MHz */
|
||||
__u64 pcr;
|
||||
|
||||
/* Flags passed in filter events */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Filter's event returned through DMX_GET_EVENT.
|
||||
* poll with POLLPRI would block until events are available.
|
||||
*/
|
||||
struct dmx_filter_event {
|
||||
enum dmx_event type;
|
||||
|
||||
union {
|
||||
struct dmx_pes_event_info pes;
|
||||
struct dmx_section_event_info section;
|
||||
struct dmx_rec_chunk_event_info recording_chunk;
|
||||
struct dmx_pcr_event_info pcr;
|
||||
} params;
|
||||
};
|
||||
|
||||
typedef struct dmx_caps {
|
||||
__u32 caps;
|
||||
|
||||
@@ -292,5 +429,6 @@ struct dmx_stc {
|
||||
#define DMX_RELEASE_DATA _IO('o', 57)
|
||||
#define DMX_FEED_DATA _IO('o', 58)
|
||||
#define DMX_SET_PLAYBACK_MODE _IOW('o', 59, enum dmx_playback_mode_t)
|
||||
#define DMX_GET_EVENT _IOR('o', 60, struct dmx_filter_event)
|
||||
|
||||
#endif /*_DVBDMX_H_*/
|
||||
|
||||
Reference in New Issue
Block a user