aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-02-03 22:58:29 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-02-03 22:58:29 +0000
commit6fa5a56c1ba7ee770e48ddc8f785d85c00ba9c4d (patch)
treec60e1a61c337ae83557526b1bbe229a52219479a /libavformat
parentcdc90af00835297b8d5f3f06c47cf2c53267c3a3 (diff)
downloadffmpeg-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.h30
-rw-r--r--libavformat/dv1394.c69
-rw-r--r--libavformat/utils.c39
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)