# HG changeset patch # User bellard # Date 1044313109 0 # Node ID fb671d87824eb5a00f5d6f0937b5367528195a09 # Parent 2a60f406fcccb1c1eab4027e456c4ce40c8e9e65 zero copy packet handling for DV1394 by Max Krasnyansky diff -r 2a60f406fccc -r fb671d87824e avformat.h --- a/avformat.h Mon Feb 03 22:53:10 2003 +0000 +++ b/avformat.h Mon Feb 03 22:58:29 2003 +0000 @@ -20,15 +20,33 @@ 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; + int size; + int stream_index; + int flags; + int duration; + void (*destruct)(struct AVPacket *); + void *priv; +} AVPacket; #define PKT_FLAG_KEY 0x0001 -} AVPacket; + +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 */ diff -r 2a60f406fccc -r fb671d87824e dv1394.c --- a/dv1394.c Mon Feb 03 22:53:10 2003 +0000 +++ b/dv1394.c Mon Feb 03 22:58:29 2003 +0000 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -60,7 +61,8 @@ 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 @@ return -ENOMEM; ast = av_new_stream(context, 1); if (!ast) { - av_free(vst); + av_free(vst); return -ENOMEM; } @@ -158,7 +160,13 @@ 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 @@ 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 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; + + 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; - - /* Wait until more frames are available */ if (poll(&p, 1, -1) < 0) { + if (errno == EAGAIN || errno == EINTR) + goto restart_poll; perror("Poll failed"); return -EIO; } @@ -211,7 +239,7 @@ 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 @@ } } - 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) diff -r 2a60f406fccc -r fb671d87824e utils.c --- a/utils.c Mon Feb 03 22:53:10 2003 +0000 +++ b/utils.c Mon Feb 03 22:58:29 2003 +0000 @@ -151,6 +151,15 @@ /* 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. * * @param pkt packet @@ -159,34 +168,18 @@ */ 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; - pkt->size = size; - /* sane state */ - pkt->pts = AV_NOPTS_VALUE; - pkt->stream_index = 0; - pkt->flags = 0; - - for(i=0; idata[size+i]= 0; + memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + av_init_packet(pkt); + pkt->data = data; + pkt->size = size; + 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)