mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-19 22:30:06 +01:00
moved
git-svn-id: svn://code.dyne.org/veejay/trunk@60 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
This commit is contained in:
41
veejay-current/utils/Makefile.am
Normal file
41
veejay-current/utils/Makefile.am
Normal file
@@ -0,0 +1,41 @@
|
||||
# Process this file with Automake to produce Makefile.in
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
|
||||
noinst_LIBRARIES = libmotion.a libmjpegutils.a
|
||||
#lib_LIBRARIES = libmjpegutils.a
|
||||
|
||||
libmotion_MMXSSE = mblock_sumsq_mmx.s mblock_bsumsq_mmx.s mblock_bsad_mmx.s \
|
||||
mblock_sad_mmxe.s mblock_sad_mmx.s \
|
||||
mblock_sub44_sads_x86.c attributes.h
|
||||
|
||||
libmjpegutils_a_SOURCES = mjpeg_logging.c cpu_accel.c \
|
||||
mjpeg_logging.h mjpeg_types.h cpu_accel.h \
|
||||
yuv4mpeg.c yuv4mpeg_ratio.c \
|
||||
yuv4mpeg.h yuv4mpeg_intern.h \
|
||||
mpegconsts.c mpegconsts.h \
|
||||
mpegtimecode.c mpegtimecode.h
|
||||
|
||||
#include_HEADERS = yuv4mpeg.h mpegconsts.h mjpeg_logging.h mjpeg_types.h mpegtimecode.h
|
||||
|
||||
if HAVE_ASM_NASM
|
||||
if HAVE_ASM_MMX
|
||||
libmotion_SIMD = $(libmotion_MMXSSE)
|
||||
else
|
||||
mpeg2enc_SIMD =
|
||||
endif
|
||||
else
|
||||
mpeg2enc_SIMD =
|
||||
endif
|
||||
|
||||
libmotion_a_SOURCES = motionsearch.c $(libmotion_SIMD) mmx.h motionsearch.h fastintfns.h
|
||||
|
||||
EXTRA_DIST = videodev_mjpeg.h format_codes.h mblock_sub44_sads_x86_h.c mblock_sub44_sads_x86.h
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
%.o: %.s ; $(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
27
veejay-current/utils/attributes.h
Normal file
27
veejay-current/utils/attributes.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* attributes.h
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
|
||||
*
|
||||
* mpeg2dec 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.
|
||||
*
|
||||
* mpeg2dec 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//use gcc attribs to align critical data structures
|
||||
#ifdef ATTRIBUTE_ALIGNED_MAX
|
||||
#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
|
||||
#else
|
||||
#define ATTR_ALIGN(align)
|
||||
#endif
|
||||
161
veejay-current/utils/cpu_accel.c
Normal file
161
veejay-current/utils/cpu_accel.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* cpu_accel.c
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
|
||||
*
|
||||
* mpeg2dec 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.
|
||||
*
|
||||
* mpeg2dec 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include "cpu_accel.h"
|
||||
|
||||
#ifdef HAVE_X86CPU
|
||||
|
||||
#include "mjpeg_types.h"
|
||||
|
||||
/* Some miscelaneous stuff to allow checking whether SSE instructions cause
|
||||
illegal instruction errors.
|
||||
*/
|
||||
|
||||
static sigjmp_buf sigill_recover;
|
||||
|
||||
static RETSIGTYPE sigillhandler(int sig )
|
||||
{
|
||||
siglongjmp( sigill_recover, 1 );
|
||||
}
|
||||
|
||||
typedef RETSIGTYPE (*__sig_t)(int);
|
||||
|
||||
static int testsseill()
|
||||
{
|
||||
int illegal;
|
||||
#if defined(__CYGWIN__)
|
||||
/* SSE causes a crash on CYGWIN, apparently.
|
||||
Perhaps the wrong signal is being caught or something along
|
||||
those line ;-) or maybe SSE itself won't work...
|
||||
*/
|
||||
illegal = 1;
|
||||
#else
|
||||
__sig_t old_handler = signal( SIGILL, sigillhandler);
|
||||
if( sigsetjmp( sigill_recover, 1 ) == 0 )
|
||||
{
|
||||
asm ( "movups %xmm0, %xmm0" );
|
||||
illegal = 0;
|
||||
}
|
||||
else
|
||||
illegal = 1;
|
||||
signal( SIGILL, old_handler );
|
||||
#endif
|
||||
return illegal;
|
||||
}
|
||||
|
||||
static int x86_accel (void)
|
||||
{
|
||||
int32_t eax, ebx, ecx, edx;
|
||||
int32_t AMD;
|
||||
int32_t caps;
|
||||
|
||||
#define cpuid(op,eax,ebx,ecx,edx) \
|
||||
asm ("cpuid" \
|
||||
: "=a" (eax), \
|
||||
"=b" (ebx), \
|
||||
"=c" (ecx), \
|
||||
"=d" (edx) \
|
||||
: "a" (op) \
|
||||
: "cc")
|
||||
|
||||
asm ("pushfl\n\t"
|
||||
"popl %0\n\t"
|
||||
"movl %0,%1\n\t"
|
||||
"xorl $0x200000,%0\n\t"
|
||||
"pushl %0\n\t"
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl %0"
|
||||
: "=a" (eax),
|
||||
"=b" (ebx)
|
||||
:
|
||||
: "cc");
|
||||
|
||||
|
||||
if (eax == ebx) // no cpuid
|
||||
return 0;
|
||||
|
||||
cpuid (0x00000000, eax, ebx, ecx, edx);
|
||||
if (!eax) // vendor string only
|
||||
return 0;
|
||||
|
||||
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
|
||||
|
||||
cpuid (0x00000001, eax, ebx, ecx, edx);
|
||||
if (! (edx & 0x00800000)) // no MMX
|
||||
return 0;
|
||||
|
||||
caps = ACCEL_X86_MMX;
|
||||
/* If SSE capable CPU has same MMX extensions as AMD
|
||||
and then some. However, to use SSE O.S. must have signalled
|
||||
it use of FXSAVE/FXRSTOR through CR4.OSFXSR and hence FXSR (bit 24)
|
||||
here
|
||||
*/
|
||||
if ((edx & 0x02000000))
|
||||
caps = ACCEL_X86_MMX | ACCEL_X86_MMXEXT;
|
||||
if( (edx & 0x03000000) == 0x03000000 )
|
||||
{
|
||||
/* Check whether O.S. has SSE support... has to be done with
|
||||
exception 'cos those Intel morons put the relevant bit
|
||||
in a reg that is only accesible in ring 0... doh!
|
||||
*/
|
||||
if( !testsseill() )
|
||||
caps |= ACCEL_X86_SSE;
|
||||
}
|
||||
|
||||
cpuid (0x80000000, eax, ebx, ecx, edx);
|
||||
if (eax < 0x80000001) // no extended capabilities
|
||||
return caps;
|
||||
|
||||
cpuid (0x80000001, eax, ebx, ecx, edx);
|
||||
|
||||
if (edx & 0x80000000)
|
||||
caps |= ACCEL_X86_3DNOW;
|
||||
|
||||
if (AMD && (edx & 0x00400000)) // AMD MMX extensions
|
||||
{
|
||||
caps |= ACCEL_X86_MMXEXT;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cpu_accel (void)
|
||||
{
|
||||
#ifdef HAVE_X86CPU
|
||||
static int got_accel = 0;
|
||||
static int accel;
|
||||
|
||||
if (!got_accel) {
|
||||
got_accel = 1;
|
||||
accel = x86_accel ();
|
||||
}
|
||||
|
||||
return accel;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
30
veejay-current/utils/cpu_accel.h
Normal file
30
veejay-current/utils/cpu_accel.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* cpu_accel.h
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* This file was part of mpeg2dec, a free MPEG-2 video stream decoder.
|
||||
*
|
||||
* mpeg2dec 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.
|
||||
*
|
||||
* mpeg2dec 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// x86 accelerations
|
||||
#define ACCEL_X86_MMX 0x80000000
|
||||
#define ACCEL_X86_3DNOW 0x40000000
|
||||
#define ACCEL_X86_MMXEXT 0x20000000
|
||||
#define ACCEL_X86_SSE 0x10000000
|
||||
|
||||
int cpu_accel (void);
|
||||
32
veejay-current/utils/fastintfns.h
Normal file
32
veejay-current/utils/fastintfns.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* fast int primitives. min,max,abs,samesign
|
||||
*
|
||||
* WARNING: Assumes 2's complement arithmetic.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static __inline__ int intmax( register int x, register int y )
|
||||
{
|
||||
return x < y ? y : x;
|
||||
}
|
||||
|
||||
static __inline__ int intmin( register int x, register int y )
|
||||
{
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
static __inline__ int intabs( register int x )
|
||||
{
|
||||
return x < 0 ? -x : x;
|
||||
}
|
||||
|
||||
#define fabsshift ((8*sizeof(unsigned int))-1)
|
||||
|
||||
#define signmask(x) (((int)x)>>fabsshift)
|
||||
static __inline__ int intsamesign(int x, int y)
|
||||
{
|
||||
return (y+(signmask(x) & -(y<<1)));
|
||||
}
|
||||
#undef signmask
|
||||
#undef fabsshift
|
||||
|
||||
38
veejay-current/utils/format_codes.h
Normal file
38
veejay-current/utils/format_codes.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
$Id: format_codes.h,v 1.1.1.1 2004/10/27 23:48:57 niels Exp $
|
||||
|
||||
Copyright (C) 2001 Andrew Stevens <andrew.stevens@planet-interkom.de>
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __FORMAT_CODES_H__
|
||||
#define __FORMAT_CODES_H__
|
||||
|
||||
#define MPEG_FORMAT_MPEG1 0
|
||||
#define MPEG_FORMAT_VCD 1
|
||||
#define MPEG_FORMAT_VCD_NSR 2
|
||||
#define MPEG_FORMAT_MPEG2 3
|
||||
#define MPEG_FORMAT_SVCD 4
|
||||
#define MPEG_FORMAT_SVCD_NSR 5
|
||||
#define MPEG_FORMAT_VCD_STILL 6
|
||||
#define MPEG_FORMAT_SVCD_STILL 7
|
||||
#define MPEG_FORMAT_DVD 8
|
||||
|
||||
#define MPEG_FORMAT_FIRST 0
|
||||
#define MPEG_FORMAT_LAST 8
|
||||
|
||||
#define MPEG_STILLS_FORMAT(x) (x==MPEG_FORMAT_VCD_STILL||x==MPEG_FORMAT_SVCD_STILL)
|
||||
#endif /* __FORMAT_CODES_H__ */
|
||||
329
veejay-current/utils/mblock_bsad_mmx.s
Normal file
329
veejay-current/utils/mblock_bsad_mmx.s
Normal file
@@ -0,0 +1,329 @@
|
||||
;
|
||||
; bdist1_mmx.s: mmX optimized bidirectional absolute distance sum
|
||||
;
|
||||
; Original believed to be Copyright (C) 2000 Brent Byeler
|
||||
;
|
||||
; This program is free software; you can reaxstribute 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
|
||||
;/*
|
||||
; * absolute difference error between a (16*h) block and a bidirectional
|
||||
; * prediction
|
||||
; *
|
||||
; * p2: address of top left pel of block
|
||||
; * pf,hxf,hyf: address and half pel flags of forward ref. block
|
||||
; * pb,hxb,hyb: address and half pel flags of backward ref. block
|
||||
; * h: height of block
|
||||
; * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb
|
||||
; * mmX version
|
||||
; */
|
||||
|
||||
;int bsad_mmx(
|
||||
;unsigned char *pf, unsigned char *pb, unsigned char *p2,
|
||||
;int lx, int hxf, int hyf, int hxb, int hyb, int h)
|
||||
;{
|
||||
; unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc;
|
||||
|
||||
; Handy macros for readbility
|
||||
|
||||
%define pf [ebp+8]
|
||||
%define pb [ebp+12]
|
||||
%define p2 [ebp+16]
|
||||
%define lx [ebp+20]
|
||||
%define hxf [ebp+24]
|
||||
%define hyf [ebp+28]
|
||||
%define hxb [ebp+32]
|
||||
%define hyb [ebp+36]
|
||||
%define h [ebp+40]
|
||||
|
||||
|
||||
%define pfa [esp+4]
|
||||
%define pfb [esp+8]
|
||||
%define pfc [esp+12]
|
||||
%define pba [esp+16]
|
||||
%define pbb [esp+20]
|
||||
%define pbc [esp+24]
|
||||
|
||||
SECTION .text
|
||||
global bsad_mmx
|
||||
|
||||
align 32
|
||||
bsad_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
;;
|
||||
;; Make space for local variables on stack
|
||||
sub esp, 32
|
||||
|
||||
|
||||
mov edx, hxb
|
||||
mov eax, hxf
|
||||
mov esi, lx
|
||||
|
||||
mov ecx, pf
|
||||
add ecx, eax
|
||||
mov pfa, ecx
|
||||
mov ecx, esi
|
||||
imul ecx, hyf
|
||||
mov ebx, pf
|
||||
add ecx, ebx
|
||||
mov pfb, ecx
|
||||
add eax, ecx
|
||||
mov pfc, eax
|
||||
mov eax, pb
|
||||
add eax, edx
|
||||
mov pba, eax
|
||||
mov eax, esi
|
||||
imul eax, hyb
|
||||
mov ecx, pb
|
||||
add eax, ecx
|
||||
mov pbb, eax
|
||||
add edx, eax
|
||||
mov pbc, edx
|
||||
xor esi, esi ; esi is "s" the accumulator
|
||||
mov eax, esi
|
||||
|
||||
mov edi, h
|
||||
test edi, edi ; h = 0?
|
||||
jle near bsadexit
|
||||
|
||||
pxor mm7, mm7
|
||||
pxor mm6, mm6
|
||||
pcmpeqw mm5, mm5
|
||||
psubw mm6, mm5
|
||||
psllw mm6, 1
|
||||
|
||||
bsadtop:
|
||||
mov eax, pf
|
||||
mov ebx, pfa
|
||||
mov ecx, pfb
|
||||
mov edx, pfc
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [ecx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [edx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 2
|
||||
psrlw mm1, 2
|
||||
mov eax, pb
|
||||
mov ebx, pba
|
||||
mov ecx, pbb
|
||||
mov edx, pbc
|
||||
movq mm2, [eax]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
movq mm4, [ebx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [ecx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [edx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
paddw mm2, mm6
|
||||
paddw mm3, mm6
|
||||
psrlw mm2, 2
|
||||
psrlw mm3, 2
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
psrlw mm6, 1
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psllw mm6, 1
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
packuswb mm0, mm1
|
||||
|
||||
mov eax, p2
|
||||
movq mm1, [eax]
|
||||
movq mm2, mm0
|
||||
psubusb mm0, mm1
|
||||
psubusb mm1, mm2
|
||||
por mm0, mm1
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
paddw mm0, mm1
|
||||
movq mm1, mm0
|
||||
punpcklwd mm0, mm7
|
||||
punpckhwd mm1, mm7
|
||||
|
||||
paddd mm0, mm1
|
||||
movd eax, mm0
|
||||
psrlq mm0, 32
|
||||
movd ebx, mm0
|
||||
add esi, eax
|
||||
add esi, ebx
|
||||
mov eax, pf
|
||||
mov ebx, pfa
|
||||
mov ecx, pfb
|
||||
mov edx, pfc
|
||||
movq mm0, [eax+8]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [ebx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [ecx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [edx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 2
|
||||
psrlw mm1, 2
|
||||
mov eax, pb
|
||||
mov ebx, pba
|
||||
mov ecx, pbb
|
||||
mov edx, pbc
|
||||
movq mm2, [eax+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
movq mm4, [ebx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [ecx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [edx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
paddw mm2, mm6
|
||||
paddw mm3, mm6
|
||||
psrlw mm2, 2
|
||||
psrlw mm3, 2
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
psrlw mm6, 1
|
||||
paddW mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psllw mm6, 1
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
packuswb mm0, mm1
|
||||
mov eax, p2
|
||||
movq mm1, [eax+8]
|
||||
movq mm2, mm0
|
||||
psubusb mm0, mm1
|
||||
psubusb mm1, mm2
|
||||
por mm0, mm1
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
paddw mm0, mm1
|
||||
movq mm1, mm0
|
||||
punpcklwd mm0, mm7
|
||||
punpckhwd mm1, mm7
|
||||
paddd mm0, mm1
|
||||
movd eax, mm0
|
||||
psrlq mm0, 32
|
||||
movd ebx, mm0
|
||||
add esi, eax
|
||||
add esi, ebx
|
||||
|
||||
mov eax, lx
|
||||
add p2, eax
|
||||
add pf, eax
|
||||
add pfa, eax
|
||||
add pfb, eax
|
||||
add pfc, eax
|
||||
add pb, eax
|
||||
add pba, eax
|
||||
add pbb, eax
|
||||
add pbc, eax
|
||||
|
||||
dec edi
|
||||
jg near bsadtop
|
||||
mov eax, esi
|
||||
|
||||
bsadexit:
|
||||
|
||||
|
||||
;;
|
||||
;; Get rid of local variables
|
||||
add esp, 32
|
||||
|
||||
;; Retore (callee saves convention...)
|
||||
;;
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
|
||||
pop ebp ; restore stack pointer
|
||||
|
||||
emms ; clear mmx registers
|
||||
ret
|
||||
|
||||
|
||||
327
veejay-current/utils/mblock_bsumsq_mmx.s
Normal file
327
veejay-current/utils/mblock_bsumsq_mmx.s
Normal file
@@ -0,0 +1,327 @@
|
||||
;
|
||||
; bdist2_mmx.s: MMX optimized bidirectional squared distance sum
|
||||
;
|
||||
; Original believed to be Copyright (C) 2000 Brent Byeler
|
||||
;
|
||||
; This program is free software; you can reaxstribute 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
|
||||
;/*
|
||||
; * squared error between a (16*h) block and a bidirectional
|
||||
; * prediction
|
||||
; *
|
||||
; * p2: address of top left pel of block
|
||||
; * pf,hxf,hyf: address and half pel flags of forward ref. block
|
||||
; * pb,hxb,hyb: address and half pel flags of backward ref. block
|
||||
; * h: height of block
|
||||
; * lx: distance (in bytes) of vertically adjacent pels in p2,pf,pb
|
||||
; * mmX version
|
||||
; */
|
||||
|
||||
;int bsumsq_mmx(
|
||||
;unsigned char *pf, unsigned char *pb, unsigned char *p2,
|
||||
;int lx, int hxf, int hyf, int hxb, int hyb, int h)
|
||||
;{
|
||||
; unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc;
|
||||
; int s;
|
||||
|
||||
; Handy macros for readbility
|
||||
|
||||
%define pf [ebp+8]
|
||||
%define pb [ebp+12]
|
||||
%define p2 [ebp+16]
|
||||
%define lx [ebp+20]
|
||||
%define hxf [ebp+24]
|
||||
%define hyf [ebp+28]
|
||||
%define hxb [ebp+32]
|
||||
%define hyb [ebp+36]
|
||||
%define h [ebp+40]
|
||||
|
||||
|
||||
%define pfa [esp+4]
|
||||
%define pfb [esp+8]
|
||||
%define pfc [esp+12]
|
||||
%define pba [esp+16]
|
||||
%define pbb [esp+20]
|
||||
%define pbc [esp+24]
|
||||
|
||||
SECTION .text
|
||||
global bsumsq_mmx
|
||||
|
||||
align 32
|
||||
bsumsq_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
;;
|
||||
;; Make space for local variables on stack
|
||||
sub esp, 32
|
||||
|
||||
mov edx, hxb
|
||||
mov eax, hxf
|
||||
mov esi, lx
|
||||
|
||||
mov ecx, pf
|
||||
add ecx, eax
|
||||
mov pfa, ecx
|
||||
mov ecx, esi
|
||||
imul ecx, hyf
|
||||
mov ebx, pf
|
||||
add ecx, ebx
|
||||
mov pfb, ecx
|
||||
add eax, ecx
|
||||
mov pfc, eax
|
||||
mov eax, pb
|
||||
add eax, edx
|
||||
mov pba, eax
|
||||
mov eax, esi
|
||||
imul eax, hyb
|
||||
mov ecx, pb
|
||||
add eax, ecx
|
||||
mov pbb, eax
|
||||
add edx, eax
|
||||
mov pbc, edx
|
||||
xor esi, esi ; esi = s (accumulated sym)
|
||||
mov eax, esi
|
||||
|
||||
mov edi, h
|
||||
test edi, edi ; h = 0?
|
||||
jle near bsumsqexit
|
||||
|
||||
pxor mm7, mm7
|
||||
pxor mm6, mm6
|
||||
pcmpeqw mm5, mm5
|
||||
psubw mm6, mm5
|
||||
psllw mm6, 1
|
||||
|
||||
bsumsqtop:
|
||||
mov eax, pf
|
||||
mov ebx, pfa
|
||||
mov ecx, pfb
|
||||
mov edx, pfc
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [ecx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [edx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 2
|
||||
psrlw mm1, 2
|
||||
|
||||
mov eax, pb
|
||||
mov ebx, pba
|
||||
mov ecx, pbb
|
||||
mov edx, pbc
|
||||
movq mm2, [eax]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
movq mm4, [ebx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [ecx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [edx]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
|
||||
paddw mm2, mm6
|
||||
paddw mm3, mm6
|
||||
psrlw mm2, 2
|
||||
psrlw mm3, 2
|
||||
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
psrlw mm6, 1
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psllw mm6, 1
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
|
||||
mov eax, p2
|
||||
movq mm2, [eax]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movd eax, mm0
|
||||
psrlq mm0, 32
|
||||
movd ebx, mm0
|
||||
add esi, eax
|
||||
add esi, ebx
|
||||
|
||||
mov eax, pf
|
||||
mov ebx, pfa
|
||||
mov ecx, pfb
|
||||
mov edx, pfc
|
||||
movq mm0, [eax+8]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [ebx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [ecx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [edx+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 2
|
||||
psrlw mm1, 2
|
||||
|
||||
mov eax, pb
|
||||
mov ebx, pba
|
||||
mov ecx, pbb
|
||||
mov edx, pbc
|
||||
movq mm2, [eax+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
movq mm4, [ebx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [ecx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
movq mm4, [edx+8]
|
||||
movq mm5, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm5, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm5
|
||||
paddw mm2, mm6
|
||||
paddw mm3, mm6
|
||||
psrlw mm2, 2
|
||||
psrlw mm3, 2
|
||||
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
psrlw mm6, 1
|
||||
paddW mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psllw mm6, 1
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
|
||||
mov eax, p2
|
||||
movq mm2, [eax+8]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movd eax, mm0
|
||||
psrlq mm0, 32
|
||||
movd ebx, mm0
|
||||
add esi, eax
|
||||
add esi, ebx
|
||||
|
||||
mov eax, lx
|
||||
add p2, eax
|
||||
add pf, eax
|
||||
add pfa, eax
|
||||
add pfb, eax
|
||||
add pfc, eax
|
||||
add pb, eax
|
||||
add pba, eax
|
||||
add pbb, eax
|
||||
add pbc, eax
|
||||
|
||||
dec edi
|
||||
jg near bsumsqtop
|
||||
mov eax, esi
|
||||
|
||||
bsumsqexit:
|
||||
|
||||
;;
|
||||
;; Get rid of local variables
|
||||
add esp, 32
|
||||
|
||||
;; Retore (callee saves convention...)
|
||||
;;
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
|
||||
pop ebp ; restore stack pointer
|
||||
|
||||
emms ; clear mmx registers
|
||||
ret
|
||||
|
||||
1094
veejay-current/utils/mblock_sad_mmx.s
Normal file
1094
veejay-current/utils/mblock_sad_mmx.s
Normal file
File diff suppressed because it is too large
Load Diff
1002
veejay-current/utils/mblock_sad_mmxe.s
Normal file
1002
veejay-current/utils/mblock_sad_mmxe.s
Normal file
File diff suppressed because it is too large
Load Diff
245
veejay-current/utils/mblock_sub44_sads_x86.c
Normal file
245
veejay-current/utils/mblock_sub44_sads_x86.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
*
|
||||
* mblock_sub44_sads.c
|
||||
* Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
|
||||
*
|
||||
* Fast block sum-absolute difference computation for a rectangular area 4*x
|
||||
* by y where y > h against a 4 by h block.
|
||||
*
|
||||
* Used for 4*4 sub-sampled motion compensation calculations.
|
||||
*
|
||||
* This is actually just a shell that uses templates from the included
|
||||
* file "mblock_sub44_sads_x86_h.c". I didn't trust the compiler to do a good
|
||||
* job on nested inlining. One day I'll experiment.
|
||||
*
|
||||
*
|
||||
* This file is part of mpeg2enc, a free MPEG-2 video stream encoder
|
||||
* based on the original MSSG reference design
|
||||
*
|
||||
* mpeg2enc is free software; you can redistribute new parts
|
||||
* and/or modify 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.
|
||||
*
|
||||
* mpeg2dec 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.
|
||||
*
|
||||
* See the files for those sections (c) MSSG
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "mjpeg_types.h"
|
||||
#include "attributes.h"
|
||||
#include "mmx.h"
|
||||
#include "fastintfns.h"
|
||||
#include "motionsearch.h"
|
||||
#include "mblock_sub44_sads_x86.h"
|
||||
|
||||
/*
|
||||
Register usage:
|
||||
mm0-mm3 Hold the current row
|
||||
mm4 Used for accumulating partial SAD
|
||||
mm7 Holds zero
|
||||
*/
|
||||
|
||||
static inline void mmx_zero_reg (void)
|
||||
{
|
||||
/* load 0 into mm7 */
|
||||
pxor_r2r (mm7, mm7);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a 8*4 block of 4*4 sub-sampled pels (qpels) into the MMX
|
||||
* registers
|
||||
*
|
||||
*/
|
||||
|
||||
static __inline__ void load_blk(uint8_t *blk,uint32_t rowstride,int h)
|
||||
{
|
||||
movq_m2r( *blk, mm0);
|
||||
blk += rowstride;
|
||||
movq_m2r( *blk, mm1);
|
||||
if( h == 2 )
|
||||
return;
|
||||
blk += rowstride;
|
||||
movq_m2r( *blk, mm2);
|
||||
blk += rowstride;
|
||||
movq_m2r( *blk, mm3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a shift right on the 4*4 block in the MMX registers
|
||||
* We do this as a macro as otherwise we get warnings from the
|
||||
* pre-optimised asm generated.
|
||||
*/
|
||||
#define shift_blk(shift)\
|
||||
psrlq_i2r( shift,mm0);\
|
||||
psrlq_i2r( shift,mm1);\
|
||||
psrlq_i2r( shift,mm2);\
|
||||
psrlq_i2r( shift,mm3);
|
||||
|
||||
/*
|
||||
* Compute the Sum absolute differences between the 4*h block in
|
||||
* the MMX registers (4 least sig. bytes in mm0..mm3)
|
||||
*
|
||||
* and the 4*h block pointed to by refblk
|
||||
*
|
||||
* h == 2 || h == 4
|
||||
*
|
||||
* TODO: Currently always loads and shifts 4*4 even if 4*2 is required.
|
||||
*
|
||||
*/
|
||||
|
||||
static __inline__ int qblock_sad_mmxe(uint8_t *refblk,
|
||||
uint32_t h,
|
||||
uint32_t rowstride)
|
||||
{
|
||||
int res;
|
||||
pxor_r2r (mm4,mm4);
|
||||
|
||||
movq_r2r (mm0,mm5); /* First row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
pxor_r2r ( mm7, mm7);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
psadbw_r2r ( mm5, mm6);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
|
||||
|
||||
movq_r2r (mm1,mm5); /* Second row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
psadbw_r2r ( mm5, mm6);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
if( h == 4 )
|
||||
{
|
||||
|
||||
movq_r2r (mm2,mm5); /* Third row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
psadbw_r2r ( mm5, mm6);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
|
||||
movq_r2r (mm3,mm5); /* Fourth row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
psadbw_r2r ( mm5, mm6);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
}
|
||||
movd_r2m ( mm4, res );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ int qblock_sad_mmx(uint8_t *refblk,
|
||||
uint32_t h,
|
||||
uint32_t rowstride)
|
||||
{
|
||||
int res;
|
||||
pxor_r2r (mm4,mm4);
|
||||
|
||||
movq_r2r (mm0,mm5); /* First row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
pxor_r2r ( mm7, mm7);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
|
||||
movq_r2r ( mm5, mm7);
|
||||
psubusw_r2r ( mm6, mm5);
|
||||
|
||||
psubusw_r2r ( mm7, mm6);
|
||||
|
||||
paddw_r2r ( mm5, mm4);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
|
||||
|
||||
movq_r2r (mm1,mm5); /* Second row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
pxor_r2r ( mm7, mm7);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
movq_r2r ( mm5, mm7);
|
||||
psubusw_r2r ( mm6, mm5);
|
||||
psubusw_r2r ( mm7, mm6);
|
||||
paddw_r2r ( mm5, mm4);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
if( h == 4 )
|
||||
{
|
||||
|
||||
movq_r2r (mm2,mm5); /* Third row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
pxor_r2r ( mm7, mm7);
|
||||
refblk += rowstride;
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
movq_r2r ( mm5, mm7);
|
||||
psubusw_r2r ( mm6, mm5);
|
||||
psubusw_r2r ( mm7, mm6);
|
||||
paddw_r2r ( mm5, mm4);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
|
||||
movq_r2r (mm3,mm5); /* Fourth row */
|
||||
movd_m2r (*refblk, mm6);
|
||||
pxor_r2r ( mm7, mm7);
|
||||
punpcklbw_r2r ( mm7, mm5);
|
||||
punpcklbw_r2r ( mm7, mm6);
|
||||
movq_r2r ( mm5, mm7);
|
||||
psubusw_r2r ( mm6, mm5);
|
||||
psubusw_r2r ( mm7, mm6);
|
||||
paddw_r2r ( mm5, mm4);
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
}
|
||||
|
||||
|
||||
movq_r2r ( mm4, mm5 );
|
||||
psrlq_i2r ( 32, mm5 );
|
||||
paddw_r2r ( mm5, mm4 );
|
||||
movq_r2r ( mm4, mm6 );
|
||||
psrlq_i2r ( 16, mm6 );
|
||||
paddw_r2r ( mm6, mm4 );
|
||||
movd_r2m ( mm4, res );
|
||||
|
||||
return res & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do the Extended MMX versions
|
||||
*/
|
||||
#define SIMD_SUFFIX(x) x##_mmxe
|
||||
#include "mblock_sub44_sads_x86_h.c"
|
||||
#undef SIMD_SUFFIX
|
||||
/*
|
||||
* Do the original MMX versions
|
||||
*/
|
||||
#define SIMD_SUFFIX(x) x##_mmx
|
||||
#include "mblock_sub44_sads_x86_h.c"
|
||||
#undef SIMD_SUFFIX
|
||||
|
||||
|
||||
|
||||
|
||||
39
veejay-current/utils/mblock_sub44_sads_x86.h
Normal file
39
veejay-current/utils/mblock_sub44_sads_x86.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* (C) 2000/2002 Andrew Stevens */
|
||||
|
||||
/* This software 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MBLOCK_SUB44_SADS_X86_H__
|
||||
#define __MBLOCK_SUB44_SADS_X86__
|
||||
|
||||
#include <config.h>
|
||||
#include "mjpeg_types.h"
|
||||
|
||||
int mblocks_sub44_mests_mmxe( uint8_t *blk, uint8_t *ref,
|
||||
int ilow, int jlow,
|
||||
int ihigh, int jhigh,
|
||||
int h, int rowstride,
|
||||
int threshold,
|
||||
me_result_s *resvec);
|
||||
int mblocks_sub44_mests_mmx( uint8_t *blk, uint8_t *ref,
|
||||
int ilow, int jlow,
|
||||
int ihigh, int jhigh,
|
||||
int threshold,
|
||||
int h, int rowstride,
|
||||
me_result_s *resvec);
|
||||
|
||||
#endif
|
||||
98
veejay-current/utils/mblock_sub44_sads_x86_h.c
Normal file
98
veejay-current/utils/mblock_sub44_sads_x86_h.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* mblock_sub44_sads_x86_h.c
|
||||
* Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
|
||||
*
|
||||
* Fast block sum-absolute difference computation for a rectangular area 4*x
|
||||
* by y where y > h against a 4 by h block.
|
||||
*
|
||||
* Used for 4*4 sub-sampled motion compensation calculations.
|
||||
*
|
||||
*
|
||||
* This file is part of mpeg2enc, a free MPEG-2 video stream encoder
|
||||
* based on the original MSSG reference design
|
||||
*
|
||||
* mpeg2enc is free software; you can redistribute new parts
|
||||
* and/or modify 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.
|
||||
*
|
||||
* mpeg2enc 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.
|
||||
*
|
||||
* See the files for those sections (c) MSSG
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Generates a vector sad's for 4*4 sub-sampled pel (qpel) data (with
|
||||
* co-ordinates and top-left qpel address) from specified rectangle
|
||||
* against a specified 16*h pel (4*4 qpel) reference block. The
|
||||
* generated vector contains results only for those sad's that fall
|
||||
* below twice the running best sad and are aligned on 8-pel
|
||||
* boundaries
|
||||
*
|
||||
* Invariant: blk points to top-left sub-sampled pel for macroblock
|
||||
* at (ilow,ihigh)
|
||||
* i{low,high) j(low,high) must be multiples of 4.
|
||||
*
|
||||
* sad = Sum Absolute Differences
|
||||
*
|
||||
* NOTES: for best efficiency i{low,high) should be multiples of 16.
|
||||
*
|
||||
* */
|
||||
|
||||
int SIMD_SUFFIX(mblocks_sub44_mests)( uint8_t *blk, uint8_t *ref,
|
||||
int ilow,int jlow,
|
||||
int ihigh, int jhigh,
|
||||
int h, int rowstride,
|
||||
int threshold,
|
||||
me_result_s *resvec)
|
||||
{
|
||||
int32_t x,y;
|
||||
uint8_t *currowblk = blk;
|
||||
uint8_t *curblk;
|
||||
me_result_s *cres = resvec;
|
||||
int gridrowstride = (rowstride);
|
||||
int weight;
|
||||
|
||||
for( y=jlow; y <= jhigh ; y+=4)
|
||||
{
|
||||
curblk = currowblk;
|
||||
for( x = ilow; x <= ihigh; x += 4)
|
||||
{
|
||||
if( (x & 15) == (ilow & 15) )
|
||||
{
|
||||
load_blk( curblk, rowstride, h );
|
||||
}
|
||||
weight = SIMD_SUFFIX(qblock_sad)(ref, h, rowstride);
|
||||
if( weight <= threshold )
|
||||
{
|
||||
threshold = intmin(weight<<2,threshold);
|
||||
/* Rough and-ready absolute distance penalty */
|
||||
/* NOTE: This penalty is *vital* to correct operation
|
||||
as otherwise the sub-mean filtering won't work on very
|
||||
uniform images.
|
||||
*/
|
||||
cres->weight = (uint16_t)(weight+(intmax(intabs(x),intabs(y))<<2));
|
||||
cres->x = (uint8_t)x;
|
||||
cres->y = (uint8_t)y;
|
||||
++cres;
|
||||
}
|
||||
curblk += 1;
|
||||
shift_blk(8);
|
||||
}
|
||||
currowblk += gridrowstride;
|
||||
}
|
||||
emms();
|
||||
return cres - resvec;
|
||||
}
|
||||
|
||||
#undef concat
|
||||
673
veejay-current/utils/mblock_sumsq_mmx.s
Normal file
673
veejay-current/utils/mblock_sumsq_mmx.s
Normal file
@@ -0,0 +1,673 @@
|
||||
;
|
||||
; dist2_mmx.s: mmX optimized squared distance sum
|
||||
;
|
||||
; Original believed to be Copyright (C) 2000 Brent Byeler
|
||||
;
|
||||
; This program is free software; you can reaxstribute 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
|
||||
; total squared difference between two (16*h) blocks
|
||||
; including optional half pel interpolation of [ebp+8] ; blk1 (hx,hy)
|
||||
; blk1,blk2: addresses of top left pels of both blocks
|
||||
; lx: distance (in bytes) of vertically adjacent pels
|
||||
; hx,hy: flags for horizontal and/or vertical interpolation
|
||||
; h: height of block (usually 8 or 16)
|
||||
; mmX version
|
||||
|
||||
global sumsq_mmx
|
||||
; int sumsq_mmx(unsigned char *blk1, unsigned char *blk2,
|
||||
; int lx, int hx, int hy, int h)
|
||||
|
||||
; mm7 = 0
|
||||
|
||||
; eax = pblk1
|
||||
; ebx = pblk2
|
||||
; ecx = temp
|
||||
; edx = distance_sum
|
||||
; edi = h
|
||||
; esi = lx
|
||||
|
||||
;;
|
||||
;; private constants needed
|
||||
;;
|
||||
|
||||
SECTION .data
|
||||
align 16
|
||||
twos:
|
||||
dw 2
|
||||
dw 2
|
||||
dw 2
|
||||
dw 2
|
||||
|
||||
SECTION .text
|
||||
|
||||
align 32
|
||||
sumsq_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, [ebp+16] ; lx
|
||||
mov eax, [ebp+20] ; hx
|
||||
mov edx, [ebp+24] ; hy
|
||||
mov edi, [ebp+28] ; h
|
||||
|
||||
pxor mm5, mm5 ; sum
|
||||
test edi, edi ; h = 0?
|
||||
jle near d2exit
|
||||
|
||||
pxor mm7, mm7 ; get zeros i mm7
|
||||
|
||||
test eax, eax ; hx != 0?
|
||||
jne near d2is10
|
||||
test edx, edx ; hy != 0?
|
||||
jne near d2is10
|
||||
|
||||
mov eax, [ebp+8]
|
||||
mov ebx, [ebp+12]
|
||||
jmp d2top00
|
||||
|
||||
align 32
|
||||
d2top00:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movq mm1, [eax+8]
|
||||
movq mm2, mm1
|
||||
punpcklbw mm1, mm7
|
||||
punpckhbw mm2, mm7
|
||||
|
||||
movq mm3, [ebx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
psubw mm1, mm3
|
||||
psubw mm2, mm4
|
||||
pmaddwd mm1, mm1
|
||||
pmaddwd mm2, mm2
|
||||
paddd mm1, mm2
|
||||
|
||||
paddd mm0, mm1
|
||||
|
||||
;; Accumulate sum in edx... we use mm5
|
||||
;movd ecx, mm0
|
||||
;add edx, ecx
|
||||
;psrlq mm0, 32
|
||||
;movd ecx, mm0
|
||||
;add edx, ecx
|
||||
paddd mm5, mm0
|
||||
|
||||
add eax, esi
|
||||
add ebx, esi
|
||||
dec edi
|
||||
jg d2top00
|
||||
jmp near d2exit
|
||||
;jmp d2exit changes made because of problems with nasm 0.98.23
|
||||
|
||||
|
||||
d2is10:
|
||||
test eax, eax
|
||||
je near d2is01
|
||||
test edx, edx
|
||||
jne near d2is01
|
||||
|
||||
|
||||
mov eax, [ebp+8] ; blk1
|
||||
mov ebx, [ebp+12] ; blk1
|
||||
|
||||
pxor mm6, mm6 ; mm6 = 0 and isn't changed anyplace in the loop..
|
||||
pcmpeqw mm1, mm1
|
||||
psubw mm6, mm1
|
||||
jmp d2top10
|
||||
|
||||
align 32
|
||||
d2top10:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [eax+1]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6 ; here we add mm6 = 0.... weird...
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movq mm1, [eax+8]
|
||||
movq mm2, mm1
|
||||
punpcklbw mm1, mm7
|
||||
punpckhbw mm2, mm7
|
||||
movq mm3, [eax+9]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
paddw mm1, mm3
|
||||
paddw mm2, mm4
|
||||
paddw mm1, mm6
|
||||
paddw mm2, mm6
|
||||
psrlw mm1, 1
|
||||
psrlw mm2, 1
|
||||
|
||||
movq mm3, [ebx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
psubw mm1, mm3
|
||||
psubw mm2, mm4
|
||||
pmaddwd mm1, mm1
|
||||
pmaddwd mm2, mm2
|
||||
paddd mm1, mm2
|
||||
|
||||
|
||||
paddd mm0, mm1
|
||||
; Accumulate mm0 sum on edx... we'll use mm5 for this and add up at the end
|
||||
; movd ecx, mm0
|
||||
; add edx, ecx
|
||||
; psrlq mm0, 32
|
||||
; movd ecx, mm0
|
||||
; add edx, ecx
|
||||
paddd mm5, mm0
|
||||
add eax, esi
|
||||
add ebx, esi
|
||||
dec edi
|
||||
jg near d2top10
|
||||
|
||||
|
||||
jmp near d2exit
|
||||
;jmp d2exit changes made because of problems with nasm 0.98.23
|
||||
|
||||
d2is01:
|
||||
test eax, eax
|
||||
jne near d2is11
|
||||
test edx, edx
|
||||
je near d2is11
|
||||
|
||||
mov eax, [ebp+8] ; blk1
|
||||
mov edx, [ebp+12] ; blk2
|
||||
mov ebx, eax
|
||||
add ebx, esi ; blk1 + lx
|
||||
|
||||
pxor mm6, mm6
|
||||
pcmpeqw mm1, mm1
|
||||
psubw mm6, mm1 ; mm6 = 1
|
||||
jmp d2top01
|
||||
|
||||
align 32
|
||||
d2top01:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
paddw mm0, mm6
|
||||
paddw mm1, mm6
|
||||
psrlw mm0, 1
|
||||
psrlw mm1, 1
|
||||
|
||||
movq mm2, [edx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movq mm1, [eax+8]
|
||||
movq mm2, mm1
|
||||
punpcklbw mm1, mm7
|
||||
punpckhbw mm2, mm7
|
||||
|
||||
movq mm3, [ebx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
paddw mm1, mm3
|
||||
paddw mm2, mm4
|
||||
paddw mm1, mm6
|
||||
paddw mm2, mm6
|
||||
psrlw mm1, 1
|
||||
psrlw mm2, 1
|
||||
|
||||
movq mm3, [edx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
psubw mm1, mm3
|
||||
psubw mm2, mm4
|
||||
|
||||
pmaddwd mm1, mm1
|
||||
pmaddwd mm2, mm2
|
||||
paddd mm0, mm1
|
||||
paddd mm0, mm2
|
||||
|
||||
paddd mm5, mm0
|
||||
|
||||
mov eax, ebx ; eax = eax + lx
|
||||
add edx, esi ; edx = edx + lx
|
||||
add ebx, esi ; ebx = ebx + lx
|
||||
dec edi
|
||||
jg near d2top01
|
||||
jmp near d2exit
|
||||
;jmp d2exit changes made because of problems with nasm 0.98.23
|
||||
|
||||
d2is11:
|
||||
mov eax, [ebp+8] ; blk1
|
||||
mov edx, [ebp+12] ; blk2
|
||||
mov ebx, eax ; blk1
|
||||
add ebx, esi ; ebx = blk1 + lx
|
||||
jmp d2top11
|
||||
|
||||
align 32
|
||||
d2top11:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
movq mm2, [eax+1]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
movq mm4, [ebx+1]
|
||||
movq mm6, mm4
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm6, mm7
|
||||
paddw mm2, mm4
|
||||
paddw mm3, mm6
|
||||
paddw mm0, mm2
|
||||
paddw mm1, mm3
|
||||
movq mm6, [twos]
|
||||
paddw mm0, mm6 ; round mm0
|
||||
paddw mm1, mm6 ; round mm1
|
||||
psrlw mm0, 2
|
||||
psrlw mm1, 2
|
||||
|
||||
movq mm2, [edx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm0, mm1
|
||||
|
||||
movq mm1, [eax+8]
|
||||
movq mm2, mm1
|
||||
punpcklbw mm1, mm7
|
||||
punpckhbw mm2, mm7
|
||||
|
||||
movq mm3, [eax+9]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
paddw mm1, mm3
|
||||
paddw mm2, mm4
|
||||
|
||||
movq mm3, [ebx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
paddw mm1, mm3
|
||||
paddw mm2, mm4
|
||||
|
||||
movq mm3, [ebx+9]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
paddw mm1, mm3
|
||||
paddw mm2, mm4
|
||||
|
||||
movq mm6, [twos]
|
||||
paddw mm1, mm6
|
||||
paddw mm2, mm6
|
||||
|
||||
psrlw mm1, 2
|
||||
psrlw mm2, 2
|
||||
|
||||
movq mm3, [edx+8]
|
||||
movq mm4, mm3
|
||||
punpcklbw mm3, mm7
|
||||
punpckhbw mm4, mm7
|
||||
|
||||
psubw mm1, mm3
|
||||
psubw mm2, mm4
|
||||
pmaddwd mm1, mm1
|
||||
pmaddwd mm2, mm2
|
||||
paddd mm1, mm2
|
||||
|
||||
paddd mm0, mm1
|
||||
|
||||
;;
|
||||
;; Accumulate the result in "s" we use mm6 for the purpose...
|
||||
paddd mm5, mm0
|
||||
|
||||
mov eax, ebx ; ahem ebx = eax at start of loop and wasn't changed...
|
||||
add ebx, esi
|
||||
add edx, esi
|
||||
dec edi
|
||||
jg near d2top11
|
||||
|
||||
|
||||
d2exit:
|
||||
;; Put the final sum in eax for return...
|
||||
movd eax, mm5
|
||||
psrlq mm5, 32
|
||||
movd ecx, mm5
|
||||
add eax, ecx
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
|
||||
pop ebp ; restore stack pointer
|
||||
|
||||
emms ; clear mmx registers
|
||||
ret
|
||||
|
||||
|
||||
; total squared difference between two (8*h) blocks
|
||||
; blk1,blk2: addresses of top left pels of both blocks
|
||||
; lx: distance (in bytes) of vertically adjacent pels
|
||||
; h: height of block (usually 4, or 8)
|
||||
; mmX version
|
||||
|
||||
global sumsq_sub22_mmx
|
||||
; int sumsq_sub22_mmx(unsigned char *blk1, unsigned char *blk2,
|
||||
; int lx, int h)
|
||||
|
||||
; mm7 = 0
|
||||
|
||||
; eax = pblk1
|
||||
; ebx = pblk2
|
||||
; ecx = temp
|
||||
; edx = distance_sum
|
||||
; edi = h
|
||||
; esi = lx
|
||||
|
||||
align 32
|
||||
sumsq_sub22_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, [ebp+16] ; lx
|
||||
mov edi, [ebp+20] ; h
|
||||
|
||||
pxor mm5, mm5 ; sum
|
||||
test edi, edi ; h = 0?
|
||||
jle near d2exit
|
||||
|
||||
pxor mm7, mm7 ; get zeros i mm7
|
||||
|
||||
mov eax, [ebp+8] ; blk1
|
||||
mov ebx, [ebp+12] ; blk2
|
||||
jmp d2top22
|
||||
|
||||
align 32
|
||||
d2top22:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
|
||||
movq mm2, [ebx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
psubw mm0, mm2
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm0, mm0
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm5, mm0
|
||||
paddd mm5, mm1
|
||||
|
||||
add eax, esi
|
||||
add ebx, esi
|
||||
dec edi
|
||||
jg d2top22
|
||||
jmp d2exit
|
||||
|
||||
|
||||
; total squared difference between interpolation of two (8*h) blocks and
|
||||
; another 8*h block
|
||||
; blk1,blk2: addresses of top left pels of both blocks
|
||||
; lx: distance (in bytes) of vertically adjacent pels
|
||||
; h: height of block (usually 4, or 8)
|
||||
; mmX version
|
||||
|
||||
global bsumsq_sub22_mmx
|
||||
; int bsumsq_sub22_mmx(unsigned char *blk1f, unsigned char*blk1b,
|
||||
; unsigned char *blk2,
|
||||
; int lx, int h)
|
||||
|
||||
; mm7 = 0
|
||||
|
||||
; eax = pblk1f
|
||||
; ebx = pblk2
|
||||
; ecx = pblk1b
|
||||
; edx = distance_sum
|
||||
; edi = h
|
||||
; esi = lx
|
||||
|
||||
align 32
|
||||
bsumsq_sub22_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, [ebp+20] ; lx
|
||||
mov edi, [ebp+24] ; h
|
||||
|
||||
pxor mm5, mm5 ; sum
|
||||
test edi, edi ; h = 0?
|
||||
jle near d2exit
|
||||
|
||||
pxor mm7, mm7 ; get zeros i mm7
|
||||
|
||||
mov eax, [ebp+8] ; blk1f
|
||||
mov ebx, [ebp+12] ; blk1b
|
||||
mov ecx, [ebp+16] ; blk2
|
||||
jmp bd2top22
|
||||
|
||||
align 32
|
||||
bd2top22:
|
||||
movq mm0, [eax]
|
||||
movq mm1, mm0
|
||||
movq mm4, [ebx]
|
||||
movq mm6, mm4
|
||||
punpcklbw mm0, mm7
|
||||
punpckhbw mm1, mm7
|
||||
punpcklbw mm4, mm7
|
||||
punpckhbw mm6, mm7
|
||||
|
||||
movq mm2, [ecx]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm7
|
||||
punpckhbw mm3, mm7
|
||||
|
||||
paddw mm0, mm4
|
||||
psrlw mm0, 1
|
||||
psubw mm0, mm2
|
||||
pmaddwd mm0, mm0
|
||||
paddw mm1, mm6
|
||||
psrlw mm1, 1
|
||||
psubw mm1, mm3
|
||||
pmaddwd mm1, mm1
|
||||
paddd mm5, mm0
|
||||
paddd mm5, mm1
|
||||
|
||||
add eax, esi
|
||||
add ebx, esi
|
||||
add ecx, esi
|
||||
dec edi
|
||||
jg bd2top22
|
||||
jmp d2exit
|
||||
|
||||
|
||||
global variance_mmx
|
||||
|
||||
;;; variance of a (size*size) block, multiplied by 256
|
||||
;;; p: address of top left pel of block
|
||||
;;; lx: seperation (in bytes) of vertically adjacent pels
|
||||
;;; NOTE: size is 8 or 16
|
||||
|
||||
;;; int variance_mmx(uint8_t *p, int size, int lx)
|
||||
|
||||
|
||||
variance_mmx:
|
||||
push ebp ; save frame pointer
|
||||
mov ebp, esp ; link
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov eax, 0 ; col offset...
|
||||
mov edx, [ebp+16] ; lx
|
||||
|
||||
pxor mm0, mm0
|
||||
pxor mm7, mm7 ; Zero sum accumulator (4 words)
|
||||
pxor mm6, mm6 ; Zero squares accumulator (2 dwords)
|
||||
varcols:
|
||||
mov ebx, [ebp+8] ; p
|
||||
mov ecx, [ebp+12] ; size
|
||||
varrows:
|
||||
|
||||
movq mm2, [ebx+eax]
|
||||
movq mm3, mm2
|
||||
punpcklbw mm2, mm0
|
||||
punpckhbw mm3, mm0
|
||||
|
||||
movq mm4, mm2
|
||||
movq mm5, mm3
|
||||
|
||||
pmaddwd mm4, mm2 ; Squares 0:3
|
||||
paddw mm7, mm2 ; Accumulate sum 0:3 (words)
|
||||
paddd mm6, mm4 ; Accumulate sum squares 0:3 (dwords)
|
||||
|
||||
pmaddwd mm5, mm3 ; Squares 4:7 (words)
|
||||
paddw mm7, mm3 ; Accumulate sum 0:3 (words)
|
||||
paddd mm6, mm5 ; Accumulate sum squares 4:7 (dwords)
|
||||
|
||||
|
||||
add ebx, edx ; Next row
|
||||
dec ecx
|
||||
jnz varrows
|
||||
|
||||
add eax, 8
|
||||
cmp eax, [ebp+12]
|
||||
jl varcols
|
||||
|
||||
;; Sum squared -> eax
|
||||
|
||||
movq mm1, mm7
|
||||
psrlq mm1, 32
|
||||
paddw mm7, mm1
|
||||
movq mm1, mm7
|
||||
psrlq mm1, 16
|
||||
paddw mm7, mm1
|
||||
movd eax, mm7
|
||||
and eax, 0xffff
|
||||
imul eax, eax
|
||||
|
||||
;; Squares sum -> ecx
|
||||
|
||||
movq mm1, mm6
|
||||
psrlq mm1, 32
|
||||
paddd mm6, mm1
|
||||
movd ecx, mm6
|
||||
|
||||
mov ebx, [ebp+12]
|
||||
shr eax, 6 ; Divide sum squared by 64 for 8*8
|
||||
cmp ebx, 8
|
||||
jz var8_8 ; If 16 * 16 divide again by 4 (256)
|
||||
shr eax, 2
|
||||
var8_8:
|
||||
|
||||
sub ecx, eax
|
||||
mov eax, ecx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
|
||||
pop ebp ; restore stack pointer
|
||||
|
||||
emms ; clear mmx registers
|
||||
ret
|
||||
218
veejay-current/utils/mjpeg_logging.c
Normal file
218
veejay-current/utils/mjpeg_logging.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
$Id: mjpeg_logging.c,v 1.1.1.1 2004/10/27 23:48:57 niels Exp $
|
||||
|
||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int fred;
|
||||
#include "mjpeg_logging.h"
|
||||
|
||||
static const char _rcsid[] = "$Id: ";
|
||||
|
||||
#define MAX_DEFAULT_ID_SIZE 16
|
||||
#define DEFAULT_DEFAULT_ID "???"
|
||||
|
||||
#ifdef HAVE___PROGNAME
|
||||
extern const char *__progname;
|
||||
#endif
|
||||
|
||||
static log_level_t mjpeg_log_verbosity = 0;
|
||||
static char default_handler_id[MAX_DEFAULT_ID_SIZE];
|
||||
static char default_handler_id_is_set = 0;
|
||||
|
||||
static int default_mjpeg_log_filter( log_level_t level )
|
||||
{
|
||||
int verb_from_env;
|
||||
if( mjpeg_log_verbosity == 0 )
|
||||
{
|
||||
char *mjpeg_verb_env = getenv("MJPEG_VERBOSITY");
|
||||
if( mjpeg_verb_env != NULL )
|
||||
{
|
||||
verb_from_env = LOG_WARN-atoi(mjpeg_verb_env);
|
||||
if( verb_from_env >= LOG_DEBUG && verb_from_env <= LOG_ERROR )
|
||||
mjpeg_log_verbosity = verb_from_env;
|
||||
}
|
||||
}
|
||||
return (level < LOG_WARN && level < mjpeg_log_verbosity);
|
||||
}
|
||||
|
||||
static mjpeg_log_filter_t _filter = default_mjpeg_log_filter;
|
||||
|
||||
static void
|
||||
default_mjpeg_log_handler(log_level_t level, const char message[])
|
||||
{
|
||||
if( (*_filter)( level ) )
|
||||
return;
|
||||
switch(level) {
|
||||
case LOG_ERROR:
|
||||
fprintf(stderr, "E: %s\n", message);
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
fprintf(stderr, "D: %s\n", message);
|
||||
break;
|
||||
case LOG_WARN:
|
||||
fprintf(stderr, "W: %s\n", message);
|
||||
break;
|
||||
case LOG_INFO:
|
||||
fprintf(stderr, "I: %s\n", message);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static mjpeg_log_handler_t _handler = default_mjpeg_log_handler;
|
||||
|
||||
|
||||
mjpeg_log_handler_t
|
||||
mjpeg_log_set_handler(mjpeg_log_handler_t new_handler)
|
||||
{
|
||||
mjpeg_log_handler_t old_handler = _handler;
|
||||
|
||||
_handler = new_handler;
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/***************
|
||||
*
|
||||
* Set default log handlers degree of verboseity.
|
||||
* 0 = quiet, 1 = info, 2 = debug
|
||||
*
|
||||
*************/
|
||||
|
||||
int
|
||||
mjpeg_default_handler_verbosity(int verbosity)
|
||||
{
|
||||
int prev_verb = mjpeg_log_verbosity;
|
||||
mjpeg_log_verbosity = LOG_WARN - verbosity;
|
||||
return prev_verb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set identifier string used by default handler
|
||||
*
|
||||
*/
|
||||
int
|
||||
mjpeg_default_handler_identifier(const char *new_id)
|
||||
{
|
||||
const char *s;
|
||||
if (new_id == NULL) {
|
||||
default_handler_id_is_set = 0;
|
||||
return 0;
|
||||
}
|
||||
/* find basename of new_id (remove any directory prefix) */
|
||||
if ((s = strrchr(new_id, '/')) == NULL)
|
||||
s = new_id;
|
||||
else
|
||||
s = s + 1;
|
||||
strncpy(default_handler_id, s, MAX_DEFAULT_ID_SIZE);
|
||||
default_handler_id[MAX_DEFAULT_ID_SIZE-1] = '\0';
|
||||
default_handler_id_is_set = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mjpeg_logv(log_level_t level, const char format[], va_list args)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
|
||||
/* TODO: Original had a re-entrancy error trap to assist bug
|
||||
finding. To make this work with multi-threaded applications a
|
||||
lock is needed hence delete.
|
||||
*/
|
||||
|
||||
|
||||
vsnprintf(buf, sizeof(buf)-1, format, args);
|
||||
|
||||
_handler(level, buf);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_log(log_level_t level, const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
mjpeg_logv(level, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_debug(const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
mjpeg_logv(LOG_DEBUG, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_info(const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
mjpeg_logv(LOG_INFO, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_warn(const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
mjpeg_logv(LOG_WARN, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_error(const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
mjpeg_logv(LOG_ERROR, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
mjpeg_error_exit1(const char format[], ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start( args, format );
|
||||
mjpeg_logv( LOG_ERROR, format, args);
|
||||
va_end(args);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "gnu"
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
79
veejay-current/utils/mjpeg_logging.h
Normal file
79
veejay-current/utils/mjpeg_logging.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
$Id: mjpeg_logging.h,v 1.1.1.1 2004/10/27 23:48:57 niels Exp $
|
||||
|
||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MJPEG_LOGGING_H__
|
||||
#define __MJPEG_LOGGING_H__
|
||||
|
||||
#include "mjpeg_types.h"
|
||||
|
||||
typedef enum {
|
||||
LOG_DEBUG = 1,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERROR
|
||||
} log_level_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void
|
||||
mjpeg_log(log_level_t level, const char format[], ...) GNUC_PRINTF(2, 3);
|
||||
|
||||
typedef int(*mjpeg_log_filter_t)(log_level_t level);
|
||||
|
||||
typedef void(*mjpeg_log_handler_t)(log_level_t level, const char message[]);
|
||||
|
||||
mjpeg_log_handler_t
|
||||
mjpeg_log_set_handler(mjpeg_log_handler_t new_handler);
|
||||
|
||||
int
|
||||
mjpeg_default_handler_identifier(const char *new_id);
|
||||
|
||||
int
|
||||
mjpeg_default_handler_verbosity(int verbosity);
|
||||
|
||||
void
|
||||
mjpeg_debug(const char format[], ...) GNUC_PRINTF(1,2);
|
||||
|
||||
void
|
||||
mjpeg_info(const char format[], ...) GNUC_PRINTF(1,2);
|
||||
|
||||
void
|
||||
mjpeg_warn(const char format[], ...) GNUC_PRINTF(1,2);
|
||||
|
||||
void
|
||||
mjpeg_error(const char format[], ...) GNUC_PRINTF(1,2);
|
||||
|
||||
void
|
||||
mjpeg_error_exit1(const char format[], ...) GNUC_PRINTF(1,2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __MJPEG_LOGGING_H__ */
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "gnu"
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
109
veejay-current/utils/mjpeg_types.h
Normal file
109
veejay-current/utils/mjpeg_types.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
$Id: mjpeg_types.h,v 1.1.1.1 2004/10/27 23:48:57 niels Exp $
|
||||
|
||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MJPEG_TYPES_H__
|
||||
#define __MJPEG_TYPES_H__
|
||||
#include <config.h>
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
# include <stdint.h>
|
||||
#elif defined(HAVE_INTTYPES_H)
|
||||
# include <inttypes.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
# include <sys/types.h>
|
||||
typedef u_int8_t uint8_t;
|
||||
typedef u_int16_t uint16_t;
|
||||
typedef u_int32_t uint32_t;
|
||||
typedef u_int64_t uint64_t;
|
||||
# define INT8_C(c) c
|
||||
# define INT16_C(c) c
|
||||
# define INT32_C(c) c
|
||||
# define INT64_C(c) c ## LL
|
||||
# define UINT8_C(c) c ## U
|
||||
# define UINT16_C(c) c ## U
|
||||
# define UINT32_C(c) c ## U
|
||||
# define UINT64_C(c) c ## ULL
|
||||
#else
|
||||
/* warning ISO/IEC 9899:1999 <stdint.h> was missing and even <inttypes.h> */
|
||||
/* fixme */
|
||||
#endif /* HAVE_STDINT_H */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/types.h> /* FreeBSD - ssize_t */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STDBOOL_H) && !defined(__cplusplus)
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
/* ISO/IEC 9899:1999 <stdbool.h> missing -- enabling workaround */
|
||||
|
||||
# ifndef __cplusplus
|
||||
typedef enum
|
||||
{
|
||||
false = 0,
|
||||
true = 1
|
||||
} locBool;
|
||||
|
||||
# define false false
|
||||
# define true true
|
||||
# define bool locBool
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PRId64
|
||||
#define PRId64 PRID64_STRING_FORMAT
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
||||
#define GNUC_PRINTF( format_idx, arg_idx ) \
|
||||
__attribute__((format (printf, format_idx, arg_idx)))
|
||||
#define GNUC_SCANF( format_idx, arg_idx ) \
|
||||
__attribute__((format (scanf, format_idx, arg_idx)))
|
||||
#define GNUC_FORMAT( arg_idx ) \
|
||||
__attribute__((format_arg (arg_idx)))
|
||||
#define GNUC_NORETURN \
|
||||
__attribute__((noreturn))
|
||||
#define GNUC_CONST \
|
||||
__attribute__((const))
|
||||
#define GNUC_UNUSED \
|
||||
__attribute__((unused))
|
||||
#define GNUC_PACKED \
|
||||
__attribute__((packed))
|
||||
#else /* !__GNUC__ */
|
||||
#define GNUC_PRINTF( format_idx, arg_idx )
|
||||
#define GNUC_SCANF( format_idx, arg_idx )
|
||||
#define GNUC_FORMAT( arg_idx )
|
||||
#define GNUC_NORETURN
|
||||
#define GNUC_CONST
|
||||
#define GNUC_UNUSED
|
||||
#define GNUC_PACKED
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
|
||||
#endif /* __MJPEG_TYPES_H__ */
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "gnu"
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
271
veejay-current/utils/mmx.h
Normal file
271
veejay-current/utils/mmx.h
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* mmx.h
|
||||
* Copyright (C) 1997-1999 H. Dietz and R. Fisher
|
||||
*
|
||||
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
|
||||
*
|
||||
* mpeg2dec 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.
|
||||
*
|
||||
* mpeg2dec 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "attributes.h"
|
||||
|
||||
/*
|
||||
* The type of an value that fits in an MMX register (note that long
|
||||
* long constant values MUST be suffixed by LL and unsigned long long
|
||||
* values by ULL, lest they be truncated by the compiler)
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
int64_t q; /* Quadword (64-bit) value */
|
||||
uint64_t uq; /* Unsigned Quadword */
|
||||
int32_t d[2]; /* 2 Doubleword (32-bit) values */
|
||||
uint32_t ud[2]; /* 2 Unsigned Doubleword */
|
||||
int16_t w[4]; /* 4 Word (16-bit) values */
|
||||
uint16_t uw[4]; /* 4 Unsigned Word */
|
||||
int8_t b[8]; /* 8 Byte (8-bit) values */
|
||||
uint8_t ub[8]; /* 8 Unsigned Byte */
|
||||
float s[2]; /* Single-precision (32-bit) value */
|
||||
} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */
|
||||
|
||||
|
||||
#define mmx_si2r(op,imm,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "J" (imm) )
|
||||
|
||||
#define mmx_m2r(op,mem,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (mem))
|
||||
|
||||
#define mmx_r2m(op,reg,mem) \
|
||||
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||
: "=X" (mem) \
|
||||
: /* nothing */ )
|
||||
|
||||
#define mmx_r2r(op,regs,regd) \
|
||||
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
|
||||
|
||||
|
||||
#define emms() __asm__ __volatile__ ("emms")
|
||||
#define femms() __asm__ __volatile__ ("femms")
|
||||
|
||||
#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
|
||||
#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
|
||||
#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
|
||||
|
||||
#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
|
||||
#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
|
||||
#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
|
||||
|
||||
#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
|
||||
#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
|
||||
#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
|
||||
#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
|
||||
|
||||
#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
|
||||
#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
|
||||
|
||||
#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
|
||||
#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
|
||||
#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
|
||||
#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
|
||||
#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
|
||||
#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
|
||||
|
||||
#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
|
||||
#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
|
||||
#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
|
||||
#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
|
||||
|
||||
#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
|
||||
#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
|
||||
#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
|
||||
#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
|
||||
|
||||
#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
|
||||
#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
|
||||
|
||||
#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
|
||||
#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
|
||||
|
||||
#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
|
||||
#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
|
||||
#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
|
||||
#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
|
||||
#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
|
||||
#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
|
||||
|
||||
#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
|
||||
#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
|
||||
#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
|
||||
#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
|
||||
#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
|
||||
#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
|
||||
|
||||
#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
|
||||
#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
|
||||
|
||||
#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
|
||||
#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
|
||||
|
||||
#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
|
||||
#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
|
||||
|
||||
#define por_m2r(var,reg) mmx_m2r (por, var, reg)
|
||||
#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
|
||||
|
||||
#define pslld_i2r(imm,reg) mmx_si2r (pslld, imm, reg)
|
||||
#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
|
||||
#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
|
||||
#define psllq_i2r(imm,reg) mmx_si2r (psllq, imm, reg)
|
||||
#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
|
||||
#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
|
||||
#define psllw_i2r(imm,reg) mmx_si2r (psllw, imm, reg)
|
||||
#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
|
||||
#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
|
||||
|
||||
#define psrad_i2r(imm,reg) mmx_si2r (psrad, imm, reg)
|
||||
#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
|
||||
#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
|
||||
#define psraw_i2r(imm,reg) mmx_si2r (psraw, imm, reg)
|
||||
#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
|
||||
#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
|
||||
|
||||
#define psrld_i2r(imm,reg) mmx_si2r (psrld, imm, reg)
|
||||
#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
|
||||
#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
|
||||
#define psrlq_i2r(imm,reg) mmx_si2r (psrlq, imm, reg)
|
||||
#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
|
||||
#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
|
||||
#define psrlw_i2r(imm,reg) mmx_si2r (psrlw, imm, reg)
|
||||
#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
|
||||
#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
|
||||
|
||||
#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
|
||||
#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
|
||||
#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
|
||||
#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
|
||||
#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
|
||||
#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
|
||||
|
||||
#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
|
||||
#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
|
||||
#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
|
||||
#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
|
||||
|
||||
#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
|
||||
#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
|
||||
#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
|
||||
#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
|
||||
|
||||
#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
|
||||
#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
|
||||
#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
|
||||
#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
|
||||
#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
|
||||
#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
|
||||
|
||||
#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
|
||||
#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
|
||||
#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
|
||||
#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
|
||||
#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
|
||||
#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
|
||||
|
||||
#define pxor_m2r(var, reg) mmx_m2r (pxor, var, reg)
|
||||
#define pxor_r2r(regs, regd) mmx_r2r (pxor, regs, regd)
|
||||
|
||||
/* AMD MMX extensions - also available in intel SSE */
|
||||
|
||||
|
||||
#define mmx_m2ri(op,mem,reg,imm) \
|
||||
__asm__ __volatile__ (#op " %1, %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (mem), "X" (imm))
|
||||
#define mmx_r2ri(op,regs,regd,imm) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
|
||||
: /* nothing */ \
|
||||
: "X" (imm) )
|
||||
|
||||
#define mmx_fetch(mem,hint) \
|
||||
__asm__ __volatile__ ("prefetch" #hint " %0" \
|
||||
: /* nothing */ \
|
||||
: "X" (mem))
|
||||
|
||||
/* 3DNow goodies */
|
||||
#define pfmul_m2r(var,reg) mmx_m2r( pfmul, var, reg )
|
||||
#define pfmul_r2r(regs,regd) mmx_r2r( pfmul, regs, regd )
|
||||
#define pfadd_m2r(var,reg) mmx_m2r( pfadd, var, reg )
|
||||
#define pfadd_r2r(regs,regd) mmx_r2r( pfadd, regs, regd )
|
||||
#define pf2id_r2r(regs,regd) mmx_r2r( pf2id, regs, regd )
|
||||
#define pi2fd_r2r(regs,regd) mmx_r2r( pi2fd, regs, regd )
|
||||
|
||||
/* SSE goodies */
|
||||
#define mulps_r2r( regs, regd) mmx_r2r( mulps, regs, regd )
|
||||
#define mulps_m2r( var, regd) mmx_m2r( mulps, var, regd )
|
||||
#define movups_r2r(reg1, reg2) mmx_r2r( movups, reg1, reg2 )
|
||||
#define movups_m2r(var, reg) mmx_m2r( movups, var, reg )
|
||||
#define movaps_m2r(var, reg) mmx_m2r( movaps, var, reg )
|
||||
#define movups_r2m(reg, var) mmx_r2m( movups, reg, var )
|
||||
#define movaps_r2m(reg, var) mmx_r2m( movaps, reg, var )
|
||||
#define cvtps2pi_r2r(regs,regd) mmx_r2r( cvtps2pi, regs, regd )
|
||||
#define cvtpi2ps_r2r(regs,regd) mmx_r2r( cvtpi2ps, regs, regd )
|
||||
#define shufps_r2ri(regs, regd, imm) mmx_r2ri( shufps, regs, regd, imm )
|
||||
|
||||
|
||||
#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
|
||||
|
||||
#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
|
||||
|
||||
#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
|
||||
#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
|
||||
#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
|
||||
#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
|
||||
|
||||
#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
|
||||
|
||||
#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
|
||||
|
||||
#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
|
||||
#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
|
||||
|
||||
#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
|
||||
#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
|
||||
|
||||
#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
|
||||
#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
|
||||
|
||||
#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
|
||||
#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
|
||||
|
||||
#define pmovmskb(mmreg,reg) \
|
||||
__asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
|
||||
|
||||
#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
|
||||
#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
|
||||
|
||||
#define prefetcht0(mem) mmx_fetch (mem, t0)
|
||||
#define prefetcht1(mem) mmx_fetch (mem, t1)
|
||||
#define prefetcht2(mem) mmx_fetch (mem, t2)
|
||||
#define prefetchnta(mem) mmx_fetch (mem, nta)
|
||||
|
||||
#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
|
||||
#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
|
||||
|
||||
#define pshufw_m2ri(var,reg,imm) mmx_m2ri( pshufw, var, reg, imm)
|
||||
#define pshufw_r2ri(regs,regd,imm) mmx_r2ri( pshufw, regs, regd, imm)
|
||||
|
||||
#define sfence() __asm__ __volatile__ ("sfence\n\t")
|
||||
1237
veejay-current/utils/motionsearch.c
Normal file
1237
veejay-current/utils/motionsearch.c
Normal file
File diff suppressed because it is too large
Load Diff
141
veejay-current/utils/motionsearch.h
Normal file
141
veejay-current/utils/motionsearch.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* (C) 2000/2001 Andrew Stevens */
|
||||
|
||||
/* This software 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MOTIONSEARCH_H__
|
||||
#define __MOTIONSEARCH_H__
|
||||
|
||||
#include <config.h>
|
||||
#include "mjpeg_types.h"
|
||||
|
||||
struct me_result
|
||||
{
|
||||
uint16_t weight;
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
};
|
||||
|
||||
typedef struct me_result me_result_s;
|
||||
|
||||
#define MAX_MATCHES (256*256/4)
|
||||
|
||||
typedef struct _me_result_vec {
|
||||
int len;
|
||||
me_result_s mests[MAX_MATCHES];
|
||||
} me_result_set;
|
||||
|
||||
/*
|
||||
* Function pointers for selecting CPU specific implementations
|
||||
*
|
||||
* Top-level motion estimation entry points.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Use given set of 2*2 sub-sampled motion estimates generated using
|
||||
* pbuild_sub22_mests to generate a best 1-pel motion estimate.
|
||||
*
|
||||
*/
|
||||
|
||||
extern void (*pfind_best_one_pel)( me_result_set *sub22set,
|
||||
uint8_t *org, uint8_t *blk,
|
||||
int i0, int j0,
|
||||
int ihigh, int jhigh,
|
||||
int rowstride, int h,
|
||||
me_result_s *res
|
||||
);
|
||||
|
||||
/*
|
||||
* Use given set of 4*4 sub-sampled motion estimates generated using
|
||||
* pbuild_sub44_mests to generate a set of best 2*2 sub-sampled motion
|
||||
* estimates.
|
||||
*/
|
||||
|
||||
extern int (*pbuild_sub22_mests)( me_result_set *sub44set,
|
||||
me_result_set *sub22set,
|
||||
int i0, int j0, int ihigh, int jhigh,
|
||||
int null_mc_sad,
|
||||
uint8_t *s22org, uint8_t *s22blk,
|
||||
int frowstride, int fh,
|
||||
int reduction
|
||||
);
|
||||
|
||||
/*
|
||||
* Generate a set the best 4*4 sub-sampled motion estimates
|
||||
* from the specifed rectangle of candidates in s44org with respect
|
||||
* to the reference block s44blk
|
||||
*/
|
||||
|
||||
extern int (*pbuild_sub44_mests)( me_result_set *sub44set,
|
||||
int ilow, int jlow, int ihigh, int jhigh,
|
||||
int i0, int j0,
|
||||
int null_mc_sad,
|
||||
uint8_t *s44org, uint8_t *s44blk,
|
||||
int qrowstride, int qh,
|
||||
int reduction );
|
||||
|
||||
|
||||
/*
|
||||
* Lower level difference comparison routines
|
||||
*
|
||||
* Naming convention: for block difference metric functions
|
||||
* sad - Sum Absolute difference
|
||||
* sumsq - Sum of squares
|
||||
* sub44 - 4*4 Subsampled macroblocks (i.e. 4x4 subsampled pels)
|
||||
* sub22 2*2 submsapled macroblocks (i.e. 8x8 subsampled pels)
|
||||
* <nothing> Ordinary macroblocks (i.e. 16x16 pels)
|
||||
* "b" prefix: Difference of bi-directionally interpolated block
|
||||
* (i.e. mean of two blocks)
|
||||
* _xy suffix: Difference with half-pel sub-sampling offset.
|
||||
* (i.e. _00 is just ordinary no sub-sampling)
|
||||
* mests - Motion estimate results relative motion vector with sad.
|
||||
*/
|
||||
|
||||
extern int (*psumsq_sub22)( uint8_t *blk1, uint8_t *blk2,
|
||||
int rowstride, int h);
|
||||
extern int (*pbsumsq_sub22)( uint8_t *blk1f, uint8_t *blk1b,
|
||||
uint8_t *blk2,
|
||||
int rowstride, int h);
|
||||
|
||||
extern int (*pvariance)(uint8_t *mb, int size, int rowstride);
|
||||
|
||||
|
||||
extern int (*psad_sub22) ( uint8_t *blk1, uint8_t *blk2, int frowstride, int fh);
|
||||
extern int (*psad_sub44) ( uint8_t *blk1, uint8_t *blk2, int qrowstride, int qh);
|
||||
extern int (*psad_00) ( uint8_t *blk1, uint8_t *blk2, int rowstride, int h, int distlim);
|
||||
extern int (*psad_01) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h);
|
||||
extern int (*psad_10) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h);
|
||||
extern int (*psad_11) (uint8_t *blk1, uint8_t *blk2, int rowstride, int h);
|
||||
|
||||
extern int (*psumsq) (uint8_t *blk1, uint8_t *blk2,
|
||||
int rowstride, int hx, int hy, int h);
|
||||
|
||||
|
||||
extern int (*pbsumsq) (uint8_t *pf, uint8_t *pb,
|
||||
uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h);
|
||||
|
||||
extern int (*pbsad) (uint8_t *pf, uint8_t *pb,
|
||||
uint8_t *p2, int rowstride, int hxf, int hyf, int hxb, int hyb, int h);
|
||||
|
||||
void init_motion_search(void);
|
||||
int round_search_radius( int radius );
|
||||
void subsample_image( uint8_t *image, int rowstride,
|
||||
uint8_t *sub22_image,
|
||||
uint8_t *sub44_image);
|
||||
|
||||
#endif /* __MOTIONSEARCH_H__ */
|
||||
450
veejay-current/utils/mpegconsts.c
Normal file
450
veejay-current/utils/mpegconsts.c
Normal file
@@ -0,0 +1,450 @@
|
||||
|
||||
/*
|
||||
* mpegconsts.c: Video format constants for MPEG and utilities for display
|
||||
* and conversion to format used for yuv4mpeg
|
||||
*
|
||||
* Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
|
||||
* Copyright (C) 2001 Matthew Marjanovic <maddog@mir.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "mpegconsts.h"
|
||||
#include "yuv4mpeg.h"
|
||||
#include "yuv4mpeg_intern.h"
|
||||
|
||||
static y4m_ratio_t
|
||||
mpeg_framerates[] = {
|
||||
Y4M_FPS_UNKNOWN,
|
||||
Y4M_FPS_NTSC_FILM,
|
||||
Y4M_FPS_FILM,
|
||||
Y4M_FPS_PAL,
|
||||
Y4M_FPS_NTSC,
|
||||
Y4M_FPS_30,
|
||||
Y4M_FPS_PAL_FIELD,
|
||||
Y4M_FPS_NTSC_FIELD,
|
||||
Y4M_FPS_60
|
||||
};
|
||||
|
||||
|
||||
#define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0]))
|
||||
const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES;
|
||||
|
||||
static const char *
|
||||
framerate_definitions[MPEG_NUM_RATES] =
|
||||
{
|
||||
"illegal",
|
||||
"24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)",
|
||||
"24.0 (NATIVE FILM)",
|
||||
"25.0 (PAL/SECAM VIDEO / converted FILM)",
|
||||
"30000.0/1001.0 (NTSC VIDEO)",
|
||||
"30.0",
|
||||
"50.0 (PAL FIELD RATE)",
|
||||
"60000.0/1001.0 (NTSC FIELD RATE)",
|
||||
"60.0"
|
||||
};
|
||||
|
||||
|
||||
static const char *mpeg1_aspect_ratio_definitions[] =
|
||||
{
|
||||
"1:1 (square pixels)",
|
||||
"1:0.6735",
|
||||
"1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)",
|
||||
"1:0.7615",
|
||||
"1:0.8055",
|
||||
"1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)",
|
||||
"1:0.8935",
|
||||
"1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)",
|
||||
"1:0.9815",
|
||||
"1:1.0255",
|
||||
"1:1:0695",
|
||||
"1:1.1250 (4:3 NTSC for 720x480/352x240 images)",
|
||||
"1:1.1575",
|
||||
"1:1.2015"
|
||||
};
|
||||
|
||||
static const y4m_ratio_t mpeg1_aspect_ratios[] =
|
||||
{
|
||||
Y4M_SAR_MPEG1_1,
|
||||
Y4M_SAR_MPEG1_2,
|
||||
Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */
|
||||
Y4M_SAR_MPEG1_4,
|
||||
Y4M_SAR_MPEG1_5,
|
||||
Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */
|
||||
Y4M_SAR_MPEG1_7,
|
||||
Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */
|
||||
Y4M_SAR_MPEG1_9,
|
||||
Y4M_SAR_MPEG1_10,
|
||||
Y4M_SAR_MPEG1_11,
|
||||
Y4M_SAR_MPEG1_12, /* NTSC 4:3 */
|
||||
Y4M_SAR_MPEG1_13,
|
||||
Y4M_SAR_MPEG1_14,
|
||||
};
|
||||
|
||||
static const char *mpeg2_aspect_ratio_definitions[] =
|
||||
{
|
||||
"1:1 pixels",
|
||||
"4:3 display",
|
||||
"16:9 display",
|
||||
"2.21:1 display"
|
||||
};
|
||||
|
||||
|
||||
static const y4m_ratio_t mpeg2_aspect_ratios[] =
|
||||
{
|
||||
Y4M_DAR_MPEG2_1,
|
||||
Y4M_DAR_MPEG2_2,
|
||||
Y4M_DAR_MPEG2_3,
|
||||
Y4M_DAR_MPEG2_4
|
||||
};
|
||||
|
||||
static const char **aspect_ratio_definitions[2] =
|
||||
{
|
||||
mpeg1_aspect_ratio_definitions,
|
||||
mpeg2_aspect_ratio_definitions
|
||||
};
|
||||
|
||||
static const y4m_ratio_t *mpeg_aspect_ratios[2] =
|
||||
{
|
||||
mpeg1_aspect_ratios,
|
||||
mpeg2_aspect_ratios
|
||||
};
|
||||
|
||||
const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] =
|
||||
{
|
||||
sizeof(mpeg1_aspect_ratios)/sizeof(mpeg1_aspect_ratios[0]),
|
||||
sizeof(mpeg2_aspect_ratios)/sizeof(mpeg2_aspect_ratios[0])
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert MPEG frame-rate code to corresponding frame-rate
|
||||
*/
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_framerate( mpeg_framerate_code_t code )
|
||||
{
|
||||
if( code == 0 || code > mpeg_num_framerates )
|
||||
return y4m_fps_UNKNOWN;
|
||||
else
|
||||
return mpeg_framerates[code];
|
||||
}
|
||||
|
||||
/*
|
||||
* Look-up MPEG frame rate code for a (exact) frame rate.
|
||||
*/
|
||||
|
||||
|
||||
mpeg_framerate_code_t
|
||||
mpeg_framerate_code( y4m_ratio_t framerate )
|
||||
{
|
||||
mpeg_framerate_code_t i;
|
||||
|
||||
y4m_ratio_reduce(&framerate);
|
||||
for (i = 1; i < mpeg_num_framerates; ++i) {
|
||||
if (Y4M_RATIO_EQL(framerate, mpeg_framerates[i]))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* small enough to distinguish 1/1000 from 1/1001 */
|
||||
#define MPEG_FPS_TOLERANCE 0.0001
|
||||
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_conform_framerate( double fps )
|
||||
{
|
||||
mpeg_framerate_code_t i;
|
||||
y4m_ratio_t result;
|
||||
|
||||
/* try to match it to a standard frame rate */
|
||||
for (i = 1; i < mpeg_num_framerates; i++)
|
||||
{
|
||||
double deviation = 1.0 - (Y4M_RATIO_DBL(mpeg_framerates[i]) / fps);
|
||||
if ( (deviation > -MPEG_FPS_TOLERANCE) &&
|
||||
(deviation < +MPEG_FPS_TOLERANCE) )
|
||||
return mpeg_framerates[i];
|
||||
}
|
||||
/* no luck? just turn it into a ratio (6 decimal place accuracy) */
|
||||
result.n = (fps * 1000000.0) + 0.5;
|
||||
result.d = 1000000;
|
||||
y4m_ratio_reduce(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Convert MPEG aspect-ratio code to corresponding aspect-ratio
|
||||
*/
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code )
|
||||
{
|
||||
y4m_ratio_t ratio;
|
||||
if( mpeg_version < 1 || mpeg_version > 2 )
|
||||
return y4m_sar_UNKNOWN;
|
||||
if( code == 0 || code > mpeg_num_aspect_ratios[mpeg_version-1] )
|
||||
return y4m_sar_UNKNOWN;
|
||||
else
|
||||
{
|
||||
ratio = mpeg_aspect_ratios[mpeg_version-1][code-1];
|
||||
y4m_ratio_reduce(&ratio);
|
||||
return ratio;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look-up corresponding MPEG aspect ratio code given an exact aspect ratio.
|
||||
*
|
||||
* WARNING: The semantics of aspect ratio coding *changed* between
|
||||
* MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In
|
||||
* MPEG2 it is the (far more sensible) aspect ratio of the eventual
|
||||
* display.
|
||||
*
|
||||
*/
|
||||
|
||||
mpeg_aspect_code_t
|
||||
mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio )
|
||||
{
|
||||
mpeg_aspect_code_t i;
|
||||
y4m_ratio_t red_ratio = aspect_ratio;
|
||||
y4m_ratio_reduce( &red_ratio );
|
||||
if( mpeg_version < 1 || mpeg_version > 2 )
|
||||
return 0;
|
||||
for( i = 1; i < mpeg_num_aspect_ratios[mpeg_version-1]; ++i )
|
||||
{
|
||||
y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version-1][i-1];
|
||||
y4m_ratio_reduce( &red_entry );
|
||||
if( Y4M_RATIO_EQL( red_entry, red_ratio) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Guess the correct MPEG aspect ratio code,
|
||||
* given the true sample aspect ratio and frame size of a video stream
|
||||
* (and the MPEG version, 1 or 2).
|
||||
*
|
||||
* Returns 0 if it has no good guess.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* this is big enough to accommodate the difference between 720 and 704 */
|
||||
#define GUESS_ASPECT_TOLERANCE 0.03
|
||||
|
||||
mpeg_aspect_code_t
|
||||
mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect,
|
||||
int frame_width, int frame_height)
|
||||
{
|
||||
if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_UNKNOWN))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
switch (mpeg_version) {
|
||||
case 1:
|
||||
if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_CCIR601))
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_16_9))
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_CCIR601))
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_16_9))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE))
|
||||
{
|
||||
return 1; /* '1' means square *pixels* in MPEG-2; go figure. */
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
double true_far; /* true frame aspect ratio */
|
||||
true_far =
|
||||
(double)(sampleaspect.n * frame_width) /
|
||||
(double)(sampleaspect.d * frame_height);
|
||||
/* start at '2'... */
|
||||
for (i = 2; i < mpeg_num_aspect_ratios[mpeg_version-1]; i++)
|
||||
{
|
||||
double ratio =
|
||||
true_far / Y4M_RATIO_DBL(mpeg_aspect_ratios[mpeg_version-1][i-1]);
|
||||
if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) &&
|
||||
(ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) )
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Guess the true sample aspect ratio of a video stream,
|
||||
* given the MPEG aspect ratio code and the actual frame size
|
||||
* (and the MPEG version, 1 or 2).
|
||||
*
|
||||
* Returns y4m_sar_UNKNOWN if it has no good guess.
|
||||
*
|
||||
*/
|
||||
y4m_ratio_t
|
||||
mpeg_guess_sample_aspect_ratio(int mpeg_version,
|
||||
mpeg_aspect_code_t code,
|
||||
int frame_width, int frame_height)
|
||||
{
|
||||
switch (mpeg_version)
|
||||
{
|
||||
case 1:
|
||||
/* MPEG-1 codes turn into SAR's, just not quite the right ones.
|
||||
For the common/known values, we provide the ratio used in practice,
|
||||
otherwise say we don't know.*/
|
||||
switch (code)
|
||||
{
|
||||
case 1: return y4m_sar_SQUARE; break;
|
||||
case 3: return y4m_sar_PAL_16_9; break;
|
||||
case 6: return y4m_sar_NTSC_16_9; break;
|
||||
case 8: return y4m_sar_PAL_CCIR601; break;
|
||||
case 12: return y4m_sar_NTSC_CCIR601; break;
|
||||
default:
|
||||
return y4m_sar_UNKNOWN; break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* MPEG-2 codes turn into Frame Aspect Ratios, though not exactly the
|
||||
FAR's used in practice. For common/standard frame sizes, we provide
|
||||
the original SAR; otherwise, we say we don't know. */
|
||||
if (code == 1)
|
||||
{
|
||||
return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */
|
||||
}
|
||||
else if ((code >= 2) && (code <= 4))
|
||||
{
|
||||
return y4m_guess_sar(frame_width, frame_height,
|
||||
mpeg2_aspect_ratios[code-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return y4m_sar_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return y4m_sar_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Look-up MPEG explanatory definition string for frame rate code
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const char *
|
||||
mpeg_framerate_code_definition( mpeg_framerate_code_t code )
|
||||
{
|
||||
if( code == 0 || code >= mpeg_num_framerates )
|
||||
return "UNDEFINED: illegal/reserved frame-rate ratio code";
|
||||
|
||||
return framerate_definitions[code];
|
||||
}
|
||||
|
||||
/*
|
||||
* Look-up MPEG explanatory definition string aspect ratio code for an
|
||||
* aspect ratio code
|
||||
*
|
||||
*/
|
||||
|
||||
const char *
|
||||
mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code )
|
||||
{
|
||||
if( mpeg_version < 1 || mpeg_version > 2 )
|
||||
return "UNDEFINED: illegal MPEG version";
|
||||
|
||||
if( code < 1 || code > mpeg_num_aspect_ratios[mpeg_version-1] )
|
||||
return "UNDEFINED: illegal aspect ratio code";
|
||||
|
||||
return aspect_ratio_definitions[mpeg_version-1][code-1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Look-up explanatory definition of interlace field order code
|
||||
*
|
||||
*/
|
||||
|
||||
const char *
|
||||
mpeg_interlace_code_definition( int yuv4m_interlace_code )
|
||||
{
|
||||
const char *def;
|
||||
switch( yuv4m_interlace_code )
|
||||
{
|
||||
case Y4M_UNKNOWN :
|
||||
def = "unknown";
|
||||
break;
|
||||
case Y4M_ILACE_NONE :
|
||||
def = "none/progressive";
|
||||
break;
|
||||
case Y4M_ILACE_TOP_FIRST :
|
||||
def = "top-field-first";
|
||||
break;
|
||||
case Y4M_ILACE_BOTTOM_FIRST :
|
||||
def = "bottom-field-first";
|
||||
break;
|
||||
default :
|
||||
def = "UNDEFINED: illegal video interlacing type-code!";
|
||||
break;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
149
veejay-current/utils/mpegconsts.h
Normal file
149
veejay-current/utils/mpegconsts.h
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
/*
|
||||
* mpegconsts.c: Video format constants for MPEG and utilities for display
|
||||
* and conversion to format used for yuv4mpeg
|
||||
*
|
||||
* Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MPEGCONSTS_H__
|
||||
#define __MPEGCONSTS_H__
|
||||
|
||||
|
||||
#include "yuv4mpeg.h"
|
||||
|
||||
|
||||
typedef unsigned int mpeg_framerate_code_t;
|
||||
typedef unsigned int mpeg_aspect_code_t;
|
||||
|
||||
extern const mpeg_framerate_code_t mpeg_num_framerates;
|
||||
extern const mpeg_aspect_code_t mpeg_num_aspect_ratios[2];
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert MPEG frame-rate code to corresponding frame-rate
|
||||
* y4m_fps_UNKNOWN = { 0, 0 } = Undefined/resrerved code.
|
||||
*/
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_framerate( mpeg_framerate_code_t code );
|
||||
|
||||
|
||||
/*
|
||||
* Look-up MPEG frame rate code for a (exact) frame rate.
|
||||
* 0 = No MPEG code defined for frame-rate
|
||||
*/
|
||||
|
||||
mpeg_framerate_code_t
|
||||
mpeg_framerate_code( y4m_ratio_t framerate );
|
||||
|
||||
|
||||
/*
|
||||
* Convert floating-point framerate to an exact ratio.
|
||||
* Uses a standard MPEG rate, if it finds one within MPEG_FPS_TOLERANCE
|
||||
* (see mpegconsts.c), otherwise uses "fps:1000000" as the ratio.
|
||||
*/
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_conform_framerate( double fps );
|
||||
|
||||
|
||||
/*
|
||||
* Convert MPEG aspect ratio code to corresponding aspect ratio
|
||||
*
|
||||
* WARNING: The semantics of aspect ratio coding *changed* between
|
||||
* MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In
|
||||
* MPEG2 it is the (far more sensible) aspect ratio of the eventual
|
||||
* display.
|
||||
*
|
||||
*/
|
||||
|
||||
y4m_ratio_t
|
||||
mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code );
|
||||
|
||||
/*
|
||||
* Look-up MPEG aspect ratio code for an aspect ratio - tolerance
|
||||
* is Y4M_ASPECT_MULT used by YUV4MPEG (see yuv4mpeg_intern.h)
|
||||
*
|
||||
* WARNING: The semantics of aspect ratio coding *changed* between
|
||||
* MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In
|
||||
* MPEG2 it is the (far more sensible) aspect ratio of the eventual
|
||||
* display.
|
||||
*
|
||||
*/
|
||||
|
||||
mpeg_aspect_code_t
|
||||
mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio );
|
||||
|
||||
/*
|
||||
* Look-up MPEG explanatory definition string aspect ratio code for an
|
||||
* aspect ratio code
|
||||
*
|
||||
*/
|
||||
|
||||
const char *
|
||||
mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code );
|
||||
|
||||
/*
|
||||
* Look-up MPEG explanatory definition string aspect ratio code for an
|
||||
* frame rate code
|
||||
*
|
||||
*/
|
||||
|
||||
const char *
|
||||
mpeg_framerate_code_definition( mpeg_framerate_code_t code );
|
||||
|
||||
const char *
|
||||
mpeg_interlace_code_definition( int yuv4m_interlace_code );
|
||||
|
||||
|
||||
/*
|
||||
* Guess the correct MPEG aspect ratio code,
|
||||
* given the true sample aspect ratio and frame size of a video stream
|
||||
* (and the MPEG version, 1 or 2).
|
||||
*
|
||||
* Returns 0 if it has no good answer.
|
||||
*
|
||||
*/
|
||||
mpeg_aspect_code_t
|
||||
mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect,
|
||||
int frame_width, int frame_height);
|
||||
|
||||
/*
|
||||
* Guess the true sample aspect ratio of a video stream,
|
||||
* given the MPEG aspect ratio code and the actual frame size
|
||||
* (and the MPEG version, 1 or 2).
|
||||
*
|
||||
* Returns y4m_sar_UNKNOWN if it has no good answer.
|
||||
*
|
||||
*/
|
||||
y4m_ratio_t
|
||||
mpeg_guess_sample_aspect_ratio(int mpeg_version,
|
||||
mpeg_aspect_code_t code,
|
||||
int frame_width, int frame_height);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* __MPEGCONSTS_H__ */
|
||||
105
veejay-current/utils/mpegtimecode.c
Normal file
105
veejay-current/utils/mpegtimecode.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Kawamata/Hitoshi <hitoshi.kawamata@nifty.ne.jp>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include "mpegtimecode.h"
|
||||
|
||||
/**************************************************************
|
||||
* // NTSC DROP FRAME TIMECODE / 29.97fps (SMTPE)
|
||||
* // hh:mm:ss:ff
|
||||
* // hh: 0..
|
||||
* // mm: 0..59
|
||||
* // ss: 0..59
|
||||
* // ff: 0..29 # ss != 0 || mm % 10 == 0
|
||||
* // 2..29 # ss == 0 && mm % 10 != 0
|
||||
* //
|
||||
* // 00:00:00:00 00:00:00:01 00:00:00:02 ... 00:00:00:29
|
||||
* // 00:00:01:00 00:00:01:01 00:00:01:02 ... 00:00:01:29
|
||||
* // :
|
||||
* // 00:00:59:00 00:00:59:01 00:00:59:02 ... 00:00:59:29
|
||||
* // 00:01:00:02 ... 00:01:00:29
|
||||
* // 00:01:01:00 00:01:01:01 00:01:01:02 ... 00:01:00:29
|
||||
* // :
|
||||
* // 00:01:59:00 00:01:59:01 00:01:59:02 ... 00:01:59:29
|
||||
* // 00:02:00:02 ... 00:02:00:29
|
||||
* // 00:02:01:00 00:02:01:01 00:02:01:02 ... 00:02:00:29
|
||||
* // :
|
||||
* // :
|
||||
* // 00:09:59:00 00:09:59:01 00:09:59:02 ... 00:09:59:29
|
||||
* // 00:10:00:00 00:10:00:01 00:10:00:02 ... 00:10:00:29
|
||||
* // 00:10:01:00 00:10:01:01 00:10:01:02 ... 00:10:01:29
|
||||
* // :
|
||||
* // 00:10:59:00 00:10:59:01 00:10:59:02 ... 00:10:59:29
|
||||
* // 00:11:00:02 ... 00:11:00:29
|
||||
* // 00:11:01:00 00:11:01:01 00:11:01:02 ... 00:11:00:29
|
||||
* // :
|
||||
* // :
|
||||
* // DROP FRAME / 59.94fps (no any standard)
|
||||
* // DROP FRAME / 23.976fps (no any standard)
|
||||
***************************************************************/
|
||||
|
||||
int dropframetimecode = -1;
|
||||
|
||||
/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */
|
||||
int
|
||||
mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps)
|
||||
{
|
||||
static const int ifpss[] = { 0, 24, 24, 25, 30, 30, 50, 60, 60, };
|
||||
int h, m, s;
|
||||
|
||||
if (dropframetimecode < 0) {
|
||||
char *env = getenv("MJPEG_DROP_FRAME_TIME_CODE");
|
||||
dropframetimecode = (env && *env != '0' && *env != 'n' && *env != 'N');
|
||||
}
|
||||
if (dropframetimecode &&
|
||||
0 < fpscode && fpscode + 1 < sizeof ifpss / sizeof ifpss[0] &&
|
||||
ifpss[fpscode] == ifpss[fpscode + 1]) {
|
||||
int topinmin = 0, k = (30*4) / ifpss[fpscode];
|
||||
f *= k; /* frame# when 119.88fps */
|
||||
h = (f / ((10*60*30-18)*4)); /* # of 10min. */
|
||||
f %= ((10*60*30-18)*4); /* frame# in 10min. */
|
||||
f -= (2*4); /* frame# in 10min. - (2*4) */
|
||||
m = (f / ((60*30-2)*4)); /* min. in 10min. */
|
||||
topinmin = ((f - k) / ((60*30-2)*4) < m);
|
||||
m += (h % 6 * 10); /* min. */
|
||||
h /= 6; /* hour */
|
||||
f %= ((60*30-2)*4); /* frame# in min. - (2*4)*/
|
||||
f += (2*4); /* frame# in min. */
|
||||
s = f / (30*4); /* sec. */
|
||||
f %= (30*4); /* frame# in sec. */
|
||||
f /= k; /* frame# in sec. on original fps */
|
||||
tc->f = f;
|
||||
if (topinmin)
|
||||
f = -f;
|
||||
} else {
|
||||
int ifps = ((0 < fpscode && fpscode < sizeof ifpss / sizeof ifpss[0])?
|
||||
ifpss[fpscode]: (int)(fps + .5));
|
||||
s = f / ifps;
|
||||
f %= ifps;
|
||||
m = s / 60;
|
||||
s %= 60;
|
||||
h = m / 60;
|
||||
m %= 60;
|
||||
tc->f = f;
|
||||
}
|
||||
tc->s = s;
|
||||
tc->m = m;
|
||||
tc->h = h;
|
||||
return f;
|
||||
}
|
||||
39
veejay-current/utils/mpegtimecode.h
Normal file
39
veejay-current/utils/mpegtimecode.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* -*- mode:C -*- */
|
||||
/*
|
||||
* Copyright (C) 2001 Kawamata/Hitoshi <hitoshi.kawamata@nifty.ne.jp>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __MPEGTIMECODE_H__
|
||||
#define __MPEGTIMECODE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char h, m, s, f;
|
||||
} MPEG_timecode_t;
|
||||
|
||||
extern int dropframetimecode;
|
||||
extern int mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps);
|
||||
/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
118
veejay-current/utils/videodev_mjpeg.h
Normal file
118
veejay-current/utils/videodev_mjpeg.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* These are the MJPEG API extensions for the Video4Linux API,
|
||||
first introduced by the Iomega Buz driver by Rainer Johanni
|
||||
<rainer@johanni.de>
|
||||
*/
|
||||
|
||||
/* This is identical with the mgavideo internal params struct,
|
||||
please tell me if you change this struct here ! <gz@lysator.liu.se) */
|
||||
struct mjpeg_params
|
||||
{
|
||||
|
||||
/* The following parameters can only be queried */
|
||||
|
||||
int major_version; /* Major version number of driver */
|
||||
int minor_version; /* Minor version number of driver */
|
||||
|
||||
/* Main control parameters */
|
||||
|
||||
int input; /* Input channel: 0 = Composite, 1 = S-VHS */
|
||||
int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
|
||||
int decimation; /* decimation of captured video,
|
||||
enlargement of video played back.
|
||||
Valid values are 1, 2, 4 or 0.
|
||||
0 is a special value where the user
|
||||
has full control over video scaling */
|
||||
|
||||
/* The following parameters only have to be set if decimation==0,
|
||||
for other values of decimation they provide the data how the image is captured */
|
||||
|
||||
int HorDcm; /* Horizontal decimation: 1, 2 or 4 */
|
||||
int VerDcm; /* Vertical decimation: 1 or 2 */
|
||||
int TmpDcm; /* Temporal decimation: 1 or 2,
|
||||
if TmpDcm==2 in capture every second frame is dropped,
|
||||
in playback every frame is played twice */
|
||||
int field_per_buff; /* Number of fields per buffer: 1 or 2 */
|
||||
int img_x; /* start of image in x direction */
|
||||
int img_y; /* start of image in y direction */
|
||||
int img_width; /* image width BEFORE decimation,
|
||||
must be a multiple of HorDcm*16 */
|
||||
int img_height; /* image height BEFORE decimation,
|
||||
must be a multiple of VerDcm*8 */
|
||||
|
||||
/* --- End of parameters for decimation==0 only --- */
|
||||
|
||||
/* JPEG control parameters */
|
||||
|
||||
int quality; /* Measure for quality of compressed images.
|
||||
Scales linearly with the size of the compressed images.
|
||||
Must be beetween 0 and 100, 100 is a compression
|
||||
ratio of 1:4 */
|
||||
|
||||
int odd_even; /* Which field should come first ???
|
||||
This is more aptly named "top_first",
|
||||
i.e. (odd_even==1) --> top-field-first */
|
||||
|
||||
int APPn; /* Number of APP segment to be written, must be 0..15 */
|
||||
int APP_len; /* Length of data in JPEG APPn segment */
|
||||
char APP_data[60]; /* Data in the JPEG APPn segment. */
|
||||
|
||||
int COM_len; /* Length of data in JPEG COM segment */
|
||||
char COM_data[60]; /* Data in JPEG COM segment */
|
||||
|
||||
unsigned long jpeg_markers; /* Which markers should go into the JPEG output.
|
||||
Unless you exactly know what you do, leave them untouched.
|
||||
Inluding less markers will make the resulting code
|
||||
smaller, but there will be fewer aplications
|
||||
which can read it.
|
||||
The presence of the APP and COM marker is
|
||||
influenced by APP0_len and COM_len ONLY! */
|
||||
#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
|
||||
#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
|
||||
#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
|
||||
#define JPEG_MARKER_COM (1<<6) /* Comment segment */
|
||||
#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */
|
||||
|
||||
int VFIFO_FB; /* Flag for enabling Video Fifo Feedback.
|
||||
If this flag is turned on and JPEG decompressing
|
||||
is going to the screen, the decompress process
|
||||
is stopped every time the Video Fifo is full.
|
||||
This enables a smooth decompress to the screen
|
||||
but the video output signal will get scrambled */
|
||||
|
||||
/* Misc */
|
||||
|
||||
char reserved[312]; /* Makes 512 bytes for this structure */
|
||||
};
|
||||
|
||||
struct mjpeg_requestbuffers
|
||||
{
|
||||
unsigned long count; /* Number of buffers for MJPEG grabbing */
|
||||
unsigned long size; /* Size PER BUFFER in bytes */
|
||||
};
|
||||
|
||||
struct mjpeg_sync
|
||||
{
|
||||
unsigned long frame; /* Frame (0 - n) for double buffer */
|
||||
unsigned long length; /* number of code bytes in buffer (capture only) */
|
||||
unsigned long seq; /* frame sequence number */
|
||||
struct timeval timestamp; /* timestamp */
|
||||
};
|
||||
|
||||
struct mjpeg_status
|
||||
{
|
||||
int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */
|
||||
int signal; /* Returned: 1 if valid video signal detected */
|
||||
int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
|
||||
int color; /* Returned: 1 if color signal detected */
|
||||
};
|
||||
|
||||
/*
|
||||
Private IOCTL to set up for displaying MJPEG
|
||||
*/
|
||||
#define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params)
|
||||
#define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params)
|
||||
#define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers)
|
||||
#define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int)
|
||||
#define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int)
|
||||
#define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync)
|
||||
#define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status)
|
||||
774
veejay-current/utils/yuv4mpeg.c
Normal file
774
veejay-current/utils/yuv4mpeg.c
Normal file
@@ -0,0 +1,774 @@
|
||||
/*
|
||||
* yuv4mpeg.c: Functions for reading and writing "new" YUV4MPEG streams
|
||||
*
|
||||
* Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "yuv4mpeg.h"
|
||||
#include "yuv4mpeg_intern.h"
|
||||
#include "mjpeg_logging.h"
|
||||
|
||||
|
||||
static int _y4mparam_allow_unknown_tags = 1; /* default is forgiveness */
|
||||
|
||||
static void *(*_y4m_alloc)(size_t bytes) = malloc;
|
||||
static void (*_y4m_free)(void *ptr) = free;
|
||||
|
||||
|
||||
|
||||
int y4m_allow_unknown_tags(int yn)
|
||||
{
|
||||
int old = _y4mparam_allow_unknown_tags;
|
||||
if (yn >= 0)
|
||||
_y4mparam_allow_unknown_tags = (yn) ? 1 : 0;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Convenience functions for fd read/write
|
||||
*
|
||||
* - guaranteed to transfer entire payload (or fail)
|
||||
* - returns:
|
||||
* 0 on complete success
|
||||
* +(# of remaining bytes) on eof (for y4m_read)
|
||||
* -(# of rem. bytes) on error (and ERRNO should be set)
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
ssize_t y4m_read(int fd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t n;
|
||||
uint8_t *ptr = (uint8_t *)buf;
|
||||
|
||||
while (len > 0) {
|
||||
n = read(fd, ptr, len);
|
||||
if (n <= 0) {
|
||||
/* return amount left to read */
|
||||
if (n == 0)
|
||||
return len; /* n == 0 --> eof */
|
||||
else
|
||||
return -len; /* n < 0 --> error */
|
||||
}
|
||||
ptr += n;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ssize_t y4m_write(int fd, const void *buf, size_t len)
|
||||
{
|
||||
ssize_t n;
|
||||
const uint8_t *ptr = (const uint8_t *)buf;
|
||||
|
||||
while (len > 0) {
|
||||
n = write(fd, ptr, len);
|
||||
if (n <= 0) return -len; /* return amount left to write */
|
||||
ptr += n;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* "Extra tags" handling
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
static char *y4m_new_xtag(void)
|
||||
{
|
||||
return _y4m_alloc(Y4M_MAX_XTAG_SIZE * sizeof(char));
|
||||
}
|
||||
|
||||
|
||||
void y4m_init_xtag_list(y4m_xtag_list_t *xtags)
|
||||
{
|
||||
int i;
|
||||
xtags->count = 0;
|
||||
for (i = 0; i < Y4M_MAX_XTAGS; i++) {
|
||||
xtags->tags[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void y4m_fini_xtag_list(y4m_xtag_list_t *xtags)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < Y4M_MAX_XTAGS; i++) {
|
||||
if (xtags->tags[i] != NULL) {
|
||||
_y4m_free(xtags->tags[i]);
|
||||
xtags->tags[i] = NULL;
|
||||
}
|
||||
}
|
||||
xtags->count = 0;
|
||||
}
|
||||
|
||||
|
||||
void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < src->count; i++) {
|
||||
if (dest->tags[i] == NULL)
|
||||
dest->tags[i] = y4m_new_xtag();
|
||||
strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE);
|
||||
}
|
||||
dest->count = src->count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int y4m_snprint_xtags(char *s, int maxn, const y4m_xtag_list_t *xtags)
|
||||
{
|
||||
int i, room;
|
||||
|
||||
for (i = 0, room = maxn - 1; i < xtags->count; i++) {
|
||||
int n = snprintf(s, room + 1, " %s", xtags->tags[i]);
|
||||
if ((n < 0) || (n > room)) return Y4M_ERR_HEADER;
|
||||
s += n;
|
||||
room -= n;
|
||||
}
|
||||
s[0] = '\n'; /* finish off header with newline */
|
||||
s[1] = '\0'; /* ...and end-of-string */
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
int y4m_xtag_count(const y4m_xtag_list_t *xtags)
|
||||
{
|
||||
return xtags->count;
|
||||
}
|
||||
|
||||
|
||||
const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n)
|
||||
{
|
||||
if (n >= xtags->count)
|
||||
return NULL;
|
||||
else
|
||||
return xtags->tags[n];
|
||||
}
|
||||
|
||||
|
||||
int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag)
|
||||
{
|
||||
if (xtags->count >= Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS;
|
||||
if (xtags->tags[xtags->count] == NULL)
|
||||
xtags->tags[xtags->count] = y4m_new_xtag();
|
||||
strncpy(xtags->tags[xtags->count], tag, Y4M_MAX_XTAG_SIZE);
|
||||
(xtags->count)++;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n)
|
||||
{
|
||||
int i;
|
||||
char *q;
|
||||
|
||||
if ((n < 0) || (n >= xtags->count)) return Y4M_ERR_RANGE;
|
||||
q = xtags->tags[n];
|
||||
for (i = n; i < (xtags->count - 1); i++)
|
||||
xtags->tags[i] = xtags->tags[i+1];
|
||||
xtags->tags[i] = q;
|
||||
(xtags->count)--;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
int y4m_xtag_clearlist(y4m_xtag_list_t *xtags)
|
||||
{
|
||||
xtags->count = 0;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if ((dest->count + src->count) > Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS;
|
||||
for (i = dest->count, j = 0;
|
||||
j < src->count;
|
||||
i++, j++) {
|
||||
if (dest->tags[i] == NULL)
|
||||
dest->tags[i] = y4m_new_xtag();
|
||||
strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE);
|
||||
}
|
||||
dest->count += src->count;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Creators/destructors for y4m_*_info_t structures
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void y4m_init_stream_info(y4m_stream_info_t *info)
|
||||
{
|
||||
if (info == NULL) return;
|
||||
/* initialize info */
|
||||
info->width = Y4M_UNKNOWN;
|
||||
info->height = Y4M_UNKNOWN;
|
||||
info->interlace = Y4M_UNKNOWN;
|
||||
info->framerate = y4m_fps_UNKNOWN;
|
||||
info->sampleaspect = y4m_sar_UNKNOWN;
|
||||
y4m_init_xtag_list(&(info->x_tags));
|
||||
}
|
||||
|
||||
|
||||
void y4m_copy_stream_info(y4m_stream_info_t *dest,
|
||||
const y4m_stream_info_t *src)
|
||||
{
|
||||
if ((dest == NULL) || (src == NULL)) return;
|
||||
/* copy info */
|
||||
dest->width = src->width;
|
||||
dest->height = src->height;
|
||||
dest->interlace = src->interlace;
|
||||
dest->framerate = src->framerate;
|
||||
dest->sampleaspect = src->sampleaspect;
|
||||
dest->framelength = src->framelength;
|
||||
y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags));
|
||||
}
|
||||
|
||||
|
||||
void y4m_fini_stream_info(y4m_stream_info_t *info)
|
||||
{
|
||||
if (info == NULL) return;
|
||||
y4m_fini_xtag_list(&(info->x_tags));
|
||||
}
|
||||
|
||||
|
||||
void y4m_si_set_width(y4m_stream_info_t *si, int width)
|
||||
{
|
||||
si->width = width;
|
||||
si->framelength = (si->height * si->width) * 3 / 2;
|
||||
}
|
||||
|
||||
int y4m_si_get_width(const y4m_stream_info_t *si)
|
||||
{ return si->width; }
|
||||
|
||||
void y4m_si_set_height(y4m_stream_info_t *si, int height)
|
||||
{
|
||||
si->height = height;
|
||||
si->framelength = (si->height * si->width) * 3 / 2;
|
||||
}
|
||||
|
||||
int y4m_si_get_height(const y4m_stream_info_t *si)
|
||||
{ return si->height; }
|
||||
|
||||
void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace)
|
||||
{ si->interlace = interlace; }
|
||||
|
||||
int y4m_si_get_interlace(const y4m_stream_info_t *si)
|
||||
{ return si->interlace; }
|
||||
|
||||
void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate)
|
||||
{ si->framerate = framerate; }
|
||||
|
||||
y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si)
|
||||
{ return si->framerate; }
|
||||
|
||||
void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar)
|
||||
{ si->sampleaspect = sar; }
|
||||
|
||||
y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si)
|
||||
{ return si->sampleaspect; }
|
||||
|
||||
int y4m_si_get_framelength(const y4m_stream_info_t *si)
|
||||
{ return si->framelength; }
|
||||
|
||||
y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si)
|
||||
{ return &(si->x_tags); }
|
||||
|
||||
|
||||
|
||||
void y4m_init_frame_info(y4m_frame_info_t *info)
|
||||
{
|
||||
if (info == NULL) return;
|
||||
/* initialize info */
|
||||
y4m_init_xtag_list(&(info->x_tags));
|
||||
}
|
||||
|
||||
|
||||
void y4m_copy_frame_info(y4m_frame_info_t *dest, const y4m_frame_info_t *src)
|
||||
{
|
||||
if ((dest == NULL) || (src == NULL)) return;
|
||||
/* copy info */
|
||||
y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags));
|
||||
}
|
||||
|
||||
|
||||
void y4m_fini_frame_info(y4m_frame_info_t *info)
|
||||
{
|
||||
if (info == NULL) return;
|
||||
y4m_fini_xtag_list(&(info->x_tags));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Tag parsing
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i)
|
||||
{
|
||||
char *token, *value;
|
||||
char tag;
|
||||
int err;
|
||||
|
||||
/* parse fields */
|
||||
for (token = strtok(s, Y4M_DELIM);
|
||||
token != NULL;
|
||||
token = strtok(NULL, Y4M_DELIM)) {
|
||||
if (token[0] == '\0') continue; /* skip empty strings */
|
||||
tag = token[0];
|
||||
value = token + 1;
|
||||
switch (tag) {
|
||||
case 'W': /* width */
|
||||
i->width = atoi(value);
|
||||
if (i->width <= 0) return Y4M_ERR_RANGE;
|
||||
break;
|
||||
case 'H': /* height */
|
||||
i->height = atoi(value);
|
||||
if (i->height <= 0) return Y4M_ERR_RANGE;
|
||||
break;
|
||||
case 'F': /* frame rate (fps) */
|
||||
if ((err = y4m_parse_ratio(&(i->framerate), value)) != Y4M_OK)
|
||||
return err;
|
||||
if (i->framerate.n < 0) return Y4M_ERR_RANGE;
|
||||
break;
|
||||
case 'I': /* interlacing */
|
||||
switch (value[0]) {
|
||||
case 'p': i->interlace = Y4M_ILACE_NONE; break;
|
||||
case 't': i->interlace = Y4M_ILACE_TOP_FIRST; break;
|
||||
case 'b': i->interlace = Y4M_ILACE_BOTTOM_FIRST; break;
|
||||
case '?':
|
||||
default:
|
||||
i->interlace = Y4M_UNKNOWN; break;
|
||||
}
|
||||
break;
|
||||
case 'A': /* sample (pixel) aspect ratio */
|
||||
if ((err = y4m_parse_ratio(&(i->sampleaspect), value)) != Y4M_OK)
|
||||
return err;
|
||||
if (i->sampleaspect.n < 0) return Y4M_ERR_RANGE;
|
||||
break;
|
||||
case 'X': /* 'X' meta-tag */
|
||||
if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err;
|
||||
break;
|
||||
default:
|
||||
/* possible error on unknown options */
|
||||
if (_y4mparam_allow_unknown_tags) {
|
||||
/* unknown tags ok: store in xtag list and warn... */
|
||||
if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err;
|
||||
mjpeg_warn("Unknown stream tag encountered: '%s'", token);
|
||||
} else {
|
||||
/* unknown tags are *not* ok */
|
||||
return Y4M_ERR_BADTAG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error checking... width and height must be known since we can't
|
||||
* parse without them
|
||||
*/
|
||||
if( i->width == Y4M_UNKNOWN || i->height == Y4M_UNKNOWN )
|
||||
return Y4M_ERR_HEADER;
|
||||
/* ta da! done. */
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int y4m_parse_frame_tags(char *s, y4m_frame_info_t *i)
|
||||
{
|
||||
char *token, *value;
|
||||
char tag;
|
||||
int err;
|
||||
|
||||
/* parse fields */
|
||||
for (token = strtok(s, Y4M_DELIM);
|
||||
token != NULL;
|
||||
token = strtok(NULL, Y4M_DELIM)) {
|
||||
if (token[0] == '\0') continue; /* skip empty strings */
|
||||
tag = token[0];
|
||||
value = token + 1;
|
||||
switch (tag) {
|
||||
case 'X': /* 'X' meta-tag */
|
||||
if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err;
|
||||
break;
|
||||
default:
|
||||
/* possible error on unknown options */
|
||||
if (_y4mparam_allow_unknown_tags) {
|
||||
/* unknown tags ok: store in xtag list and warn... */
|
||||
if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err;
|
||||
mjpeg_warn("Unknown frame tag encountered: '%s'", token);
|
||||
} else {
|
||||
/* unknown tags are *not* ok */
|
||||
return Y4M_ERR_BADTAG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* ta da! done. */
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Read/Write stream header
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
int y4m_read_stream_header(int fd, y4m_stream_info_t *i)
|
||||
{
|
||||
char line[Y4M_LINE_MAX];
|
||||
char *p;
|
||||
int n;
|
||||
int err;
|
||||
|
||||
/* read the header line */
|
||||
for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) {
|
||||
if (read(fd, p, 1) < 1)
|
||||
return Y4M_ERR_SYSTEM;
|
||||
if (*p == '\n') {
|
||||
*p = '\0'; /* Replace linefeed by end of string */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n >= Y4M_LINE_MAX)
|
||||
return Y4M_ERR_HEADER;
|
||||
/* look for keyword in header */
|
||||
if (strncmp(line, Y4M_MAGIC, strlen(Y4M_MAGIC)))
|
||||
return Y4M_ERR_MAGIC;
|
||||
if ((err = y4m_parse_stream_tags(line + strlen(Y4M_MAGIC), i)) != Y4M_OK)
|
||||
return err;
|
||||
|
||||
i->framelength = (i->height * i->width) * 3 / 2;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int y4m_write_stream_header(int fd, const y4m_stream_info_t *i)
|
||||
{
|
||||
char s[Y4M_LINE_MAX+1];
|
||||
int n;
|
||||
int err;
|
||||
y4m_ratio_t rate = i->framerate;
|
||||
y4m_ratio_t aspect = i->sampleaspect;
|
||||
|
||||
y4m_ratio_reduce(&rate);
|
||||
y4m_ratio_reduce(&aspect);
|
||||
n = snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d",
|
||||
Y4M_MAGIC,
|
||||
i->width,
|
||||
i->height,
|
||||
rate.n, rate.d,
|
||||
(i->interlace == Y4M_ILACE_NONE) ? "p" :
|
||||
(i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" :
|
||||
(i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : "?",
|
||||
aspect.n, aspect.d);
|
||||
if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER;
|
||||
if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags)))
|
||||
!= Y4M_OK)
|
||||
return err;
|
||||
/* non-zero on error */
|
||||
return (y4m_write(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Read/Write frame header
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
int y4m_read_frame_header(int fd, y4m_frame_info_t *i)
|
||||
{
|
||||
char line[Y4M_LINE_MAX];
|
||||
char *p;
|
||||
int n;
|
||||
ssize_t remain;
|
||||
|
||||
/* This is more clever than read_stream_header...
|
||||
Try to read "FRAME\n" all at once, and don't try to parse
|
||||
if nothing else is there...
|
||||
*/
|
||||
remain = y4m_read(fd, line, sizeof(Y4M_FRAME_MAGIC)-1+1); /* -'\0', +'\n' */
|
||||
if (remain < 0) return Y4M_ERR_SYSTEM;
|
||||
if (remain > 0) {
|
||||
/* A clean EOF should end exactly at a frame-boundary */
|
||||
if (remain == sizeof(Y4M_FRAME_MAGIC))
|
||||
return Y4M_ERR_EOF;
|
||||
else
|
||||
return Y4M_ERR_BADEOF;
|
||||
}
|
||||
if (strncmp(line, Y4M_FRAME_MAGIC, sizeof(Y4M_FRAME_MAGIC)-1))
|
||||
return Y4M_ERR_MAGIC;
|
||||
if (line[sizeof(Y4M_FRAME_MAGIC)-1] == '\n')
|
||||
return Y4M_OK; /* done -- no tags: that was the end-of-line. */
|
||||
|
||||
if (line[sizeof(Y4M_FRAME_MAGIC)-1] != Y4M_DELIM[0]) {
|
||||
return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */
|
||||
}
|
||||
|
||||
/* proceed to get the tags... (overwrite the magic) */
|
||||
for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) {
|
||||
if (y4m_read(fd, p, 1))
|
||||
return Y4M_ERR_SYSTEM;
|
||||
if (*p == '\n') {
|
||||
*p = '\0'; /* Replace linefeed by end of string */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER;
|
||||
/* non-zero on error */
|
||||
return y4m_parse_frame_tags(line, i);
|
||||
}
|
||||
|
||||
|
||||
int y4m_write_frame_header(int fd, const y4m_frame_info_t *i)
|
||||
{
|
||||
char s[Y4M_LINE_MAX+1];
|
||||
int n;
|
||||
int err;
|
||||
|
||||
n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC);
|
||||
if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER;
|
||||
if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags)))
|
||||
!= Y4M_OK)
|
||||
return err;
|
||||
/* non-zero on error */
|
||||
return (y4m_write(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Read/Write entire frame
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
int y4m_read_frame(int fd, const y4m_stream_info_t *si,
|
||||
y4m_frame_info_t *fi, uint8_t * const yuv[3])
|
||||
{
|
||||
int err;
|
||||
int w = si->width;
|
||||
int h = si->height;
|
||||
|
||||
/* Read frame header */
|
||||
if ((err = y4m_read_frame_header(fd, fi)) != Y4M_OK) return err;
|
||||
/* Read luminance scanlines */
|
||||
if (y4m_read(fd, yuv[0], w*h)) return Y4M_ERR_SYSTEM;
|
||||
/* Read chrominance scanlines */
|
||||
if (y4m_read(fd, yuv[1], w*h/4)) return Y4M_ERR_SYSTEM;
|
||||
if (y4m_read(fd, yuv[2], w*h/4)) return Y4M_ERR_SYSTEM;
|
||||
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int y4m_write_frame(int fd, const y4m_stream_info_t *si,
|
||||
const y4m_frame_info_t *fi, uint8_t * const yuv[3])
|
||||
{
|
||||
int err;
|
||||
int w = si->width;
|
||||
int h = si->height;
|
||||
|
||||
/* Write frame header */
|
||||
if ((err = y4m_write_frame_header(fd, fi)) != Y4M_OK) return err;
|
||||
/* Write luminance,chrominance scanlines */
|
||||
if (y4m_write(fd, yuv[0], w*h) ||
|
||||
y4m_write(fd, yuv[1], w*h/4) ||
|
||||
y4m_write(fd, yuv[2], w*h/4))
|
||||
return Y4M_ERR_SYSTEM;
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Read/Write entire frame, (de)interleaved (to)from two separate fields
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi,
|
||||
uint8_t * const upper_field[3],
|
||||
uint8_t * const lower_field[3])
|
||||
{
|
||||
int i, y, err;
|
||||
int width = si->width;
|
||||
int height = si->height;
|
||||
|
||||
/* Read frame header */
|
||||
if ((err = y4m_read_frame_header(fd, fi)) != Y4M_OK) return err;
|
||||
/* Read Y', Cb, and Cr planes */
|
||||
for (i = 0; i < 3; i++) {
|
||||
uint8_t *srctop = upper_field[i];
|
||||
uint8_t *srcbot = lower_field[i];
|
||||
/* alternately write one line from each */
|
||||
for (y = 0; y < height; y += 2) {
|
||||
if (y4m_read(fd, srctop, width)) return Y4M_ERR_SYSTEM;
|
||||
srctop += width;
|
||||
if (y4m_read(fd, srcbot, width)) return Y4M_ERR_SYSTEM;
|
||||
srcbot += width;
|
||||
}
|
||||
/* for chroma, width/height are half as big */
|
||||
if (i == 0) {
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
}
|
||||
}
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int y4m_write_fields(int fd, const y4m_stream_info_t *si,
|
||||
const y4m_frame_info_t *fi,
|
||||
uint8_t * const upper_field[3],
|
||||
uint8_t * const lower_field[3])
|
||||
{
|
||||
int i, y, err;
|
||||
int width = si->width;
|
||||
int height = si->height;
|
||||
|
||||
/* Write frame header */
|
||||
if ((err = y4m_write_frame_header(fd, fi)) != Y4M_OK) return err;
|
||||
/* Write Y', Cb, and Cr planes */
|
||||
for (i = 0; i < 3; i++) {
|
||||
uint8_t *srctop = upper_field[i];
|
||||
uint8_t *srcbot = lower_field[i];
|
||||
/* alternately write one line from each */
|
||||
for (y = 0; y < height; y += 2) {
|
||||
if (y4m_write(fd, srctop, width)) return Y4M_ERR_SYSTEM;
|
||||
srctop += width;
|
||||
if (y4m_write(fd, srcbot, width)) return Y4M_ERR_SYSTEM;
|
||||
srcbot += width;
|
||||
}
|
||||
/* for chroma, width/height are half as big */
|
||||
if (i == 0) {
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
}
|
||||
}
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Handy logging of stream info
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
void y4m_log_stream_info(log_level_t level, const char *prefix,
|
||||
const y4m_stream_info_t *i)
|
||||
{
|
||||
char s[256];
|
||||
|
||||
snprintf(s, sizeof(s), " frame size: ");
|
||||
if (i->width == Y4M_UNKNOWN)
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?)x");
|
||||
else
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "%dx", i->width);
|
||||
if (i->height == Y4M_UNKNOWN)
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?) pixels ");
|
||||
else
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "%d pixels ", i->height);
|
||||
if (i->framelength == Y4M_UNKNOWN)
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)");
|
||||
else
|
||||
snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", i->framelength);
|
||||
mjpeg_log(level, "%s%s", prefix, s);
|
||||
if ((i->framerate.n == 0) && (i->framerate.d == 0))
|
||||
mjpeg_log(level, "%s frame rate: ??? fps", prefix);
|
||||
else
|
||||
mjpeg_log(level, "%s frame rate: %d/%d fps (~%f)", prefix,
|
||||
i->framerate.n, i->framerate.d,
|
||||
(double) i->framerate.n / (double) i->framerate.d);
|
||||
mjpeg_log(level, "%s interlace: %s", prefix,
|
||||
(i->interlace == Y4M_ILACE_NONE) ? "none/progressive" :
|
||||
(i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" :
|
||||
(i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" :
|
||||
"anyone's guess");
|
||||
if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0))
|
||||
mjpeg_log(level, "%ssample aspect ratio: ?:?", prefix);
|
||||
else
|
||||
mjpeg_log(level, "%ssample aspect ratio: %d:%d", prefix,
|
||||
i->sampleaspect.n, i->sampleaspect.d);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Convert error code to string
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
const char *y4m_strerr(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case Y4M_OK: return "no error";
|
||||
case Y4M_ERR_RANGE: return "parameter out of range";
|
||||
case Y4M_ERR_SYSTEM: return "system error (failed read/write)";
|
||||
case Y4M_ERR_HEADER: return "bad stream or frame header";
|
||||
case Y4M_ERR_BADTAG: return "unknown header tag";
|
||||
case Y4M_ERR_MAGIC: return "bad header magic";
|
||||
case Y4M_ERR_XXTAGS: return "too many xtags";
|
||||
case Y4M_ERR_EOF: return "end-of-file";
|
||||
case Y4M_ERR_BADEOF: return "stream ended unexpectedly (EOF)";
|
||||
default:
|
||||
return "unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
473
veejay-current/utils/yuv4mpeg.h
Normal file
473
veejay-current/utils/yuv4mpeg.h
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* yuv4mpeg.h: Functions for reading and writing "new" YUV4MPEG2 streams.
|
||||
*
|
||||
* Stream format is described at the end of this file.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __YUV4MPEG_H__
|
||||
#define __YUV4MPEG_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <mjpeg_types.h>
|
||||
#include <unistd.h>
|
||||
#include <mjpeg_logging.h>
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* error codes returned by y4m_* functions
|
||||
************************************************************************/
|
||||
#define Y4M_OK 0
|
||||
#define Y4M_ERR_RANGE 1 /* argument or tag value out of range */
|
||||
#define Y4M_ERR_SYSTEM 2 /* failed system call, check errno */
|
||||
#define Y4M_ERR_HEADER 3 /* illegal/malformed header */
|
||||
#define Y4M_ERR_BADTAG 4 /* illegal tag character */
|
||||
#define Y4M_ERR_MAGIC 5 /* bad header magic */
|
||||
#define Y4M_ERR_EOF 6 /* end-of-file (clean) */
|
||||
#define Y4M_ERR_XXTAGS 7 /* too many xtags */
|
||||
#define Y4M_ERR_BADEOF 8 /* unexpected end-of-file */
|
||||
|
||||
|
||||
/* generic 'unknown' value for integer parameters (e.g. interlace, height) */
|
||||
#define Y4M_UNKNOWN -1
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'ratio' datatype, for rational numbers
|
||||
* (see 'ratio' functions down below)
|
||||
************************************************************************/
|
||||
typedef struct _y4m_ratio {
|
||||
int n; /* numerator */
|
||||
int d; /* denominator */
|
||||
} y4m_ratio_t;
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* useful standard framerates (as ratios)
|
||||
************************************************************************/
|
||||
extern const y4m_ratio_t y4m_fps_UNKNOWN;
|
||||
extern const y4m_ratio_t y4m_fps_NTSC_FILM; /* 24000/1001 film (in NTSC) */
|
||||
extern const y4m_ratio_t y4m_fps_FILM; /* 24fps film */
|
||||
extern const y4m_ratio_t y4m_fps_PAL; /* 25fps PAL */
|
||||
extern const y4m_ratio_t y4m_fps_NTSC; /* 30000/1001 NTSC */
|
||||
extern const y4m_ratio_t y4m_fps_30; /* 30fps */
|
||||
extern const y4m_ratio_t y4m_fps_PAL_FIELD; /* 50fps PAL field rate */
|
||||
extern const y4m_ratio_t y4m_fps_NTSC_FIELD; /* 60000/1001 NTSC field rate */
|
||||
extern const y4m_ratio_t y4m_fps_60; /* 60fps */
|
||||
|
||||
/************************************************************************
|
||||
* useful standard sample (pixel) aspect ratios (W:H)
|
||||
************************************************************************/
|
||||
extern const y4m_ratio_t y4m_sar_UNKNOWN;
|
||||
extern const y4m_ratio_t y4m_sar_SQUARE; /* square pixels */
|
||||
extern const y4m_ratio_t y4m_sar_NTSC_CCIR601; /* 525-line (NTSC) Rec.601 */
|
||||
extern const y4m_ratio_t y4m_sar_NTSC_16_9; /* 16:9 NTSC/Rec.601 */
|
||||
extern const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3; /* NTSC SVCD 4:3 */
|
||||
extern const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9;/* NTSC SVCD 16:9 */
|
||||
extern const y4m_ratio_t y4m_sar_PAL_CCIR601; /* 625-line (PAL) Rec.601 */
|
||||
extern const y4m_ratio_t y4m_sar_PAL_16_9; /* 16:9 PAL/Rec.601 */
|
||||
extern const y4m_ratio_t y4m_sar_PAL_SVCD_4_3; /* PAL SVCD 4:3 */
|
||||
extern const y4m_ratio_t y4m_sar_PAL_SVCD_16_9; /* PAL SVCD 16:9 */
|
||||
extern const y4m_ratio_t y4m_sar_SQR_ANA16_9; /* anamorphic 16:9 sampled */
|
||||
/* from 4:3 with square pixels */
|
||||
|
||||
/************************************************************************
|
||||
* useful standard display aspect ratios (W:H)
|
||||
************************************************************************/
|
||||
extern const y4m_ratio_t y4m_dar_UNKNOWN;
|
||||
extern const y4m_ratio_t y4m_dar_4_3; /* standard TV */
|
||||
extern const y4m_ratio_t y4m_dar_16_9; /* widescreen TV */
|
||||
extern const y4m_ratio_t y4m_dar_221_100; /* word-to-your-mother TV */
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'xtag_list' --- list of unparsed and/or meta/X header tags
|
||||
*
|
||||
* Do not touch this structure directly!
|
||||
*
|
||||
* Use the y4m_xtag_*() functions (see below).
|
||||
* You must initialize/finalize this structure before/after use.
|
||||
************************************************************************/
|
||||
#define Y4M_MAX_XTAGS 32 /* maximum number of xtags in list */
|
||||
#define Y4M_MAX_XTAG_SIZE 32 /* max length of an xtag (including 'X') */
|
||||
typedef struct _y4m_xtag_list {
|
||||
int count;
|
||||
char *tags[Y4M_MAX_XTAGS];
|
||||
} y4m_xtag_list_t;
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'stream_info' --- stream header information
|
||||
*
|
||||
* Do not touch this structure directly!
|
||||
*
|
||||
* Use the y4m_si_*() functions (see below).
|
||||
* You must initialize/finalize this structure before/after use.
|
||||
************************************************************************/
|
||||
typedef struct _y4m_stream_info {
|
||||
/* values from header */
|
||||
int width;
|
||||
int height;
|
||||
int interlace; /* see Y4M_ILACE_* definitions below */
|
||||
y4m_ratio_t framerate; /* frames-per-second; 0:0 == unknown */
|
||||
y4m_ratio_t sampleaspect; /* pixel width/height; 0:0 == unknown */
|
||||
/* computed/derivative values */
|
||||
int framelength; /* bytes of data per frame (not including header) */
|
||||
/* mystical X tags */
|
||||
y4m_xtag_list_t x_tags;
|
||||
} y4m_stream_info_t;
|
||||
|
||||
/* possible options for the interlace parameter */
|
||||
#define Y4M_ILACE_NONE 0 /* non-interlaced, progressive frame */
|
||||
#define Y4M_ILACE_TOP_FIRST 1 /* interlaced, top-field first */
|
||||
#define Y4M_ILACE_BOTTOM_FIRST 2 /* interlaced, bottom-field first */
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'frame_info' --- frame header information
|
||||
*
|
||||
* Do not touch this structure directly!
|
||||
*
|
||||
* Use the y4m_fi_*() functions (see below).
|
||||
* You must initialize/finalize this structure before/after use.
|
||||
************************************************************************/
|
||||
typedef struct _y4m_frame_info {
|
||||
/* mystical X tags */
|
||||
y4m_xtag_list_t x_tags;
|
||||
} y4m_frame_info_t;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'ratio' functions
|
||||
************************************************************************/
|
||||
|
||||
/* 'normalize' a ratio (remove common factors) */
|
||||
void y4m_ratio_reduce(y4m_ratio_t *r);
|
||||
|
||||
/* parse "nnn:ddd" into a ratio (returns Y4M_OK or Y4M_ERR_RANGE) */
|
||||
int y4m_parse_ratio(y4m_ratio_t *r, const char *s);
|
||||
|
||||
/* quick test of two ratios for equality (i.e. identical components) */
|
||||
#define Y4M_RATIO_EQL(a,b) ( ((a).n == (b).n) && ((a).d == (b).d) )
|
||||
|
||||
/* quick conversion of a ratio to a double (no divide-by-zero check!) */
|
||||
#define Y4M_RATIO_DBL(r) ((double)(r).n / (double)(r).d)
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Guess the true SAR (sample aspect ratio) from a list of commonly
|
||||
* encountered values, given the "suggested" display aspect ratio (DAR),
|
||||
* and the true frame width and height.
|
||||
*
|
||||
* Returns y4m_sar_UNKNOWN if no match is found.
|
||||
*
|
||||
*************************************************************************/
|
||||
y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 'xtag' functions
|
||||
*
|
||||
* o Before using an xtag_list (but after the structure/memory has been
|
||||
* allocated), you must initialize it via y4m_init_xtag_list().
|
||||
* o After using an xtag_list (but before the structure is released),
|
||||
* call y4m_fini_xtag_list() to free internal memory.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* initialize an xtag_list structure */
|
||||
void y4m_init_xtag_list(y4m_xtag_list_t *xtags);
|
||||
|
||||
/* finalize an xtag_list structure */
|
||||
void y4m_fini_xtag_list(y4m_xtag_list_t *xtags);
|
||||
|
||||
/* make one xtag_list into a copy of another */
|
||||
void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src);
|
||||
|
||||
/* return number of tags in an xtag_list */
|
||||
int y4m_xtag_count(const y4m_xtag_list_t *xtags);
|
||||
|
||||
/* access n'th tag in an xtag_list */
|
||||
const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n);
|
||||
|
||||
/* append a new tag to an xtag_list
|
||||
returns: Y4M_OK - success
|
||||
Y4M_ERR_XXTAGS - list is already full */
|
||||
int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag);
|
||||
|
||||
/* remove a tag from an xtag_list
|
||||
returns: Y4M_OK - success
|
||||
Y4M_ERR_RANGE - n is out of range */
|
||||
int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n);
|
||||
|
||||
/* remove all tags from an xtag_list
|
||||
returns: Y4M_OK - success */
|
||||
int y4m_xtag_clearlist(y4m_xtag_list_t *xtags);
|
||||
|
||||
/* append copies of tags from src list to dest list
|
||||
returns: Y4M_OK - success
|
||||
Y4M_ERR_XXTAGS - operation would overfill dest list */
|
||||
int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* '*_info' functions
|
||||
*
|
||||
* o Before using a *_info structure (but after the structure/memory has
|
||||
* been allocated), you must initialize it via y4m_init_*_info().
|
||||
* o After using a *_info structure (but before the structure is released),
|
||||
* call y4m_fini_*_info() to free internal memory.
|
||||
* o Use the 'set' and 'get' accessors to modify or access the fields in
|
||||
* the structures; don't touch the structure directly. (Ok, so there
|
||||
* is no really convenient C syntax to prevent you from doing this,
|
||||
* but we are all responsible programmers here, so just don't do it!)
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* initialize a stream_info structure */
|
||||
void y4m_init_stream_info(y4m_stream_info_t *i);
|
||||
|
||||
/* finalize a stream_info structure */
|
||||
void y4m_fini_stream_info(y4m_stream_info_t *i);
|
||||
|
||||
/* make one stream_info into a copy of another */
|
||||
void y4m_copy_stream_info(y4m_stream_info_t *dest,
|
||||
const y4m_stream_info_t *src);
|
||||
|
||||
/* access or set stream_info fields */
|
||||
void y4m_si_set_width(y4m_stream_info_t *si, int width);
|
||||
int y4m_si_get_width(const y4m_stream_info_t *si);
|
||||
void y4m_si_set_height(y4m_stream_info_t *si, int height);
|
||||
int y4m_si_get_height(const y4m_stream_info_t *si);
|
||||
void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace);
|
||||
int y4m_si_get_interlace(const y4m_stream_info_t *si);
|
||||
void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate);
|
||||
y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si);
|
||||
void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar);
|
||||
y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si);
|
||||
int y4m_si_get_framelength(const y4m_stream_info_t *si);
|
||||
|
||||
/* access stream_info xtag_list */
|
||||
y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si);
|
||||
|
||||
|
||||
/* initialize a frame_info structure */
|
||||
void y4m_init_frame_info(y4m_frame_info_t *i);
|
||||
|
||||
/* finalize a frame_info structure */
|
||||
void y4m_fini_frame_info(y4m_frame_info_t *i);
|
||||
|
||||
/* make one frame_info into a copy of another */
|
||||
void y4m_copy_frame_info(y4m_frame_info_t *dest,
|
||||
const y4m_frame_info_t *src);
|
||||
|
||||
/* access frame_info xtag_list */
|
||||
y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* blocking read and write functions
|
||||
*
|
||||
* o guaranteed to transfer entire payload (or fail)
|
||||
* o return values:
|
||||
* 0 (zero) complete success
|
||||
* -(# of remaining bytes) error (and errno left set)
|
||||
* +(# of remaining bytes) EOF (for y4m_read only)
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* read len bytes from fd into buf */
|
||||
ssize_t y4m_read(int fd, void *buf, size_t len);
|
||||
|
||||
/* write len bytes from fd into buf */
|
||||
ssize_t y4m_write(int fd, const void *buf, size_t len);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* stream header processing functions
|
||||
*
|
||||
* o return values:
|
||||
* Y4M_OK - success
|
||||
* Y4M_ERR_* - error (see y4m_strerr() for descriptions)
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* parse a string of stream header tags */
|
||||
int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i);
|
||||
|
||||
/* read a stream header from file descriptor fd */
|
||||
int y4m_read_stream_header(int fd, y4m_stream_info_t *i);
|
||||
|
||||
/* write a stream header to file descriptor fd */
|
||||
int y4m_write_stream_header(int fd, const y4m_stream_info_t *i);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* frame processing functions
|
||||
*
|
||||
* o return values:
|
||||
* Y4M_OK - success
|
||||
* Y4M_ERR_* - error (see y4m_strerr() for descriptions)
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* read a frame header from file descriptor fd */
|
||||
int y4m_read_frame_header(int fd, y4m_frame_info_t *i);
|
||||
|
||||
/* write a frame header to file descriptor fd */
|
||||
int y4m_write_frame_header(int fd, const y4m_frame_info_t *i);
|
||||
|
||||
/* read a complete frame (header + data)
|
||||
o yuv[3] points to three buffers, one each for Y, U, V planes */
|
||||
int y4m_read_frame(int fd, const y4m_stream_info_t *si,
|
||||
y4m_frame_info_t *fi, uint8_t * const yuv[3]);
|
||||
|
||||
/* write a complete frame (header + data)
|
||||
o yuv[3] points to three buffers, one each for Y, U, V planes */
|
||||
int y4m_write_frame(int fd, const y4m_stream_info_t *si,
|
||||
const y4m_frame_info_t *fi, uint8_t * const yuv[3]);
|
||||
|
||||
|
||||
/* read a complete frame (header + data), but de-interleave fields
|
||||
into two separate buffers
|
||||
o upper_field[3] same as yuv[3] above, but for upper field
|
||||
o lower_field[3] same as yuv[3] above, but for lower field
|
||||
*/
|
||||
int y4m_read_fields(int fd, const y4m_stream_info_t *si,
|
||||
y4m_frame_info_t *fi,
|
||||
uint8_t * const upper_field[3],
|
||||
uint8_t * const lower_field[3]);
|
||||
|
||||
/* write a complete frame (header + data), but interleave fields
|
||||
from two separate buffers
|
||||
o upper_field[3] same as yuv[3] above, but for upper field
|
||||
o lower_field[3] same as yuv[3] above, but for lower field
|
||||
*/
|
||||
int y4m_write_fields(int fd, const y4m_stream_info_t *si,
|
||||
const y4m_frame_info_t *fi,
|
||||
uint8_t * const upper_field[3],
|
||||
uint8_t * const lower_field[3]);
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* miscellaneous functions
|
||||
************************************************************************/
|
||||
|
||||
/* convenient dump of stream header info via mjpeg_log facility
|
||||
* - each logged/printed line is prefixed by 'prefix'
|
||||
*/
|
||||
void y4m_log_stream_info(log_level_t level, const char *prefix,
|
||||
const y4m_stream_info_t *i);
|
||||
|
||||
/* convert a Y4M_ERR_* error code into mildly explanatory string */
|
||||
const char *y4m_strerr(int err);
|
||||
|
||||
/* set 'allow_unknown_tag' flag for library...
|
||||
o yn = 0 : unknown header tags will produce a parsing error
|
||||
o yn = 1 : unknown header tags/values will produce a warning, but
|
||||
are otherwise passed along via the xtags list
|
||||
o yn = -1: don't change, just return current setting
|
||||
|
||||
return value: previous setting of flag
|
||||
*/
|
||||
int y4m_allow_unknown_tags(int yn);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
************************************************************************
|
||||
|
||||
Description of the (new!, forever?) YUV4MPEG2 stream format:
|
||||
|
||||
STREAM consists of
|
||||
o one '\n' terminated STREAM-HEADER
|
||||
o unlimited number of FRAMEs
|
||||
|
||||
FRAME consists of
|
||||
o one '\n' terminated FRAME-HEADER
|
||||
o "length" octets of planar YCrCb 4:2:0 image data
|
||||
(if frame is interlaced, then the two fields are interleaved)
|
||||
|
||||
|
||||
STREAM-HEADER consists of
|
||||
o string "YUV4MPEG2 " (note the space after the '2')
|
||||
o unlimited number of ' ' separated TAGGED-FIELDs
|
||||
o '\n' line terminator
|
||||
|
||||
FRAME-HEADER consists of
|
||||
o string "FRAME " (note the space after the 'E')
|
||||
o unlimited number of ' ' separated TAGGED-FIELDs
|
||||
o '\n' line terminator
|
||||
|
||||
|
||||
TAGGED-FIELD consists of
|
||||
o single ascii character tag
|
||||
o VALUE (which does not contain whitespace)
|
||||
|
||||
VALUE consists of
|
||||
o integer (base 10 ascii representation)
|
||||
or o RATIO
|
||||
or o single ascii character
|
||||
or o generic ascii string
|
||||
|
||||
RATIO consists of
|
||||
o numerator (integer)
|
||||
o ':' (a colon)
|
||||
o denominator (integer)
|
||||
|
||||
|
||||
The currently supported tags for the STREAM-HEADER:
|
||||
W - [integer] frame width, pixels, should be > 0
|
||||
H - [integer] frame height, pixels, should be > 0
|
||||
I - [char] interlacing: p - progressive (none)
|
||||
t - top-field-first
|
||||
b - bottom-field-first
|
||||
? - unknown
|
||||
F - [ratio] frame-rate, 0:0 == unknown
|
||||
A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown
|
||||
X - [character string] 'metadata' (unparsed, but passed around)
|
||||
|
||||
The currently supported tags for the FRAME-HEADER:
|
||||
X - character string 'metadata' (unparsed, but passed around)
|
||||
|
||||
************************************************************************
|
||||
************************************************************************/
|
||||
|
||||
#endif /* __YUV4MPEG_H__ */
|
||||
|
||||
|
||||
85
veejay-current/utils/yuv4mpeg_intern.h
Normal file
85
veejay-current/utils/yuv4mpeg_intern.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* yuv4mpeg_intern.h: Internal constants for "new" YUV4MPEG streams
|
||||
*
|
||||
* Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
|
||||
* Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __YUV4MPEG_INTERN_H__
|
||||
#define __YUV4MPEG_INTERN_H__
|
||||
|
||||
|
||||
#define Y4M_MAGIC "YUV4MPEG2"
|
||||
#define Y4M_FRAME_MAGIC "FRAME"
|
||||
|
||||
#define Y4M_DELIM " " /* single-character(space) separating tagged fields */
|
||||
|
||||
#define Y4M_LINE_MAX 256 /* max number of characters in a header line
|
||||
(including the '\n', but not the '\0') */
|
||||
|
||||
|
||||
/* standard framerate ratios */
|
||||
#define Y4M_FPS_UNKNOWN { 0, 0 }
|
||||
#define Y4M_FPS_NTSC_FILM { 24000, 1001 }
|
||||
#define Y4M_FPS_FILM { 24, 1 }
|
||||
#define Y4M_FPS_PAL { 25, 1 }
|
||||
#define Y4M_FPS_NTSC { 30000, 1001 }
|
||||
#define Y4M_FPS_30 { 30, 1 }
|
||||
#define Y4M_FPS_PAL_FIELD { 50, 1 }
|
||||
#define Y4M_FPS_NTSC_FIELD { 60000, 1001 }
|
||||
#define Y4M_FPS_60 { 60, 1 }
|
||||
|
||||
/* standard sample/pixel aspect ratios */
|
||||
#define Y4M_SAR_UNKNOWN { 0, 0 }
|
||||
#define Y4M_SAR_SQUARE { 1, 1 }
|
||||
#define Y4M_SAR_SQR_ANA_16_9 { 4, 3 }
|
||||
#define Y4M_SAR_NTSC_CCIR601 { 10, 11 }
|
||||
#define Y4M_SAR_NTSC_16_9 { 40, 33 }
|
||||
#define Y4M_SAR_NTSC_SVCD_4_3 { 15, 11 }
|
||||
#define Y4M_SAR_NTSC_SVCD_16_9 { 20, 11 }
|
||||
#define Y4M_SAR_PAL_CCIR601 { 59, 54 }
|
||||
#define Y4M_SAR_PAL_16_9 { 118, 81 }
|
||||
#define Y4M_SAR_PAL_SVCD_4_3 { 59, 36 }
|
||||
#define Y4M_SAR_PAL_SVCD_16_9 { 59, 27 }
|
||||
|
||||
#define Y4M_SAR_MPEG1_1 Y4M_SAR_SQUARE
|
||||
#define Y4M_SAR_MPEG1_2 { 10000, 6735 }
|
||||
#define Y4M_SAR_MPEG1_3 { 10000, 7031 } /* Anamorphic 16:9 PAL */
|
||||
#define Y4M_SAR_MPEG1_4 { 10000, 7615 }
|
||||
#define Y4M_SAR_MPEG1_5 { 10000, 8055 }
|
||||
#define Y4M_SAR_MPEG1_6 { 10000, 8437 } /* Anamorphic 16:9 NTSC */
|
||||
#define Y4M_SAR_MPEG1_7 { 10000, 8935 }
|
||||
#define Y4M_SAR_MPEG1_8 { 10000, 9375 } /* PAL/SECAM 4:3 */
|
||||
#define Y4M_SAR_MPEG1_9 { 10000, 9815 }
|
||||
#define Y4M_SAR_MPEG1_10 { 10000, 10255 }
|
||||
#define Y4M_SAR_MPEG1_11 { 10000, 10695 }
|
||||
#define Y4M_SAR_MPEG1_12 { 10000, 11250 } /* NTSC 4:3 */
|
||||
#define Y4M_SAR_MPEG1_13 { 10000, 11575 }
|
||||
#define Y4M_SAR_MPEG1_14 { 10000, 12015 }
|
||||
|
||||
#define Y4M_DAR_UNKNOWN { 0, 0 }
|
||||
#define Y4M_DAR_4_3 { 4, 3 }
|
||||
#define Y4M_DAR_16_9 { 16, 9 }
|
||||
#define Y4M_DAR_221_100 { 221, 100 }
|
||||
|
||||
#define Y4M_DAR_MPEG2_1 { 1, 1 }
|
||||
#define Y4M_DAR_MPEG2_2 { 4, 3 }
|
||||
#define Y4M_DAR_MPEG2_3 { 16, 9 }
|
||||
#define Y4M_DAR_MPEG2_4 { 221, 100 }
|
||||
|
||||
#endif /* __YUV4MPEG_INTERN_H__ */
|
||||
|
||||
156
veejay-current/utils/yuv4mpeg_ratio.c
Normal file
156
veejay-current/utils/yuv4mpeg_ratio.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* yuv4mpeg_ratio.c: Functions for dealing with y4m_ratio_t datatype.
|
||||
*
|
||||
* Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "yuv4mpeg.h"
|
||||
#include "yuv4mpeg_intern.h"
|
||||
|
||||
|
||||
/* useful list of standard framerates */
|
||||
const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN;
|
||||
const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM;
|
||||
const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM;
|
||||
const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL;
|
||||
const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC;
|
||||
const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30;
|
||||
const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD;
|
||||
const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD;
|
||||
const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60;
|
||||
|
||||
/* useful list of standard sample aspect ratios */
|
||||
const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN;
|
||||
const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE;
|
||||
const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9;
|
||||
const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601;
|
||||
const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9;
|
||||
const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3;
|
||||
const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9;
|
||||
const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601;
|
||||
const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9;
|
||||
const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3;
|
||||
const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9;
|
||||
|
||||
/* useful list of standard display aspect ratios */
|
||||
const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3;
|
||||
const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9;
|
||||
const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100;
|
||||
|
||||
/*
|
||||
* Euler's algorithm for greatest common divisor
|
||||
*/
|
||||
|
||||
static int gcd(int a, int b)
|
||||
{
|
||||
a = (a >= 0) ? a : -a;
|
||||
b = (b >= 0) ? b : -b;
|
||||
|
||||
while (b > 0) {
|
||||
int x = b;
|
||||
b = a % b;
|
||||
a = x;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Remove common factors from a ratio
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void y4m_ratio_reduce(y4m_ratio_t *r)
|
||||
{
|
||||
int d;
|
||||
if ((r->n == 0) && (r->d == 0)) return; /* "unknown" */
|
||||
d = gcd(r->n, r->d);
|
||||
r->n /= d;
|
||||
r->d /= d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Parse "nnn:ddd" into a ratio
|
||||
*
|
||||
* returns: Y4M_OK - success
|
||||
* Y4M_ERR_RANGE - range error
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
int y4m_parse_ratio(y4m_ratio_t *r, const char *s)
|
||||
{
|
||||
char *t = strchr(s, ':');
|
||||
if (t == NULL) return Y4M_ERR_RANGE;
|
||||
r->n = atoi(s);
|
||||
r->d = atoi(t+1);
|
||||
if (r->d < 0) return Y4M_ERR_RANGE;
|
||||
/* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */
|
||||
if ((r->d == 0) && (r->n != 0)) return Y4M_ERR_RANGE;
|
||||
y4m_ratio_reduce(r);
|
||||
return Y4M_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Guess the true SAR (sample aspect ratio) from a list of commonly
|
||||
* encountered values, given the "suggested" display aspect ratio, and
|
||||
* the true frame width and height.
|
||||
*
|
||||
* Returns y4m_sar_UNKNOWN if no match is found.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
/* this is big enough to accommodate the difference between 720 and 704 */
|
||||
#define GUESS_ASPECT_TOLERANCE 0.03
|
||||
|
||||
y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar)
|
||||
{
|
||||
int i;
|
||||
double implicit_sar = (double)(dar.n * height) / (double)(dar.d * width);
|
||||
y4m_ratio_t sarray[] =
|
||||
{
|
||||
y4m_sar_SQUARE,
|
||||
y4m_sar_NTSC_CCIR601,
|
||||
y4m_sar_NTSC_16_9,
|
||||
y4m_sar_NTSC_SVCD_4_3,
|
||||
y4m_sar_NTSC_SVCD_16_9,
|
||||
y4m_sar_PAL_CCIR601,
|
||||
y4m_sar_PAL_16_9,
|
||||
y4m_sar_PAL_SVCD_4_3,
|
||||
y4m_sar_PAL_SVCD_16_9,
|
||||
y4m_sar_UNKNOWN
|
||||
};
|
||||
for (i = 0; !(Y4M_RATIO_EQL(sarray[i],y4m_sar_UNKNOWN)); i++) {
|
||||
double ratio = implicit_sar / Y4M_RATIO_DBL(sarray[i]);
|
||||
if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) &&
|
||||
(ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) )
|
||||
return sarray[i];
|
||||
}
|
||||
return y4m_sar_UNKNOWN;
|
||||
}
|
||||
Reference in New Issue
Block a user