|
Packit |
0bbbb1 |
/*
|
|
Packit |
0bbbb1 |
* libiec61883 - Linux IEEE 1394 streaming media library.
|
|
Packit |
0bbbb1 |
* Copyright (C) 2004 Kristian Hogsberg, Dan Dennedy, and Dan Maas.
|
|
Packit |
0bbbb1 |
* This file written by Dan Dennedy.
|
|
Packit |
0bbbb1 |
*
|
|
Packit |
0bbbb1 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
0bbbb1 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
0bbbb1 |
* License as published by the Free Software Foundation; either
|
|
Packit |
0bbbb1 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
0bbbb1 |
*
|
|
Packit |
0bbbb1 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
0bbbb1 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0bbbb1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0bbbb1 |
* Lesser General Public License for more details.
|
|
Packit |
0bbbb1 |
*
|
|
Packit |
0bbbb1 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
0bbbb1 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
0bbbb1 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
0bbbb1 |
*/
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
0bbbb1 |
#include <config.h>
|
|
Packit |
0bbbb1 |
#endif
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
#include "iec61883.h"
|
|
Packit |
0bbbb1 |
#include "iec61883-private.h"
|
|
Packit |
0bbbb1 |
#include "tsbuffer.h"
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
#include <errno.h>
|
|
Packit |
0bbbb1 |
#include <stdio.h>
|
|
Packit |
0bbbb1 |
#include <netinet/in.h>
|
|
Packit |
0bbbb1 |
#include <stdlib.h>
|
|
Packit |
0bbbb1 |
#include <assert.h>
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
#define MAX_PACKET_SIZE 2048 /* max 1394 iso packet size */
|
|
Packit |
0bbbb1 |
#define TSP_SPH_SIZE 192 /* size of transport stream packet plus source packet header */
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_t
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_xmit_init(raw1394handle_t handle,
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_xmit_t get_data,
|
|
Packit |
0bbbb1 |
void *callback_data)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
struct iec61883_mpeg2 *mpeg;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
assert (handle != NULL);
|
|
Packit |
0bbbb1 |
mpeg = malloc(sizeof(struct iec61883_mpeg2));
|
|
Packit |
0bbbb1 |
if (!mpeg) {
|
|
Packit |
0bbbb1 |
errno = ENOMEM;
|
|
Packit |
0bbbb1 |
return NULL;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
mpeg->tsbuffer = NULL;
|
|
Packit |
0bbbb1 |
mpeg->handle = handle;
|
|
Packit |
0bbbb1 |
mpeg->put_data = NULL;
|
|
Packit |
0bbbb1 |
mpeg->get_data = get_data;
|
|
Packit |
0bbbb1 |
mpeg->callback_data = callback_data;
|
|
Packit |
0bbbb1 |
mpeg->buffer_packets = 1000;
|
|
Packit |
0bbbb1 |
mpeg->prebuffer_packets = 1000;
|
|
Packit |
0bbbb1 |
mpeg->irq_interval = 250;
|
|
Packit |
0bbbb1 |
mpeg->synch = 0;
|
|
Packit |
0bbbb1 |
mpeg->speed = RAW1394_ISO_SPEED_200;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
raw1394_set_userdata (handle, mpeg);
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
return mpeg;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_t
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_recv_init(raw1394handle_t handle,
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_recv_t put_data,
|
|
Packit |
0bbbb1 |
void *callback_data)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
struct iec61883_mpeg2 *mpeg;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
mpeg = malloc(sizeof(struct iec61883_mpeg2));
|
|
Packit |
0bbbb1 |
if (!mpeg) {
|
|
Packit |
0bbbb1 |
errno = ENOMEM;
|
|
Packit |
0bbbb1 |
return NULL;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
mpeg->tsbuffer = NULL;
|
|
Packit |
0bbbb1 |
mpeg->handle = handle;
|
|
Packit |
0bbbb1 |
mpeg->put_data = put_data;
|
|
Packit |
0bbbb1 |
mpeg->get_data = NULL;
|
|
Packit |
0bbbb1 |
mpeg->callback_data = callback_data;
|
|
Packit |
0bbbb1 |
mpeg->buffer_packets = 1000;
|
|
Packit |
0bbbb1 |
mpeg->irq_interval = 250;
|
|
Packit |
0bbbb1 |
mpeg->synch = 0;
|
|
Packit |
0bbbb1 |
mpeg->speed = RAW1394_ISO_SPEED_200;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
raw1394_set_userdata (handle, mpeg);
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
return mpeg;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
static enum raw1394_iso_disposition
|
|
Packit |
0bbbb1 |
mpeg2_recv_handler (raw1394handle_t handle,
|
|
Packit |
0bbbb1 |
unsigned char *data,
|
|
Packit |
0bbbb1 |
unsigned int len,
|
|
Packit |
0bbbb1 |
unsigned char channel,
|
|
Packit |
0bbbb1 |
unsigned char tag,
|
|
Packit |
0bbbb1 |
unsigned char sy,
|
|
Packit |
0bbbb1 |
unsigned int cycle,
|
|
Packit |
0bbbb1 |
unsigned int dropped)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
struct iec61883_mpeg2 *mpeg = raw1394_get_userdata (handle);
|
|
Packit |
0bbbb1 |
enum raw1394_iso_disposition result = RAW1394_ISO_OK;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
/* check fields of CIP header for valid packet */
|
|
Packit |
0bbbb1 |
unsigned short dbs_fn_qpc_sph = (htonl (* (unsigned long*) (data)) >> 10) & 0x3fff;
|
|
Packit |
0bbbb1 |
unsigned char fmt = (htonl (* (unsigned long*) (data + 4)) >> 24) & 0x3f;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
mpeg->total_dropped += dropped;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
if (mpeg->put_data != NULL && /* only if callback registered */
|
|
Packit |
0bbbb1 |
channel == mpeg->channel && /* only for selected channel */
|
|
Packit |
0bbbb1 |
len >= TSP_SPH_SIZE + 8 && /* no empty packets */
|
|
Packit |
0bbbb1 |
dbs_fn_qpc_sph == 0x01b1 && /* valid CIP header */
|
|
Packit |
0bbbb1 |
fmt == 0x20 )
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
/* skip over CIP header and SPH */
|
|
Packit |
0bbbb1 |
data += 12;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
/* write each TSP in the iso packet minus SPH */
|
|
Packit |
0bbbb1 |
for (; len > IEC61883_MPEG2_TSP_SIZE; len -= TSP_SPH_SIZE, data += TSP_SPH_SIZE) {
|
|
Packit |
0bbbb1 |
if (mpeg->put_data (data, IEC61883_MPEG2_TSP_SIZE, dropped, mpeg->callback_data) < 0) {
|
|
Packit |
0bbbb1 |
result = RAW1394_ISO_ERROR;
|
|
Packit |
0bbbb1 |
break;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
dropped = 0; /* do not repeatedly report dropped */
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
if (result == RAW1394_ISO_OK && dropped)
|
|
Packit |
0bbbb1 |
result = RAW1394_ISO_DEFER;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
return result;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_recv_start(struct iec61883_mpeg2 *mpeg, int channel)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
int result = 0;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
result = raw1394_iso_recv_init (mpeg->handle,
|
|
Packit |
0bbbb1 |
mpeg2_recv_handler,
|
|
Packit |
0bbbb1 |
mpeg->buffer_packets,
|
|
Packit |
0bbbb1 |
MAX_PACKET_SIZE + 8,
|
|
Packit |
0bbbb1 |
channel,
|
|
Packit |
0bbbb1 |
RAW1394_DMA_PACKET_PER_BUFFER,
|
|
Packit |
0bbbb1 |
mpeg->irq_interval);
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
if (result == 0) {
|
|
Packit |
0bbbb1 |
mpeg->total_dropped = 0;
|
|
Packit |
0bbbb1 |
mpeg->channel = channel;
|
|
Packit |
0bbbb1 |
result = raw1394_iso_recv_start (mpeg->handle, -1, -1, 0);
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
return result;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
static enum raw1394_iso_disposition
|
|
Packit |
0bbbb1 |
mpeg2_xmit_handler (raw1394handle_t handle, unsigned char *data,
|
|
Packit |
0bbbb1 |
unsigned int *len, unsigned char *tag,
|
|
Packit |
0bbbb1 |
unsigned char *sy, int cycle,
|
|
Packit |
0bbbb1 |
unsigned int dropped )
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
struct iec61883_mpeg2 *mpeg = raw1394_get_userdata (handle);
|
|
Packit |
0bbbb1 |
enum raw1394_iso_disposition result = RAW1394_ISO_OK;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
mpeg->total_dropped += dropped;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
if ( mpeg->tsbuffer != NULL ) {
|
|
Packit |
0bbbb1 |
*len = tsbuffer_send_iso_cycle (mpeg->tsbuffer, data, cycle,
|
|
Packit |
0bbbb1 |
(raw1394_get_local_id (handle) & 0x3f), dropped);
|
|
Packit |
0bbbb1 |
if (*len == 0)
|
|
Packit |
0bbbb1 |
result = RAW1394_ISO_ERROR;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
else
|
|
Packit |
0bbbb1 |
result = RAW1394_ISO_ERROR;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
*tag = IEC61883_TAG_WITH_CIP;
|
|
Packit |
0bbbb1 |
*sy = 0;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
return result;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_xmit_start (struct iec61883_mpeg2 *mpeg, int pid, int channel)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
int result = 0;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
if (mpeg->get_data != NULL) {
|
|
Packit |
0bbbb1 |
mpeg->tsbuffer = tsbuffer_init (mpeg->get_data, mpeg->callback_data, pid);
|
|
Packit |
0bbbb1 |
if (mpeg->tsbuffer != NULL) {
|
|
Packit |
0bbbb1 |
if (raw1394_iso_xmit_init (mpeg->handle,
|
|
Packit |
0bbbb1 |
mpeg2_xmit_handler,
|
|
Packit |
0bbbb1 |
mpeg->buffer_packets,
|
|
Packit |
0bbbb1 |
968, /* max packets size = 5 * 192 + 8 */
|
|
Packit |
0bbbb1 |
channel,
|
|
Packit |
0bbbb1 |
mpeg->speed,
|
|
Packit |
0bbbb1 |
mpeg->irq_interval) == 0) {
|
|
Packit |
0bbbb1 |
mpeg->total_dropped = 0;
|
|
Packit |
0bbbb1 |
result = raw1394_iso_xmit_start (mpeg->handle, -1, mpeg->prebuffer_packets);
|
|
Packit |
0bbbb1 |
} else
|
|
Packit |
0bbbb1 |
result = -1;
|
|
Packit |
0bbbb1 |
} else
|
|
Packit |
0bbbb1 |
result = -1;
|
|
Packit |
0bbbb1 |
} else
|
|
Packit |
0bbbb1 |
result = -1;
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
return result;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_xmit_stop (struct iec61883_mpeg2 *mpeg)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
if (mpeg->synch)
|
|
Packit |
0bbbb1 |
raw1394_iso_xmit_sync (mpeg->handle);
|
|
Packit |
0bbbb1 |
raw1394_iso_shutdown (mpeg->handle);
|
|
Packit |
0bbbb1 |
tsbuffer_close (mpeg->tsbuffer);
|
|
Packit |
0bbbb1 |
mpeg->tsbuffer = NULL;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_recv_stop (struct iec61883_mpeg2 *mpeg)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
if (mpeg->synch)
|
|
Packit |
0bbbb1 |
raw1394_iso_recv_flush (mpeg->handle);
|
|
Packit |
0bbbb1 |
raw1394_iso_shutdown (mpeg->handle);
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_close (struct iec61883_mpeg2 *mpeg)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg != NULL);
|
|
Packit |
0bbbb1 |
if (mpeg->put_data)
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_recv_stop (mpeg);
|
|
Packit |
0bbbb1 |
else if (mpeg->get_data)
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_xmit_stop (mpeg);
|
|
Packit |
0bbbb1 |
free (mpeg);
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
unsigned int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_buffers(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->buffer_packets;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_set_buffers(iec61883_mpeg2_t mpeg2, unsigned int packets)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
mpeg2->buffer_packets = packets;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
unsigned int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_prebuffers(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->prebuffer_packets;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_set_prebuffers(iec61883_mpeg2_t mpeg2, unsigned int packets)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
mpeg2->prebuffer_packets = packets;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
unsigned int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_irq_interval(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->irq_interval;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_set_irq_interval(iec61883_mpeg2_t mpeg2, unsigned int packets)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
mpeg2->irq_interval = packets;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_synch(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->synch;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_set_synch(iec61883_mpeg2_t mpeg2, int synch)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
mpeg2->synch = synch;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_speed(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->speed;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_set_speed(iec61883_mpeg2_t mpeg2, int speed)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
mpeg2->speed = speed;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
unsigned int
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_dropped(iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->total_dropped;
|
|
Packit |
0bbbb1 |
}
|
|
Packit |
0bbbb1 |
|
|
Packit |
0bbbb1 |
void *
|
|
Packit |
0bbbb1 |
iec61883_mpeg2_get_callback_data (iec61883_mpeg2_t mpeg2)
|
|
Packit |
0bbbb1 |
{
|
|
Packit |
0bbbb1 |
assert (mpeg2 != NULL);
|
|
Packit |
0bbbb1 |
return mpeg2->callback_data;
|
|
Packit |
0bbbb1 |
}
|