zero copy packet handling for DV1394 by Max Krasnyansky
Originally committed as revision 1542 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		
							parent
							
								
									cdc90af008
								
							
						
					
					
						commit
						6fa5a56c1b
					
				@ -20,15 +20,33 @@ extern "C" {
 | 
			
		||||
typedef struct AVPacket {
 | 
			
		||||
    INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
 | 
			
		||||
    UINT8 *data;
 | 
			
		||||
    int size;
 | 
			
		||||
    int stream_index;
 | 
			
		||||
    int flags;
 | 
			
		||||
    int duration;       
 | 
			
		||||
#define PKT_FLAG_KEY   0x0001
 | 
			
		||||
    int   size;
 | 
			
		||||
    int   stream_index;
 | 
			
		||||
    int   flags;
 | 
			
		||||
    int   duration;
 | 
			
		||||
    void  (*destruct)(struct AVPacket *);
 | 
			
		||||
    void  *priv;
 | 
			
		||||
} AVPacket; 
 | 
			
		||||
#define PKT_FLAG_KEY   0x0001
 | 
			
		||||
 | 
			
		||||
static inline void av_init_packet(AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    pkt->pts   = AV_NOPTS_VALUE;
 | 
			
		||||
    pkt->flags = 0;
 | 
			
		||||
    pkt->stream_index = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int av_new_packet(AVPacket *pkt, int size);
 | 
			
		||||
void av_free_packet(AVPacket *pkt);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Free a packet
 | 
			
		||||
 *
 | 
			
		||||
 * @param pkt packet to free
 | 
			
		||||
 */
 | 
			
		||||
static inline void av_free_packet(AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    pkt->destruct(pkt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*************************************************/
 | 
			
		||||
/* fractional numbers for exact pts handling */
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/poll.h>
 | 
			
		||||
@ -60,7 +61,8 @@ static int dv1394_reset(struct dv1394_data *dv)
 | 
			
		||||
    if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    dv->avail = 0;
 | 
			
		||||
    dv->avail  = dv->done = 0;
 | 
			
		||||
    dv->stream = 0;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -85,7 +87,7 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap
 | 
			
		||||
        return -ENOMEM;
 | 
			
		||||
    ast = av_new_stream(context, 1);
 | 
			
		||||
    if (!ast) {
 | 
			
		||||
       av_free(vst);
 | 
			
		||||
        av_free(vst);
 | 
			
		||||
        return -ENOMEM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -158,7 +160,13 @@ failed:
 | 
			
		||||
    return -EIO;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
 | 
			
		||||
static void __destruct_pkt(struct AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    pkt->data = NULL; pkt->size = 0;
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int __get_frame(struct dv1394_data *dv, AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    char *ptr = dv->ring + (dv->index * dv->frame_size);
 | 
			
		||||
 | 
			
		||||
@ -166,12 +174,15 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
 | 
			
		||||
        dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
 | 
			
		||||
        dv->done++; dv->avail--;
 | 
			
		||||
    } else {
 | 
			
		||||
       dv->pts = av_gettime() & ((1LL << 48) - 1);
 | 
			
		||||
        dv->pts = av_gettime() & ((1LL << 48) - 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(pkt->data, ptr, dv->frame_size);
 | 
			
		||||
    av_init_packet(pkt);
 | 
			
		||||
    pkt->destruct = __destruct_pkt;
 | 
			
		||||
    pkt->data     = ptr;
 | 
			
		||||
    pkt->size     = dv->frame_size;
 | 
			
		||||
    pkt->pts      = dv->pts;
 | 
			
		||||
    pkt->stream_index = dv->stream;
 | 
			
		||||
    pkt->pts = dv->pts;
 | 
			
		||||
 | 
			
		||||
    dv->stream ^= 1;
 | 
			
		||||
 | 
			
		||||
@ -181,16 +192,33 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
 | 
			
		||||
static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    struct dv1394_data *dv = context->priv_data;
 | 
			
		||||
    int len;
 | 
			
		||||
 | 
			
		||||
    if (!dv->avail) {
 | 
			
		||||
        struct dv1394_status s;
 | 
			
		||||
        struct pollfd p;
 | 
			
		||||
        p.fd = dv->fd;
 | 
			
		||||
        p.events = POLLIN | POLLERR | POLLHUP;
 | 
			
		||||
 | 
			
		||||
        if (dv->done) {
 | 
			
		||||
            /* Request more frames */
 | 
			
		||||
            if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
 | 
			
		||||
                /* This usually means that ring buffer overflowed.
 | 
			
		||||
                 * We have to reset :(.
 | 
			
		||||
                 */
 | 
			
		||||
  
 | 
			
		||||
                fprintf(stderr, "DV1394: Ring buffer overflow. Reseting ..\n");
 | 
			
		||||
 
 | 
			
		||||
                dv1394_reset(dv);
 | 
			
		||||
                dv1394_start(dv);
 | 
			
		||||
            }
 | 
			
		||||
            dv->done = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Wait until more frames are available */
 | 
			
		||||
restart_poll:
 | 
			
		||||
        p.fd = dv->fd;
 | 
			
		||||
        p.events = POLLIN | POLLERR | POLLHUP;
 | 
			
		||||
        if (poll(&p, 1, -1) < 0) {
 | 
			
		||||
            if (errno == EAGAIN || errno == EINTR)
 | 
			
		||||
                goto restart_poll;
 | 
			
		||||
            perror("Poll failed");
 | 
			
		||||
            return -EIO;
 | 
			
		||||
        }
 | 
			
		||||
@ -211,7 +239,7 @@ static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
 | 
			
		||||
 | 
			
		||||
        dv->avail = s.n_clear_frames;
 | 
			
		||||
        dv->index = s.first_clear_frame;
 | 
			
		||||
        dv->done = 0;
 | 
			
		||||
        dv->done  = 0;
 | 
			
		||||
 | 
			
		||||
        if (s.dropped_frames) {
 | 
			
		||||
            fprintf(stderr, "DV1394: Frame drop detected (%d). Reseting ..\n",
 | 
			
		||||
@ -222,31 +250,12 @@ static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (av_new_packet(pkt, dv->frame_size) < 0)
 | 
			
		||||
        return -EIO;
 | 
			
		||||
 | 
			
		||||
#ifdef DV1394_DEBUG
 | 
			
		||||
    fprintf(stderr, "index %d, avail %d, done %d\n", dv->index, dv->avail,
 | 
			
		||||
            dv->done);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    len = __copy_frame(dv, pkt);
 | 
			
		||||
 | 
			
		||||
    if (!dv->avail && dv->done) {
 | 
			
		||||
        /* Request more frames */
 | 
			
		||||
        if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
 | 
			
		||||
            /* This usually means that ring buffer overflowed.
 | 
			
		||||
             * We have to reset :(.
 | 
			
		||||
             */
 | 
			
		||||
 | 
			
		||||
            fprintf(stderr, "DV1394: Ring buffer overflow. Reseting ..\n");
 | 
			
		||||
 | 
			
		||||
            dv1394_reset(dv);
 | 
			
		||||
            dv1394_start(dv);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
    return __get_frame(dv, pkt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dv1394_close(AVFormatContext * context)
 | 
			
		||||
 | 
			
		||||
@ -150,6 +150,15 @@ AVInputFormat *av_find_input_format(const char *short_name)
 | 
			
		||||
 | 
			
		||||
/* memory handling */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Default packet destructor 
 | 
			
		||||
 */
 | 
			
		||||
static void av_destruct_packet(AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    av_free(pkt->data);
 | 
			
		||||
    pkt->data = NULL; pkt->size = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allocate the payload of a packet and intialized its fields to default values.
 | 
			
		||||
 *
 | 
			
		||||
@ -159,34 +168,18 @@ AVInputFormat *av_find_input_format(const char *short_name)
 | 
			
		||||
 */
 | 
			
		||||
int av_new_packet(AVPacket *pkt, int size)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    pkt->data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
 | 
			
		||||
    if (!pkt->data)
 | 
			
		||||
    void *data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
 | 
			
		||||
    if (!data)
 | 
			
		||||
        return AVERROR_NOMEM;
 | 
			
		||||
    memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
 | 
			
		||||
 | 
			
		||||
    av_init_packet(pkt);
 | 
			
		||||
    pkt->data = data; 
 | 
			
		||||
    pkt->size = size;
 | 
			
		||||
    /* sane state */
 | 
			
		||||
    pkt->pts = AV_NOPTS_VALUE;
 | 
			
		||||
    pkt->stream_index = 0;
 | 
			
		||||
    pkt->flags = 0;
 | 
			
		||||
    
 | 
			
		||||
    for(i=0; i<FF_INPUT_BUFFER_PADDING_SIZE; i++)
 | 
			
		||||
        pkt->data[size+i]= 0;
 | 
			
		||||
 | 
			
		||||
    pkt->destruct = av_destruct_packet;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Free a packet
 | 
			
		||||
 *
 | 
			
		||||
 * @param pkt packet to free
 | 
			
		||||
 */
 | 
			
		||||
void av_free_packet(AVPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
    av_freep(&pkt->data);
 | 
			
		||||
    /* fail safe */
 | 
			
		||||
    pkt->size = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* fifo handling */
 | 
			
		||||
 | 
			
		||||
int fifo_init(FifoBuffer *f, int size)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user