diff options
author | Fabrice Bellard <fabrice@bellard.org> | 2003-02-03 22:58:29 +0000 |
---|---|---|
committer | Fabrice Bellard <fabrice@bellard.org> | 2003-02-03 22:58:29 +0000 |
commit | 6fa5a56c1ba7ee770e48ddc8f785d85c00ba9c4d (patch) | |
tree | c60e1a61c337ae83557526b1bbe229a52219479a /libavformat | |
parent | cdc90af00835297b8d5f3f06c47cf2c53267c3a3 (diff) | |
download | ffmpeg-6fa5a56c1ba7ee770e48ddc8f785d85c00ba9c4d.tar.gz |
zero copy packet handling for DV1394 by Max Krasnyansky
Originally committed as revision 1542 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/avformat.h | 30 | ||||
-rw-r--r-- | libavformat/dv1394.c | 69 | ||||
-rw-r--r-- | libavformat/utils.c | 39 |
3 files changed, 79 insertions, 59 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a6c2f25835..c27b81df7f 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -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 */ diff --git a/libavformat/dv1394.c b/libavformat/dv1394.c index 7208277a1d..41c936393a 100644 --- a/libavformat/dv1394.c +++ b/libavformat/dv1394.c @@ -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) diff --git a/libavformat/utils.c b/libavformat/utils.c index c2e9328cd3..d295e9a3fa 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -151,6 +151,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. * * @param pkt packet @@ -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; - 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; + 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) |