Commit db7c5c10 authored by bellard's avatar bellard

zero copy packet handling for DV1394 by Max Krasnyansky


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@1542 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 70c449d6
...@@ -24,11 +24,29 @@ typedef struct AVPacket { ...@@ -24,11 +24,29 @@ typedef struct AVPacket {
int stream_index; int stream_index;
int flags; int flags;
int duration; int duration;
#define PKT_FLAG_KEY 0x0001 void (*destruct)(struct AVPacket *);
void *priv;
} AVPacket; } 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); 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 */ /* fractional numbers for exact pts handling */
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/poll.h> #include <sys/poll.h>
...@@ -60,7 +61,8 @@ static int dv1394_reset(struct dv1394_data *dv) ...@@ -60,7 +61,8 @@ static int dv1394_reset(struct dv1394_data *dv)
if (ioctl(dv->fd, DV1394_INIT, &init) < 0) if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
return -1; return -1;
dv->avail = 0; dv->avail = dv->done = 0;
dv->stream = 0;
return 0; return 0;
} }
...@@ -158,7 +160,13 @@ failed: ...@@ -158,7 +160,13 @@ failed:
return -EIO; 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); char *ptr = dv->ring + (dv->index * dv->frame_size);
...@@ -169,9 +177,12 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt) ...@@ -169,9 +177,12 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
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->stream_index = dv->stream; pkt->destruct = __destruct_pkt;
pkt->data = ptr;
pkt->size = dv->frame_size;
pkt->pts = dv->pts; pkt->pts = dv->pts;
pkt->stream_index = dv->stream;
dv->stream ^= 1; dv->stream ^= 1;
...@@ -181,16 +192,33 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt) ...@@ -181,16 +192,33 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt) static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
{ {
struct dv1394_data *dv = context->priv_data; struct dv1394_data *dv = context->priv_data;
int len;
if (!dv->avail) { if (!dv->avail) {
struct dv1394_status s; struct dv1394_status s;
struct pollfd p; 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 */ /* Wait until more frames are available */
restart_poll:
p.fd = dv->fd;
p.events = POLLIN | POLLERR | POLLHUP;
if (poll(&p, 1, -1) < 0) { if (poll(&p, 1, -1) < 0) {
if (errno == EAGAIN || errno == EINTR)
goto restart_poll;
perror("Poll failed"); perror("Poll failed");
return -EIO; return -EIO;
} }
...@@ -222,31 +250,12 @@ static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt) ...@@ -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 #ifdef DV1394_DEBUG
fprintf(stderr, "index %d, avail %d, done %d\n", dv->index, dv->avail, fprintf(stderr, "index %d, avail %d, done %d\n", dv->index, dv->avail,
dv->done); dv->done);
#endif #endif
len = __copy_frame(dv, pkt); return __get_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;
} }
static int dv1394_close(AVFormatContext * context) static int dv1394_close(AVFormatContext * context)
......
...@@ -150,6 +150,15 @@ AVInputFormat *av_find_input_format(const char *short_name) ...@@ -150,6 +150,15 @@ AVInputFormat *av_find_input_format(const char *short_name)
/* memory handling */ /* 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. * 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) ...@@ -159,34 +168,18 @@ AVInputFormat *av_find_input_format(const char *short_name)
*/ */
int av_new_packet(AVPacket *pkt, int size) int av_new_packet(AVPacket *pkt, int size)
{ {
int i; void *data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
pkt->data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); if (!data)
if (!pkt->data)
return AVERROR_NOMEM; return AVERROR_NOMEM;
pkt->size = size; memset(data + size, 0, FF_INPUT_BUFFER_PADDING_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;
av_init_packet(pkt);
pkt->data = data;
pkt->size = size;
pkt->destruct = av_destruct_packet;
return 0; 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 */ /* fifo handling */
int fifo_init(FifoBuffer *f, int size) int fifo_init(FifoBuffer *f, int size)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment