Blame src/mpeg2.c

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
}