[Mplayer-cvslog] CVS: main/libmp1e/common alloc.c,NONE,1.1 alloc.h,NONE,1.1 bstream.c,NONE,1.1 bstream.h,NONE,1.1 bstream_mmx.s,NONE,1.1 errstr.c,NONE,1.1 errstr.h,NONE,1.1 fifo.c,NONE,1.1 fifo.h,NONE,1.1 list.h,NONE,1.1 log.h,NONE,1.1 math.h,NONE,1.1 mmx.c,NONE,1.1 mmx.h,NONE,1.1 profile.c,NONE,1.1 profile.h,NONE,1.1 sync.c,NONE,1.1 sync.h,NONE,1.1 threads.h,NONE,1.1 types.h,NONE,1.1
David Holm
mswitch at mplayer.dev.hu
Wed Dec 5 00:56:47 CET 2001
- Previous message: [Mplayer-cvslog] CVS: main/libmp1e/audio audio.h,NONE,1.1 fft.c,NONE,1.1 filter.c,NONE,1.1 filter_mmx.s,NONE,1.1 libaudio.h,NONE,1.1 mp2.c,NONE,1.1 mpeg.h,NONE,1.1 psycho.c,NONE,1.1 tables.c,NONE,1.1
- Next message: [Mplayer-cvslog] CVS: main/libmp1e/systems libsystems.h,NONE,1.1 mpeg.h,NONE,1.1 mpeg1.c,NONE,1.1 mpeg2.c,NONE,1.1 output.h,NONE,1.1 rte_output.c,NONE,1.1 systems.c,NONE,1.1 systems.h,NONE,1.1 vcd.c,NONE,1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/mplayer/main/libmp1e/common
In directory mplayer:/var/tmp.root/cvs-serv18519
Added Files:
alloc.c alloc.h bstream.c bstream.h bstream_mmx.s errstr.c
errstr.h fifo.c fifo.h list.h log.h math.h mmx.c mmx.h
profile.c profile.h sync.c sync.h threads.h types.h
Log Message:
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: alloc.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include "math.h"
#ifndef HAVE_MEMALIGN
void *
alloc_aligned(size_t size, int align, bool clear)
{
void *p, *b;
if (align < sizeof(void *))
align = sizeof(void *);
if (!(b = malloc(size + align)))
return NULL;
p = (void *)(((long)((char *) b + align)) & -align);
((void **) p)[-1] = b;
if (clear)
memset(p, 0, size);
return p;
}
#endif // !HAVE_MEMALIGN
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: alloc.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef ALLOC_H
#define ALLOC_H
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "types.h"
#ifdef HAVE_MEMALIGN
#define free_aligned(p) free(p)
#else
#define free_aligned(p) free(((void **) p)[-1])
#endif
extern void *alloc_aligned(size_t, int, bool);
static inline void *
malloc_aligned(size_t size, int align)
{
void *p;
#ifdef HAVE_MEMALIGN
p = (void *) memalign(align, size);
#else
p = alloc_aligned(size, align, FALSE);
/*
if ((p = malloc(size + align)))
(char *) p += align - ((int) p & (align - 1));
*/
#endif
return p;
}
static inline void *
calloc_aligned(size_t size, int align)
{
void *p;
#ifdef HAVE_MEMALIGN
if ((p = (void *) memalign(align, size)))
memset(p, 0, size);
#else
p = alloc_aligned(size, align, TRUE);
/*
if ((p = calloc(1, size + align)))
(char *) p += align - ((int) p & (align - 1));
*/
#endif
return p;
}
#endif // ALLOC_H
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bstream.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#include <stdio.h>
#include "bstream.h"
void
binit_write(struct bs_rec *b)
{
b->n = 0;
b->buf.uq = 0;
b->uq64.uq = 64ULL;
}
/*
* Returns the number of bits encoded since bstart,
* granularity 64 bits
*/
int
bflush(struct bs_rec *b)
{
// Bits are shifted to msb already, filled up with padding
// zeroes. Store as mmx.uq to maintain frame alignment.
((unsigned int *) b->p)[0] = swab32(b->buf.ud[1]);
((unsigned int *) b->p)[1] = swab32(b->buf.ud[0]);
b->p++;
b->n = 0;
b->buf.uq = 0;
return (b->p - b->p1) * 64;
}
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bstream.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef BITSTREAM_H
#define BITSTREAM_H
#include "mmx.h"
struct bs_rec {
int n; /* Number of bits accumulated */
mmx_t * p; /* Output buffer */
mmx_t buf; /* Accumulated bits (usually cached in mm7), msb justified */
mmx_t uq64; /* 64ULL */
mmx_t * p1;
int pad;
};
extern void binit_write(struct bs_rec *b);
#define bstart(b, p0) ((b)->p1 = (b)->p = (mmx_t *)(p0));
#define bepilog(b) __asm__ __volatile__ (" movq %0,%%mm7\n" :: "m" ((b)->buf))
#define bprolog(b) __asm__ __volatile__ (" movq %%mm7,%0\n" :: "m" ((b)->buf))
/* Encode rightmost n bits in v, with v < (1 << n) and 0 < n <= 32 */
#define bputl(b, v, n) mmx_bputl(b, n, v) /* to match reg assignment of bputq */
extern void mmx_bputl(struct bs_rec *b, int n, unsigned int v) __attribute__ ((regparm (3)));
/* Encode rightmost n bits in mm0.uq, with mm0.uq < (1 << n) and 0 < n <= 64 */
#define bputq mmx_bputq
extern void mmx_bputq(struct bs_rec *b, int n) __attribute__ ((regparm (2)));
#define bwritten(b) ((((char *)(b)->p - (char *)(b)->p1) * 8) + ((b)->n))
extern int bflush(struct bs_rec *b);
#define brewind(bd, bs) (*(bd) = *(bs))
static inline void
bstartq(unsigned int v)
{
__asm__ __volatile__ ("\tmovd %0,%%mm0;\n"
:: "rm" (v) : "cc" FPU_REGS);
}
#define bcatq(v, n) \
do { \
if (__builtin_constant_p(n)) \
__asm__ __volatile__ ( \
"\tpsllq %0,%%mm0;\n" \
:: "im" ((n)) : "cc" FPU_REGS); \
/* never m but suppress warning */ \
else \
__asm__ __volatile__ ( \
"\tmovd %0,%%mm2;\n" \
"\tpsllq %%mm2,%%mm0;\n" \
:: "rm" ((unsigned int)(n)) : "cc" FPU_REGS); \
\
if (0&&__builtin_constant_p(v)) \
__asm__ __volatile__ ("\tpor %0,%%mm0;\n" \
:: "m" ((unsigned long long)(v)) \
: "cc" FPU_REGS); \
else \
__asm__ __volatile__ ( \
"\tmovd %0,%%mm1;\n" \
"\tpor %%mm1,%%mm0;\n" \
:: "rm" ((unsigned int)(v)) : "cc" FPU_REGS); \
} while (0)
#endif /* BITSTREAM_H */
--- NEW FILE ---
#
# MPEG-1 Real Time Encoder
#
# Copyright (C) 1999-2001 Michael H. Schimek
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: bstream_mmx.s,v 1.1 2001/12/04 23:56:43 mswitch Exp $
.text
.align 16
.globl mmx_bputl
.globl mmx_bputq
# void
# mmx_bputl(struct bs_rec *b [eax], int n [edx], unsigned int v [ecx])
mmx_bputl:
movd %ecx,%mm0; // value
mmx_bputq:
addl (%eax),%edx; // bs_rec->n + nbits
movl $64,%ecx;
subl %edx,%ecx;
movd %ecx,%mm1;
jle 1f;
psllq %mm1,%mm0;
movl %edx,(%eax); // bs_rec->n
por %mm0,%mm7;
ret
1:
movd 16(%eax),%mm3; // bs_rec->uq64 (64ULL)
pxor %mm2,%mm2;
movq %mm0,%mm4;
movl 4(%eax),%ecx; // bs_rec->p
paddd %mm1,%mm3;
psubd %mm1,%mm2;
psllq %mm3,%mm0;
leal 8(%ecx),%edx;
psrlq %mm2,%mm4;
movd %mm2,(%eax); // bs_rec->n
por %mm7,%mm4;
movl %edx,4(%eax); // bs_rec->p
movd %mm4,%edx;
psrlq $32,%mm4;
bswap %edx;
movd %mm4,%eax;
movl %edx,4(%ecx)
movq %mm0,%mm7;
bswap %eax;
movl %eax,(%ecx);
ret
--- NEW FILE ---
/*
* Copyright (C) 2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: errstr.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <stdarg.h>
#include <assert.h>
#include "errstr.h"
static pthread_key_t errstr_key;
struct errstr_rec {
char * message;
void (* free)(void *);
};
/**
* reset_errstr:
*
* Reset the thread specific errstr object, freeing a stored
* error message as desired. Subsequent calls to get_errstr
* will return %NULL. All newly created threads have a reset
* errstr.
**/
void
reset_errstr(void)
{
struct errstr_rec *e;
if ((e = pthread_getspecific(errstr_key))) {
if (e->message && e->free)
e->free(e->message);
free(e);
pthread_setspecific(errstr_key, NULL);
}
}
/**
* set_errstr:
* @message: Error message, any zero terminated string.
* Can be %NULL, which has the same effect as calling reset_errstr().
* @free_func: Pointer to a function to free the error message
* (eg. 'free'), can be %NULL for a static error message.
*
* Set the thread specific errstr to @message, freeing any previously
* stored message. When this function fails, subsequent calls to
* get_errstr will return %NULL. The error message is freed when
* calling reset_errstr(), set_errstr() and at thread termination.
**/
void
set_errstr(char *message, void (*free_func)(void *))
{
struct errstr_rec *e;
if ((e = pthread_getspecific(errstr_key))) {
if (e->message && e->free)
e->free(e->message);
} else if (!(e = malloc(sizeof(*e))))
return;
e->message = message;
e->free = free_func;
if (pthread_setspecific(errstr_key, e) != 0) {
if (e->message && e->free)
e->free(e->message);
free(e);
}
}
void
set_errstr_printf(char *templ, ...)
{
va_list ap;
char *msg;
va_start(ap, templ);
vasprintf(&msg, templ, ap);
va_end(ap);
set_errstr(msg, free);
}
/**
* get_errstr:
*
* Reads the thread specific errstr object, this is equivalent
* to reading the 'errstr' pseudo variable (char *). Note only
* set_errstr() can write 'errstr'.
*
* Return value:
* Error message (char *) or %NULL if not set.
**/
char *
get_errstr(void)
{
struct errstr_rec *e;
if ((e = pthread_getspecific(errstr_key)))
return e->message;
return NULL;
}
static void
uninit_errstr(void *p)
{
struct errstr_rec *e = p;
if (e) {
if (e->message && e->free)
e->free(e->message);
free(e);
}
}
static void init_errstr(void) __attribute__ ((constructor));
static void
init_errstr(void)
{
assert(pthread_key_create(&errstr_key, uninit_errstr) == 0);
}
--- NEW FILE ---
/*
* Copyright (C) 2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: errstr.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef ERRSTR_H
#define ERRSTR_H
#ifndef NO_ERRSTR
#define errstr (get_errstr())
#endif
extern void reset_errstr(void);
extern void set_errstr(char *, void (*)(void *));
extern char * get_errstr(void);
extern void set_errstr_printf(char *, ...);
#endif /* ERRSTR_H */
--- NEW FILE ---
/*
* Copyright (C) 1999-2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fifo.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
[...1132 lines suppressed...]
&& f->eof_count <= list_members(&f->consumers))
add_tail(&f->consumers, &c->node);
else
c = NULL;
pthread_mutex_unlock(&f->producer->mutex);
pthread_mutex_unlock(&f->consumer->mutex);
return c;
}
/*
TODO:
* test callbacks
* stealing buffers & callbacks ok?
* add_p/c shall make a fifo callback
* error ignores mp-fifo, in data direction only
* add wait timeout (optional)
*/
--- NEW FILE ---
/*
* Copyright (C) 1999-2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fifo.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef FIFO_H
#define FIFO_H
#include <stdlib.h>
#include <sys/time.h>
#include "list.h"
#include "threads.h"
typedef struct fifo fifo;
typedef struct buffer buffer;
typedef struct consumer consumer;
typedef struct producer producer;
struct buffer {
node node; /* fifo->full/empty */
fifo * fifo;
/*
* These fields are used for the "virtual full queue".
*
* consumer->next points to the next buffer in fifo->full
* to be dequeued, NULL if all buffers have been consumed.
* (b->refcount used to count the number of these
* references but it turned out redundant.)
*
* consumers is their number at send_full time, always > 0
* because without consumers the buffer is instantly
* send_emptied. We can't use fifo->consumers.members
* because new consumers shall not dequeue old buffers.
*
* dequeued and enqueued count the wait_full and send_empty
* calls, respectively. A buffer is actually send_emptied
* when enqueued >= consumers, and can be "recycled" when
* dequeued == 0. enqueued > dequeued is already implied by
* enqueued > consumers and no steady state.
*
* For empty buffers b->refcount is n/a, consumers always 0 and
* dequeued counts the wait_empty calls. enqueued is n/a
* because send_full transfers the buffer immediately to
* the full queue.
*
* See rem_buffer for scheduled removal.
*/
int consumers;
int dequeued;
int enqueued;
bool remove;
/* Consumer read only, see send_full_buffer() */
int type; /* application specific */
int offset;
double time;
unsigned char * data; /* mandatory */
ssize_t used;
int error; /* copy of errno */
char * errorstr; /* gettext()ized, may be NULL */
/* Owner private */
node added; /* fifo->buffers */
unsigned char * allocated;
ssize_t size;
void (* destroy)(buffer *);
void * user_data;
/* XXX? */
int rte_flags; /* rte internal use */
};
struct fifo {
node node; /* owner private */
char name[64]; /* for debug messages */
mucon pro, con;
list full; /* FIFO */
list empty; /* LIFO */
list producers;
list consumers;
int p_reentry;
int c_reentry;
int eof_count; /* counts p->eof_sent */
/* Owner private */
mucon * producer; /* -> pro */
mucon * consumer; /* -> con */
list buffers; /* add/rem_buffer */
bool unlink_full_buffers; /* default true */
void (* wait_empty)(fifo *);
void (* send_full)(producer *, buffer *);
void (* wait_full)(fifo *);
void (* send_empty)(consumer *, buffer *);
bool (* start)(fifo *);
void (* stop)(fifo *);
void (* destroy)(fifo *);
void * user_data;
buffer * (* alloc_buffer)(ssize_t);
};
struct producer {
node node; /* fifo->producers */
fifo * fifo;
int dequeued; /* bookkeeping */
bool eof_sent;
};
struct consumer {
node node; /* fifo->consumers */
fifo * fifo;
buffer * next_buffer; /* virtual pointer */
int dequeued; /* bookkeeping */
};
/**
* current_time:
*
* Buffer time is usually noted in seconds TOD. Unfortunately too
* many interfaces provide no interrupt time so we have no choice
* but to query the system clock.
*
* Return value:
* gettimeofday() in seconds and fractions, double.
**/
static inline double
current_time(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec * (1 / 1e6);
/* rezp. mult is faster, not auto optimized for accuracy */
}
/**
* destroy_buffer:
* @b: buffer *
*
* Free all resources associated with the buffer. This is a
* low-level function, don't call it for buffers which have
* been added to a fifo. No op when @b is %NULL.
**/
static inline void
destroy_buffer(buffer *b)
{
if (b && b->destroy)
b->destroy(b);
}
extern buffer * init_buffer(buffer *, ssize_t);
extern buffer * alloc_buffer(ssize_t);
/**
* destroy_fifo:
* @f: fifo *
*
* Free all resources associated with the fifo, including all
* buffers. Make sure no threads are using the fifo and no
* producers or consumers can be added.
*
* Removing all producers and consumers before calling this
* function is not necessary, for example when a consumer
* aborted before detaching himself from the fifo.
*
* No op when @f is %NULL.
**/
static inline void
destroy_fifo(fifo *f)
{
if (f && f->destroy)
f->destroy(f);
}
/**
* recv_full_buffer:
* @c: consumer *
*
* Dequeues the next buffer in production order from the consumer's fifo's
* full queue. Remind callback (unbuffered) fifos do not fill automatically
* but only when the consumer calls wait_full_buffer(). In this case
* recv_full_buffer() returns a buffer only after unget_full_buffer() or
* when the producer enqueued more than one full buffer at the last
* wait_full_buffer().
*
* Buffers must be returned with send_empty_buffer() as soon as possible
* for re-use by the producer, including those with buffer.used == 0
* (end of stream) or buffer.used < 0 (error). You can dequeue more buffers
* before returning and buffers need not be returned in order. All buffer
* contents are read-only for consumers.
*
* None of the fifo functions depend on the identity of the calling thread
* (thread_t), however we assume the consumer object is not shared.
*
* Return value:
* Buffer pointer, or %NULL if the full queue is empty.
**/
static inline buffer *
recv_full_buffer(consumer *c)
{
fifo *f = c->fifo;
buffer *b;
pthread_mutex_lock(&f->consumer->mutex);
if ((b = c->next_buffer)->node.succ) {
c->next_buffer = (buffer *) b->node.succ;
b->dequeued++;
c->dequeued++;
} else
b = NULL;
pthread_mutex_unlock(&f->consumer->mutex);
return b;
}
extern buffer * wait_full_buffer(consumer *c);
extern buffer * wait_full_buffer_timeout(consumer *c, struct
timespec *timeout);
/**
* unget_full_buffer:
* @c: consumer *
* @b: buffer *
*
* Put buffer @b, dequeued with wait_full_buffer() or recv_full_buffer()
* and not yet returned with send_empty_buffer(), back on the full queue
* of its fifo, to be dequeued again later. You can unget more than one
* buffer, in reverse order of dequeuing, starting with the most
* recently dequeued.
**/
static inline void
unget_full_buffer(consumer *c, buffer *b)
{
fifo *f = c->fifo;
/* Migration prohibited */
assert(c->fifo == b->fifo);
c->dequeued--;
pthread_mutex_lock(&f->consumer->mutex);
assert(c->next_buffer == (buffer *) b->node.succ);
b->dequeued--;
c->next_buffer = b;
pthread_mutex_unlock(&f->consumer->mutex);
}
/**
* send_empty_buffer:
* @c: consumer *
* @b: buffer *
*
* Consumers call this function when done with a previously dequeued
* full buffer. Dereferencing the buffer pointer after sending the
* buffer is not permitted.
**/
static inline void
send_empty_buffer(consumer *c, buffer *b)
{
/* Migration prohibited */
assert(c->fifo == b->fifo);
c->dequeued--;
c->fifo->send_empty(c, b);
}
/* XXX rethink */
extern void send_empty_buffered(consumer *c, buffer *b);
/**
* recv_empty_buffer:
* @p: producer *
*
* Dequeues an empty buffer, no particular order, from the producer's fifo's
* empty queue. Remind callback (unbuffered) fifos do not fill automatically
* but only when the producer calls wait_empty_buffer().
*
* Send filled buffers with send_full_buffer(). You can dequeue more buffers
* before sending and buffers need not be sent in dequeuing order.
*
* None of the fifo functions depend on the identity of the calling thread
* (thread_t), however we assume the producer object is not shared.
*
* Return value:
* Buffer pointer, or %NULL if the empty queue is empty.
**/
static inline buffer *
recv_empty_buffer(producer *p)
{
fifo *f = p->fifo;
buffer *b;
pthread_mutex_lock(&f->producer->mutex);
b = PARENT(rem_head(&f->empty), buffer, node);
pthread_mutex_unlock(&f->producer->mutex);
if (b) {
b->dequeued = 1;
p->dequeued++;
}
return b;
}
extern buffer * wait_empty_buffer(producer *p);
/**
* unget_empty_buffer:
* @p: producer *
* @b: buffer *
*
* Put buffer @b, dequeued with wait_empty_buffer() or recv_empty_buffer()
* and not yet enqueued with send_full_buffer(), back on the empty queue
* of its fifo, to be dequeued again later. You can unget more than one
* buffer, in any order, but not the same buffer twice.
*
* It may happen another producer grabs the ungot buffer, so a subsequent
* recv_empty_buffer() will not necessarily succeed.
**/
static inline void
unget_empty_buffer(producer *p, buffer *b)
{
fifo *f = p->fifo;
/* Migration prohibited, don't use this to add buffers to the fifo */
assert(p->fifo == b->fifo && b->dequeued == 1);
p->dequeued--;
b->dequeued = 0;
pthread_mutex_lock(&f->producer->mutex);
add_tail(&f->empty, &b->node);
pthread_mutex_unlock(&f->producer->mutex);
}
extern void send_full_buffer(producer *p, buffer *b);
extern void rem_buffer(buffer *b);
extern bool add_buffer(fifo *f, buffer *b);
extern int init_buffered_fifo(fifo *f, char *name, int num_buffers, ssize_t buffer_size);
extern int init_callback_fifo(fifo *f, char *name, void (* custom_wait_empty)(fifo *), void (* custom_send_full)(producer *, buffer *), void (* custom_wait_full)(fifo *), void (* custom_send_empty)(consumer *, buffer *), int num_buffers, ssize_t buffer_size);
extern void rem_producer(producer *p);
extern producer * add_producer(fifo *f, producer *p);
extern void rem_consumer(consumer *c);
extern consumer * add_consumer(fifo *f, consumer *c);
/* XXX TBD */
/* start only *after* adding a consumer? */
/* mp-fifos? */
static inline bool
start_fifo(fifo *f)
{
return f->start(f);
}
#endif /* FIFO_H */
--- NEW FILE ---
/*
* Copyright (C) 1999-2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: list.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef LIST_H
#define LIST_H
#include <assert.h>
#include <pthread.h>
#include "types.h"
/*
* Your familiar doubly linked list type, plus member
* count for fast resource accounting and optional rwlock.
*
* Warning: No verification of the validity of list and
* node parameters. The number of members must not
* exceed INT_MAX.
*
* Traverse:
* for (node = list->head; node->succ; node = node->succ)
*
* Remove:
* for (n1 = list->head; (n2 = n1->succ); n1 = n2)
* rem_node(n1);
*/
typedef struct node node;
typedef struct list list;
typedef struct xlist xlist; /* Xclusive access */
struct node {
node * succ;
node * pred;
};
struct list {
node * head;
node * null;
node * tail;
int members;
};
struct xlist {
node * head;
node * null;
node * tail;
int members;
pthread_rwlock_t rwlock;
};
/*
* list foo_list;
* struct foo { int baz; node bar; }, *foop;
*
* for_all_nodes(foop, &foo_list, bar)
* foop->baz = 0;
*
* Not useful to delete list members.
*/
#define for_all_nodes(p, l, _node_) \
for ((p) = PARENT((l)->head, typeof(*(p)), _node_); \
(p)->_node_.succ; \
(p) = PARENT((p)->_node_.succ, typeof(*(p)), _node_))
/**
* destroy_list:
*
* Free all resources associated with the list,
* you must pair this with an init_list() call.
*
* Does not free the list object or any nodes.
**/
static inline void
destroy_xlist(xlist *l)
{
assert(l->members == 0);
assert(pthread_rwlock_destroy(&l->rwlock) == 0);
}
static inline void
destroy_list(list *l)
{
}
static inline void
destroy_invalid_xlist(xlist *l)
{
pthread_rwlock_destroy(&l->rwlock);
}
/**
* init_list:
* @l: list *
*
* Return value:
* The list pointer.
**/
static inline list *
init_list(list *l)
{
l->head = (node *) &l->null;
l->null = (node *) 0;
l->tail = (node *) &l->head;
l->members = 0;
return l;
}
static inline xlist *
init_xlist(xlist *l)
{
assert(pthread_rwlock_init(&l->rwlock, NULL) == 0);
l->head = (node *) &l->null;
l->null = (node *) 0;
l->tail = (node *) &l->head;
l->members = 0;
return l;
}
/**
* list_members:
* @l: list *
*
* Return value:
* Number of nodes linked in the list. You can read
* l->members directly when the rwlock is unused.
**/
static inline unsigned int
list_members(list *l)
{
return l->members;
}
static inline unsigned int
list_xmembers(xlist *l)
{
int members;
pthread_rwlock_rdlock(&l->rwlock);
members = l->members;
pthread_rwlock_unlock(&l->rwlock);
return members;
}
/**
* empty_list:
* @l: list *
*
* Return value:
* 1 if the list is empty, 0 otherwise. You can read
* l->members directly when the rwlock is unused.
**/
static inline int
empty_list(list *l)
{
return l->members == 0;
}
static inline int
empty_xlist(xlist *l)
{
return list_xmembers(l) == 0;
}
/**
* add_head:
* @l: list *
* @n: node *
*
* Add node at the head of the list.
*
* Return value:
* The node pointer.
**/
static inline node *
add_head(list *l, node *n)
{
n->pred = (node *) &l->head;
n->succ = l->head;
l->head->pred = n;
l->head = n;
l->members++;
return n;
}
static inline node *
add_xhead(xlist *l, node *n)
{
pthread_rwlock_wrlock(&l->rwlock);
n = add_head((list *) l, n);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
/**
* add_tail:
* @l: list *
* @n: node *
*
* Add node at the end of the list.
*
* Return value:
* The node pointer.
**/
static inline node *
add_tail(list *l, node *n)
{
n->succ = (node *) &l->null;
n->pred = l->tail;
l->tail->succ = n;
l->tail = n;
l->members++;
return n;
}
static inline node *
add_xtail(xlist *l, node *n)
{
pthread_rwlock_wrlock(&l->rwlock);
n = add_tail((list *) l, n);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
/**
* rem_head:
* @l: list *
*
* Remove first node of the list.
*
* Return value:
* Node pointer, or NULL if the list is empty.
**/
static inline node *
rem_head(list *l)
{
node *n = l->head, *s = n->succ;
if (s) {
s->pred = (node *) &l->head;
l->head = s;
l->members--;
return n;
}
return NULL;
}
static inline node *
rem_xhead(xlist *l)
{
node *n;
pthread_rwlock_wrlock(&l->rwlock);
n = rem_head((list *) l);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
/**
* rem_tail:
* @l: list *
*
* Remove last node of the list.
*
* Return value:
* Node pointer, or NULL if the list is empty.
**/
static inline node *
rem_tail(list *l)
{
node *n = l->tail, *p = n->pred;
if (p) {
p->succ = (node *) &l->null;
l->tail = p;
l->members--;
return n;
}
return NULL;
}
static inline node *
rem_xtail(xlist *l)
{
node *n;
pthread_rwlock_wrlock(&l->rwlock);
n = rem_tail((list *) l);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
/**
* unlink_node:
* @l: list *
* @n: node *
*
* Remove the node from its list. The node must
* be a member of the list, not verified.
*
* Return value:
* The node pointer.
**/
static inline node *
unlink_node(list *l, node *n)
{
n->pred->succ = n->succ;
n->succ->pred = n->pred;
l->members--;
return n;
}
static inline node *
unlink_xnode(xlist *l, node *n)
{
pthread_rwlock_wrlock(&l->rwlock);
n = unlink_node((list *) l, n);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
/**
* rem_node:
* @l: list *
* @n: node *
*
* Remove the node if member of the list.
*
* Return value:
* The node pointer or NULL if the node is not
* member of the list.
**/
static inline node *
rem_node(list *l, node *n)
{
node *q;
for (q = l->head; q->succ; q = q->succ)
if (n == q) {
unlink_node(l, n);
return n;
}
return NULL;
}
static inline node *
rem_xnode(xlist *l, node *n)
{
pthread_rwlock_wrlock(&l->rwlock);
n = rem_node((list *) l, n);
pthread_rwlock_unlock(&l->rwlock);
return n;
}
#endif /* LIST_H */
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LOG_H
#define LOG_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#ifndef HAVE_PROGRAM_INVOCATION_NAME
extern char * program_invocation_name;
extern char * program_invocation_short_name;
#endif
extern int verbose;
#define ISTF2(x) #x
#define ISTF1(x) ISTF2(x)
// mp1e:log.h:35: Failed to explain this (3, No such process)
#define ASSERT(what, cond, args...) \
do { \
if (!(cond)) { \
fprintf(stderr, "%s:" __FILE__ ":" ISTF1(__LINE__) ": " \
"Failed to " what " (%d, %s)\n", \
program_invocation_short_name \
,##args, errno, strerror(errno)); \
exit(EXIT_FAILURE); \
} else if (0) { \
fprintf(stderr, "%s:" __FILE__ ":" ISTF1(__LINE__) ": " \
what " - ok\n", program_invocation_short_name \
,##args); \
} \
} while (0)
// mp1e:log.h:47: Failed to explain this
#define ASSERTX(what, cond, args...) \
do { \
if (!(cond)) { \
fprintf(stderr, "%s:" __FILE__ ":" ISTF1(__LINE__) ": " \
"Failed to " what "\n", \
program_invocation_short_name ,##args); \
exit(EXIT_FAILURE); \
} \
} while (0)
/* glib-ish g_return_if_fail */
#define CHECK(what, cond, args...) \
do { \
if (!(cond)) { \
fprintf(stderr, "%s (" __FILE__ "@%d): " \
"Failed to " what " (%d, %s)\n", \
program_invocation_short_name, \
__LINE__ ,##args, \
errno, strerror(errno)); \
return; \
} \
} while (0)
// mp1e:log.h:71: Elvis lives
#define FAIL(why, args...) \
do { \
fprintf(stderr, "%s:" __FILE__ ":" ISTF1(__LINE__) ": " \
why "\n", program_invocation_short_name ,##args); \
exit(EXIT_FAILURE); \
} while (0)
#define DUMP(array, from, to) \
do { \
int i; \
\
fprintf(stderr, __FILE__ "@%d:\n", __LINE__); \
for (i = (from); i < (to); i++) \
fprintf(stderr, #array "[%d]=%f\n", \
i, (double)((array)[i])); \
} while (0)
/* Trace execution, except where void or prohibited by law. */
#define printv(level, format, args...) \
((verbose >= level) ? fprintf(stderr, \
/* "%s: " */ format \
/*, program_invocation_short_name */ ,##args) : 0)
/* mp1e:log.h:106: User error message */
#define ERRMSG(templ, args...) \
set_errstr_printf("mp1e:" __FILE__ ":" ISTF1(__LINE__) ": " \
templ ,##args)
#endif
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: math.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef MATH_H
#define MATH_H
#include <math.h>
#include <float.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define swap(a, b) \
do { \
__typeof__ (a) _t = (b); \
(b) = (a); \
(a) = _t; \
} while (0)
static inline int
saturate(int val, int min, int max)
{
#ifdef __i686__
/* 2 x cmp cmov, typ. both evaluated */
if (val < min)
val = min;
if (val > max)
val = max;
#else
/* 1-2 branches */
if (val < min)
val = min;
else if (val > max)
val = max;
#endif
return val;
}
/*
* Integer sign, equv to saturate(val, -1, +1)
*/
#define sign(val) (((int)(val) >> 31) | ((int)(val) > 0))
/*
* Round to nearest int, halfway cases to the nearest even integer
*/
#ifdef __i386__
/* rtn is the default mode */
#define lroundn(val) ({ long res; asm volatile ("fistpl %0" : "=m" (res) : "t" (val) : "st"); res; })
#define llroundn(val) ({ long long res; asm volatile ("fistpll %0" : "=m" (res) : "t" (val) : "st"); res; })
#else
#define lroundn(val) ((long)(((val) < 0.0) ? -floor(0.5 - (val)) : floor((val) + 0.5)))
#define llroundn(val) ((long long)(((val) < 0.0) ? -floor(0.5 - (val)) : floor((val) + 0.5)))
#endif
/*
* Round integer v up to nearest integer multiple of a
* ?
*/
// #define lalign(v, a) ((v) + (a) - (int)(v) % (a))
/*
* Absolute value w/o a branch
*/
static inline unsigned int
nbabs(register int n)
{
register int t = n;
t >>= 31;
n ^= t;
n -= t;
return n;
}
/*
* Find first set bit, starting at msb.
*
* 0x89abcdef -> 31, 0x456789ab -> 30
* 0x00000001 -> 0, 0x00000000 undefined
*/
static inline int
ffsr(unsigned int n)
{
int r;
asm volatile ("\tbsrl %1,%0\n": "=r" (r) : "r" (n));
return r;
}
/*
* Number of set bits
*/
static inline unsigned int
popcnt(unsigned int v)
{
v -= ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
v = (v + (v >> 4)) & 0x0F0F0F0F;
return (v * 0x01010101) >> 24;
}
#endif // MATH_H
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mmx.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#include <stdlib.h>
#include "log.h"
#include "mmx.h"
#include "math.h"
#if #cpu (i386)
/*
* References
*
* "Intel Processor Identification and the CPUID Instruction",
* Application Note AP-485, Nov 2000, order no. 241618-016,
* http://developer.intel.com
*
* "AMD Processor Recognition Application Note",
* publication # 20734, Rev. R, June 2000.
* http://www.amd.com/products/cpg/athlon/techdocs/index.html
*
* "Cyrix CPU Detection Guide",
* Application Note 112, Rev. 1.9, July 21, 1998
* formerly available from http://www.cyrix.com/html/developers/index.htm
* when Cyrix was part of National Semiconductor.
* VIA has no similar document available as of Jan 2001.
*/
typedef union {
unsigned char s[16];
struct {
unsigned int eax;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
} r;
} cpuid_t;
static inline int
toggle_eflags_id(void)
{
int success;
__asm__ __volatile__ (
" pushfl \n"
" popl %%ecx\n"
" movl %%ecx,%%eax\n"
" xorl $0x200000,%%eax\n"
" pushl %%eax\n"
" popfl \n"
" pushfl \n"
" popl %%eax\n"
" pushl %%ecx\n"
" popfl \n"
" xorl %%ecx,%%eax\n"
" andl $0x200000,%%eax\n"
" jz 1f\n"
" movl $1,%%eax\n"
"1:\n"
: "=a" (success) :: "ecx", "cc");
return success;
}
static /*inline*/ unsigned int
cpuid(cpuid_t *buf, unsigned int level)
{
unsigned int eax;
/* ARRRR */
__asm__ __volatile__ (
" pushl %%ebx\n"
" pushl %%ecx\n"
" pushl %%edx\n"
" cpuid \n"
" movl %%eax,(%%edi)\n"
" movl %%ebx,4(%%edi)\n"
" movl %%edx,8(%%edi)\n"
" movl %%ecx,12(%%edi)\n"
" popl %%edx\n"
" popl %%ecx\n"
" popl %%ebx\n"
: "=a" (eax) : "D" (buf), "a" (level) /*: "ebx", "ecx", "edx", "cc", "memory"*/);
return eax;
}
/* XXX check kernel version before advertising SSE */
#define INTEL_CMOV (1 << 15)
#define INTEL_MMX (1 << 23)
#define INTEL_SSE (1 << 25)
#define INTEL_SSE2 (1 << 26)
#define AMD_MMXEXT (1 << 22)
#define AMD_MMX (1 << 23)
#define AMD_SSE (1 << 25)
#define AMD_3DNOWEXT (1 << 30)
#define AMD_3DNOW (1 << 31)
#define CYRIX_MMX (1 << 23)
#define CYRIX_MMXEXT (1 << 24)
#define CYRIX_3DNOW (1 << 31)
#define FEATURE(bits) ((c.r.edx & (bits)) == (bits))
int
cpu_detection(void)
{
cpuid_t c;
if (!toggle_eflags_id()) {
ASSERT("identify CPU", 0);
return CPU_UNKNOWN;
}
cpuid(&c, 0);
if (!strncmp(c.s + 4, "GenuineIntel", 12)) {
cpuid(&c, 1);
if (FEATURE(INTEL_MMX | INTEL_CMOV | INTEL_SSE | INTEL_SSE2))
return CPU_PENTIUM_4;
if (FEATURE(INTEL_MMX | INTEL_CMOV | INTEL_SSE))
return CPU_PENTIUM_III;
if (FEATURE(INTEL_MMX | INTEL_CMOV))
return CPU_PENTIUM_II;
if (FEATURE(INTEL_MMX))
return CPU_PENTIUM_MMX;
} else if (!strncmp(c.s + 4, "AuthenticAMD", 12)) {
if (cpuid(&c, 0x80000000) > 0x80000000) {
cpuid(&c, 0x80000001);
if (FEATURE(AMD_MMX | AMD_MMXEXT | AMD_3DNOW | AMD_3DNOWEXT))
return CPU_ATHLON;
if (FEATURE(AMD_MMX | AMD_3DNOW))
return CPU_K6_2;
}
} else if (!strncmp(c.s + 4, "CyrixInstead", 12)) {
if (cpuid(&c, 0x80000000) > 0x80000000) {
cpuid(&c, 0x80000001);
if (FEATURE(CYRIX_MMX | CYRIX_MMXEXT | CYRIX_3DNOW))
return CPU_CYRIX_III;
} else {
cpuid(&c, 1);
if (FEATURE(CYRIX_MMX))
return CPU_CYRIX_MII;
}
}
ASSERT("identify CPU", 0);
return CPU_UNKNOWN;
}
#else
int
cpu_detection(void)
{
return 0;
}
#endif /* !cpu x86 */
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef MMX_H
#define MMX_H
#include <stdlib.h>
typedef union {
long long q;
unsigned long long uq;
int d[2];
unsigned int ud[2];
short w[4];
unsigned short uw[4];
char b[8];
unsigned char ub[8];
} __attribute__ ((aligned (8))) mmx_t;
#define MMXQ(a) ((mmx_t)((long long)(a)))
#define MMXD(a,b) ((mmx_t)(((((unsigned long long)(b))&0xFFFFFFFFULL)<<32)|((((unsigned long long)(a))&0xFFFFFFFFULL))))
#define MMXW(a,b,c,d) ((mmx_t)(((((unsigned long long)(d))&0xFFFFULL)<<48)|((((unsigned long long)(c))&0xFFFFULL)<<32)|((((unsigned long long)(b))&0xFFFFULL)<<16)|((((unsigned long long)(a))&0xFFFFULL))))
#define MMXB(a,b,c,d,e,f,g,h) ((mmx_t)(((((unsigned long long)(h))&0xFFULL)<<56)|((((unsigned long long)(g))&0xFFULL)<<48)|((((unsigned long long)(f))&0xFFULL)<<40)|((((unsigned long long)(e))&0xFFULL)<<32)|((((unsigned long long)(d))&0xFFULL)<<24)|((((unsigned long long)(c))&0xFFULL)<<16)|((((unsigned long long)(b))&0xFFULL)<<8)|((((unsigned long long)(a))&0xFFULL))))
#define MMXRD(a) MMXD(a,a)
#define MMXRW(a) MMXW(a,a,a,a)
#define MMXRB(a) MMXB(a,a,a,a,a,a,a,a)
/*
* These are optimization classes rather than
* identifying the actual model or brand name.
* Keep order (options.c)
*/
#define CPU_UNKNOWN 0 /* no MMX */
#define CPU_PENTIUM_MMX 1 /* MMX; late P5 core */
#define CPU_PENTIUM_II 2 /* MMX, CMOV; any P6 core */
#define CPU_PENTIUM_III 3 /* MMX, CMOV, SSE; any P6 core and Itanium x86 */
#define CPU_PENTIUM_4 4 /* MMX, CMOV, SSE, SSE2; any P8 core */
#define CPU_K6_2 5 /* MMX, 3DNOW; K6-2/K6-III */
#define CPU_ATHLON 6 /* MMX, 3DNOW, AMD 3DNOW ext, CMOV, SSE int; K7 core */
#define CPU_CYRIX_MII 7 /* MMX, CMOV */
#define CPU_CYRIX_III 8 /* MMX, Cyrix MMX ext, 3DNOW, CMOV */
/* AMD Palomino? MMX, 3DNOW, AMD 3DNOW ext, CMOV, SSE int, SSE flt; ? */
/* AMD Hammer family, presumably Athlon + SSE2; K8 core */
extern int cpu_detection(void);
#if __GNUC__ == 3
# if __GNUC_MINOR__ > 0
# warning Compilation with your version of gcc is untested,
# warning may fail or create incorrect code.
# endif
# define FPU_REGS , "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"
# define SECTION(x) section (x),
# define emms() do { asm volatile ("\temms\n" ::: "cc" FPU_REGS); } while(0)
#elif __GNUC__ == 2
# if __GNUC_MINOR__ < 90 /* gcc [2.7.2.3] */
# define FPU_REGS
# define SECTION(x)
# define emms() asm("\temms\n")
# define __builtin_expect(exp, c) (exp)
# elif __GNUC_MINOR__ < 95 /* egcs [2.91.66] */
# define FPU_REGS
# define SECTION(x)
# define emms() asm("\temms\n")
# define __builtin_expect(exp, c) (exp)
# else /* egcs [2.95.2] */
# define FPU_REGS , "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"
# define SECTION(x) section (x),
# define emms() do { asm volatile ("\temms\n" ::: "cc" FPU_REGS); } while(0)
# define __builtin_expect(exp, c) (exp)
# endif
#else
# error Sorry, your GCC does not exist.
#endif
#define CACHE_LINE 32 // power of two
static inline const unsigned int
swab32(unsigned int x)
{
if (__builtin_constant_p(x))
return (((x) & 0xFFUL) << 24) | (((x) & 0xFF00UL) << 8)
| (((x) & 0xFF0000UL) >> 8) | (((x) & 0xFF000000UL) >> 24);
asm volatile ("bswap %0" : "=r" (x) : "0" (x));
return x;
}
static inline const unsigned short
swab16(unsigned short x)
{
if (__builtin_constant_p(x))
return (((x) & 0xFFUL) << 8) | (((x) & 0xFF00UL) >> 8);
asm volatile ("xchgb %b0,%h0" : "=q" (x) : "0" (x));
return x;
}
#endif // MMX_H
--- NEW FILE ---
/*
* MPEG Real Time Encoder
* Simple Profiling
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: profile.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#include "../site_def.h"
#if PROFILING
#include <stdio.h>
typedef long long int tsc_t;
// Keep in mind TSC counts real time, not process time
tsc_t rdtsc(void)
{
tsc_t tsc;
asm ("\trdtsc\n" : "=A" (tsc));
return tsc;
}
#define COUNTERS 80
static char *labels[COUNTERS];
static tsc_t start[COUNTERS];
static long long sum[COUNTERS];
static int count[COUNTERS];
void
pr_start(int n, char *label)
{
if (n > COUNTERS)
return;
labels[n] = label;
start[n] = rdtsc();
}
void
pr_event(int n, char *label)
{
if (n > COUNTERS)
return;
labels[n] = label;
count[n]++;
}
void
pr_end(int n)
{
if (n > COUNTERS)
return;
sum[n] += rdtsc() - start[n];
count[n]++;
}
void
pr_report(void)
{
int i;
for (i = 0; i < COUNTERS; i++)
if (count[i]) {
if (sum[i] > 0)
fprintf(stderr, "%25s %02d: %10lld cycles %8d iterations (%4lld %06lld)\n",
labels[i], i, sum[i] / count[i], count[i], sum[i] / 1000000, sum[i] % 1000000);
else
fprintf(stderr, "%25s %02d: %8d iterations\n", labels[i], i, count[i]);
}
}
#endif /* PROFILING */
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "../site_def.h"
#if PROFILING
extern void pr_start(int n, char *label);
extern void pr_end(int n);
extern void pr_event(int n, char *label);
extern void pr_report(void);
#else
#define pr_start(n, label)
#define pr_end(n)
#define pr_event(n, label)
#define pr_report()
#endif
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: sync.c,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#include "../common/log.h"
#include "sync.h"
#include "math.h"
struct synchr synchr;
void
mp1e_sync_init(unsigned int modules, unsigned int time_base)
{
mucon_init(&synchr.mucon);
synchr.start_time = DBL_MAX;
synchr.stop_time = DBL_MAX;
synchr.front_time = -1;
synchr.modules = modules;
synchr.vote = 0;
assert(popcnt(time_base) <= 1);
synchr.time_base = time_base;
synchr.ref_warp = 1.0;
}
/**
* mp1e_sync_start:
* @time:
*
* Trigger initial synchronization at @time.
*
* Return value:
**/
bool
mp1e_sync_start(double time)
{
pthread_mutex_lock(&synchr.mucon.mutex);
if (synchr.modules == synchr.vote) {
pthread_mutex_unlock(&synchr.mucon.mutex);
return FALSE;
}
synchr.start_time = time;
pthread_cond_broadcast(&synchr.mucon.cond);
pthread_mutex_unlock(&synchr.mucon.mutex);
return TRUE;
}
/**
* mp1e_sync_stop:
* @time:
*
* Stop encoding at @time.
*
* Return value:
**/
bool
mp1e_sync_stop(double time)
{
pthread_mutex_lock(&synchr.mucon.mutex);
if (synchr.modules != synchr.vote ||
synchr.stop_time < DBL_MAX) {
pthread_mutex_unlock(&synchr.mucon.mutex);
return FALSE;
}
synchr.stop_time = MAX(time, synchr.front_time);
printv(4, "sync_stop at %f\n", synchr.stop_time);
pthread_mutex_unlock(&synchr.mucon.mutex);
return TRUE;
}
/**
* mp1e_sync_run_in:
* @str:
* @c:
* @frame_frac:
*
* Initial synchronization for *encoding modules*.
*
* Return value:
**/
bool
mp1e_sync_run_in(synchr_stream *str, consumer *c, int *frame_frac)
{
double first_time, last_time = -1;
double frame_period;
buffer *b;
c->fifo->start(c->fifo);
b = wait_full_buffer(c);
if (b->used <= 0)
FAIL("Premature end of file (%s)", c->fifo->name);
pthread_mutex_lock(&synchr.mucon.mutex);
first_time = b->time;
if (frame_frac)
*frame_frac = 0;
for (;;) {
if (b->time == 0.0) { // offline
if (synchr.start_time < DBL_MAX) {
printv(4, "SRI %02x: accept start_time %f for %f, voted %02x/%02x\n",
str->this_module, synchr.start_time, b->time,
synchr.vote, synchr.modules);
if ((synchr.vote |= str->this_module) == synchr.modules)
break;
pthread_cond_broadcast(&synchr.mucon.cond);
}
pthread_cond_wait(&synchr.mucon.cond, &synchr.mucon.mutex);
continue;
}
// XXX return FALSE
if (0) // because rte sends in duplicate b->time, but that's ok.
if (b->time <= last_time)
FAIL("Invalid timestamps from %s: ..., %f, %f\n",
c->fifo->name, last_time, b->time);
if ((b->time - first_time) > 2.0)
FAIL("Unable to sync %s after %f secs\n",
c->fifo->name, b->time - first_time);
last_time = b->time;
if (synchr.start_time < b->time) {
printv(4, "SRI %02x: propose start_time %f, was %f\n",
str->this_module, b->time, synchr.start_time);
synchr.start_time = b->time;
synchr.vote = str->this_module;
if (str->this_module == synchr.modules)
break;
pthread_cond_broadcast(&synchr.mucon.cond);
pthread_cond_wait(&synchr.mucon.cond, &synchr.mucon.mutex);
continue;
}
frame_period = str->frame_period + b->used * str->byte_period;
if (synchr.start_time < b->time + frame_period) {
printv(4, "SRI %02x: accept start_time %f for %f, voted %02x/%02x\n",
str->this_module, synchr.start_time, b->time,
synchr.vote, synchr.modules);
if ((synchr.vote |= str->this_module) == synchr.modules) {
if (frame_frac && str->byte_period > 0.0) {
double tfrac = synchr.start_time - b->time;
int sfrac = tfrac / str->byte_period;
*frame_frac = saturate(sfrac & -str->bytes_per_sample, 0, b->used - 1);
}
break;
}
}
printv(4, "SRI %02x: disagree start_time %f, discard %f\n",
str->this_module, synchr.start_time, b->time);
synchr.vote &= ~str->this_module;
pthread_mutex_unlock(&synchr.mucon.mutex);
send_empty_buffer(c, b);
b = wait_full_buffer(c);
if (b->used <= 0)
FAIL("Capture failure");
pthread_mutex_lock(&synchr.mucon.mutex);
}
str->start_ref = b->time;
pthread_mutex_unlock(&synchr.mucon.mutex);
pthread_cond_broadcast(&synchr.mucon.cond);
unget_full_buffer(c, b);
return TRUE;
}
--- NEW FILE ---
/*
* MPEG-1 Real Time Encoder
*
* Copyright (C) 1999-2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: sync.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef SYNC_H
#define SYNC_H
#include "threads.h"
#include "fifo.h"
#include "log.h"
typedef unsigned int sync_module;
struct synchr {
mucon mucon;
double start_time;
double stop_time;
double front_time;
sync_module modules;
sync_module vote;
double ref_warp;
sync_module time_base;
};
typedef struct synchr_stream {
sync_module this_module;
double start_ref;
double byte_period;
double frame_period;
int bytes_per_sample; /* power of 2 */
} synchr_stream;
/* GGG */
extern struct synchr synchr;
extern void mp1e_sync_init(unsigned int modules, unsigned int time_base);
extern bool mp1e_sync_start(double time);
extern bool mp1e_sync_stop(double time);
extern bool mp1e_sync_run_in(synchr_stream *str, consumer *c, int *frame_frac);
static inline int
mp1e_sync_break(synchr_stream *str, double time)
{
pthread_mutex_lock(&synchr.mucon.mutex);
if (time >= synchr.stop_time) {
pthread_mutex_unlock(&synchr.mucon.mutex);
printv(4, "sync_break %08x, %f, stop_time %f\n",
str->this_module, time, synchr.stop_time);
return TRUE;
}
if (time > synchr.front_time)
synchr.front_time = time;
pthread_mutex_unlock(&synchr.mucon.mutex);
return FALSE;
}
static inline double
mp1e_sync_drift(synchr_stream *str, double time, double elapsed)
{
double drift;
pthread_mutex_lock(&synchr.mucon.mutex);
printv(4, "SD%02d %f i%f o%f d%f\n", str->this_module,
time, (time - str->start_ref), elapsed,
(time - str->start_ref) - elapsed);
if (str->this_module == synchr.time_base) {
if (elapsed >= 0.5)
synchr.ref_warp = (time - str->start_ref) / elapsed;
drift = 0.0;
printv(4, "SD%02d ref_warp %f, %f s\n",
str->this_module, synchr.ref_warp,
(time - str->start_ref) - elapsed);
} else {
double ref_time = (time - str->start_ref) * synchr.ref_warp;
drift = elapsed - ref_time;
printv(4, "SD%02d ref %f o%f, drift %f s, %f ppm, %f units\n",
str->this_module, ref_time, elapsed, drift,
elapsed * 1e6 / ref_time - 1e6,
drift / (str->frame_period + str->byte_period));
}
pthread_mutex_unlock(&synchr.mucon.mutex);
return drift;
}
#endif /* SYNC_H */
--- NEW FILE ---
/*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: threads.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef THREADS_H
#define THREADS_H
#undef _GNU_SOURCE
#define _GNU_SOURCE 1
/* XXX for rwlocks, but the parent file
may have included pthread.h already */
#include <pthread.h>
#include "list.h"
typedef struct {
pthread_mutex_t mutex; /* attn: fast mutex */
pthread_cond_t cond;
list list;
} mucon;
static inline void
mucon_init(mucon *m)
{
pthread_mutex_init(&m->mutex, NULL);
pthread_cond_init(&m->cond, NULL);
init_list(&m->list);
}
static inline void
mucon_destroy(mucon *m)
{
pthread_mutex_destroy(&m->mutex);
pthread_cond_destroy(&m->cond);
}
static inline void
wait_mucon(mucon *m)
{
pthread_mutex_lock(&m->mutex);
pthread_cond_wait(&m->cond, &m->mutex);
pthread_mutex_unlock(&m->mutex);
}
#endif /* THREADS_H */
--- NEW FILE ---
/*
* Copyright (C) 1999-2000 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: types.h,v 1.1 2001/12/04 23:56:43 mswitch Exp $ */
#ifndef TYPES_H
#define TYPES_H
#include <stddef.h>
#undef TRUE
#undef FALSE
enum { FALSE, TRUE };
typedef unsigned char bool;
#define PARENT(ptr, type, member) \
((type *)(((char *) ptr) - offsetof(type, member)))
/*
* Same as libc assert, but also reports the caller.
*/
#ifdef NDEBUG
# define asserts(expr) ((void) 0)
#else
extern void asserts_fail(char *assertion, char *file, unsigned int line, char *function, void *caller);
#define asserts(expr) \
((void) ((expr) ? 0 : asserts_fail(#expr, __FILE__, __LINE__, \
__PRETTY_FUNCTION__, __builtin_return_address(0))))
#endif
#endif /* TYPES_H */
- Previous message: [Mplayer-cvslog] CVS: main/libmp1e/audio audio.h,NONE,1.1 fft.c,NONE,1.1 filter.c,NONE,1.1 filter_mmx.s,NONE,1.1 libaudio.h,NONE,1.1 mp2.c,NONE,1.1 mpeg.h,NONE,1.1 psycho.c,NONE,1.1 tables.c,NONE,1.1
- Next message: [Mplayer-cvslog] CVS: main/libmp1e/systems libsystems.h,NONE,1.1 mpeg.h,NONE,1.1 mpeg1.c,NONE,1.1 mpeg2.c,NONE,1.1 output.h,NONE,1.1 rte_output.c,NONE,1.1 systems.c,NONE,1.1 systems.h,NONE,1.1 vcd.c,NONE,1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the MPlayer-cvslog
mailing list