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 {
|
typedef struct AVPacket {
|
||||||
INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
|
INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
|
||||||
UINT8 *data;
|
UINT8 *data;
|
||||||
int size;
|
int size;
|
||||||
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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
ast = av_new_stream(context, 1);
|
ast = av_new_stream(context, 1);
|
||||||
if (!ast) {
|
if (!ast) {
|
||||||
av_free(vst);
|
av_free(vst);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
|
|
||||||
@ -166,12 +174,15 @@ static inline int __copy_frame(struct dv1394_data *dv, AVPacket *pkt)
|
|||||||
dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
|
dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
|
||||||
dv->done++; dv->avail--;
|
dv->done++; dv->avail--;
|
||||||
} else {
|
} 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->stream_index = dv->stream;
|
||||||
pkt->pts = dv->pts;
|
|
||||||
|
|
||||||
dv->stream ^= 1;
|
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)
|
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;
|
||||||
}
|
}
|
||||||
@ -211,7 +239,7 @@ static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
|
|||||||
|
|
||||||
dv->avail = s.n_clear_frames;
|
dv->avail = s.n_clear_frames;
|
||||||
dv->index = s.first_clear_frame;
|
dv->index = s.first_clear_frame;
|
||||||
dv->done = 0;
|
dv->done = 0;
|
||||||
|
|
||||||
if (s.dropped_frames) {
|
if (s.dropped_frames) {
|
||||||
fprintf(stderr, "DV1394: Frame drop detected (%d). Reseting ..\n",
|
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
|
#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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
|
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
|
av_init_packet(pkt);
|
||||||
|
pkt->data = data;
|
||||||
pkt->size = size;
|
pkt->size = size;
|
||||||
/* sane state */
|
pkt->destruct = av_destruct_packet;
|
||||||
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;
|
|
||||||
|
|
||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user