Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
mediastreamer2
Commits
3426ac87
Commit
3426ac87
authored
Aug 01, 2011
by
Simon Morlat
Browse files
initial commit of g726 support (untested)
parent
1b8cb290
Changes
5
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
3426ac87
...
...
@@ -541,7 +541,31 @@ fi
fi
dnl check for spandsp support to bring up g726 codec
AC_ARG_ENABLE(spandsp,
[ --disable-spandsp Disable spandsp support],
[case "${enableval}" in
yes) spandsp=true ;;
no) spandsp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-spandsp) ;;
esac],[spandsp=true])
if test x$spandsp = xtrue; then
dnl check for installed version of speex
PKG_CHECK_MODULES(SPANDSP, spandsp >= 0.0.6,
[ AC_DEFINE(HAVE_SPANDSP,1,[tells whether spandsp can be used])
have_spandsp=true ],
[have_spandsp=false]
)
AC_SUBST(SPANDSP_CFLAGS)
AC_SUBST(SPANDSP_LIBS)
fi
AM_CONDITIONAL(BUILD_GSM, test x$build_gsm = xyes )
AM_CONDITIONAL(BUILD_G726, test "$have_spandsp" = "true" )
MS_CHECK_VIDEO
AM_CONDITIONAL(BUILD_VIDEO, test "$video" = "true")
...
...
include/mediastreamer2/allfilters.h
View file @
3426ac87
...
...
@@ -109,7 +109,23 @@ typedef enum MSFilterId{
MS_ANDROID_VIDEO_WRITE_ID
,
MS_TONE_DETECTOR_ID
,
MS_VP8_ENC_ID
,
MS_VP8_DEC_ID
MS_VP8_DEC_ID
,
MS_G726_40_ENC_ID
,
MS_G726_32_ENC_ID
,
MS_G726_24_ENC_ID
,
MS_G726_16_ENC_ID
,
MS_AAL2_G726_40_ENC_ID
,
MS_AAL2_G726_32_ENC_ID
,
MS_AAL2_G726_24_ENC_ID
,
MS_AAL2_G726_16_ENC_ID
,
MS_G726_40_DEC_ID
,
MS_G726_32_DEC_ID
,
MS_G726_24_DEC_ID
,
MS_G726_16_DEC_ID
,
MS_AAL2_G726_40_DEC_ID
,
MS_AAL2_G726_32_DEC_ID
,
MS_AAL2_G726_24_DEC_ID
,
MS_AAL2_G726_16_DEC_ID
}
MSFilterId
;
...
...
src/Makefile.am
View file @
3426ac87
...
...
@@ -66,6 +66,10 @@ if BUILD_GSM
libmediastreamer_la_SOURCES
+=
gsm.c
endif
if
BUILD_G726
libmediastreamer_la_SOURCES
+=
g726.c
endif
if
BUILD_WIN32
libmediastreamer_la_SOURCES
+=
winsnd3.c
\
msfileplayer_win.c msfilerec_win.c
...
...
@@ -185,7 +189,8 @@ libmediastreamer_la_LIBADD= $(ORTP_LIBS) \
$(SPEEX_LIBS)
\
$(GSM_LIBS)
\
$(LIBV4L1_LIBS)
\
$(LIBV4L2_LIBS)
$(LIBV4L2_LIBS)
\
$(SPANDSP_LIBS)
libmediastreamer_la_LDFLAGS
=
-no-undefined
-version-info
$(LIBMEDIASTREAMER_SO_VERSION)
...
...
@@ -215,7 +220,8 @@ AM_CFLAGS= $(ORTP_CFLAGS) \
$(SPEEX_CFLAGS)
\
$(GSM_CFLAGS)
\
$(STRICT_OPTIONS)
\
$(LIBPULSE_CFLAGS)
$(LIBPULSE_CFLAGS)
\
$(SPANDSP_CFLAGS)
AM_CXXFLAGS
=
$(ORTP_CFLAGS)
\
...
...
src/msv4m.m
deleted
100644 → 0
View file @
1b8cb290
/*
mediastreamer2
library
-
modular
sound
and
video
processing
and
streaming
Copyright
(
C
)
2006
Simon
MORLAT
(
simon
.
morlat
@
linphone
.
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
__
APPLE
__
#include
"mediastreamer-config.h"
#include
<
fcntl
.
h
>
#include
<
unistd
.
h
>
#include
<
sys
/
stat
.
h
>
#include
<
sys
/
types
.
h
>
#include
<
sys
/
ioctl
.
h
>
#include
<
errno
.
h
>
#include
<
string
.
h
>
#include
"mediastreamer2/msvideo.h"
#include
"mediastreamer2/msticker.h"
#include
"mediastreamer2/msv4l.h"
#include
"nowebcam.h"
#include
"mediastreamer2/mswebcam.h"
//
build
for
carbon
#define
TARGET
_
API
_
MAC
_
CARBON
1
#if
__
APPLE
_
CC
__
#include
<
Carbon
/
Carbon
.
h
>
#include
<
QuicKTime
/
QuickTime
.
h
>
#include
<
AppKit
/
AppKit
.
h
>
#else
#include
<
ConditionalMacros
.
h
>
#include
<
QuickTimeComponents
.
h
>
#include
<
TextUtils
.
h
>
#include
<
AppKit
/
AppKit
.
h
>
#include
<
stdio
.
h
>
#endif
typedef
struct
v4mState
{
char
*
name
;
char
*
id
;
SeqGrabComponent
seqgrab
;
SGChannel
sgchanvideo
;
GWorldPtr
pgworld
;
ImageSequence
decomseq
;
MSVideoSize
vsize
;
int
pix
_
fmt
;
mblk
_
t
*
mire
;
queue
_
t
rq
;
ms
_
mutex
_
t
mutex
;
int
frame
_
ind
;
int
frame
_
max
;
float
fps
;
float
start
_
time
;
int
frame
_
count
;
bool
_
t
run
;
bool
_
t
usemire
;
}
v4mState
;
static
void
v4m
_
init
(
MSFilter
*
f
){
v4mState
*
s
=
ms
_
new0
(
v4mState
,
1
)
;
s
->
seqgrab
=
NULL
;
s
->
sgchanvideo
=
NULL
;
s
->
pgworld
=
NULL
;
s
->
decomseq
=
0
;
s
->
run
=
FALSE
;
s
->
vsize
.
width
=
MS
_
VIDEO
_
SIZE
_
CIF
_
W
;
s
->
vsize
.
height
=
MS
_
VIDEO
_
SIZE
_
CIF
_
H
;
s
->
pix
_
fmt
=
MS
_
YUY2
;
qinit
(
&
s
->
rq
)
;
s
->
mire
=
NULL
;
ms
_
mutex
_
init
(
&
s
->
mutex
,
NULL
)
;
s
->
start
_
time
=
0
;
s
->
frame
_
count
=-
1
;
s
->
fps
=
15
;
s
->
usemire
=
(
getenv
(
"DEBUG"
)
!=
NULL
)
;
f
->
data
=
s
;
}
#define
BailErr
(
x
)
{
err
=
x
;
if
(
err
!=
noErr
)
goto
bail
;
}
pascal
OSErr
sgdata
_
callback
(
SGChannel
c
,
Ptr
p
,
long
len
,
long
*
offset
,
long
chRefCon
,
TimeValue
time
,
short
writeType
,
long
refCon
)
;
pascal
OSErr
sgdata
_
callback
(
SGChannel
c
,
Ptr
p
,
long
len
,
long
*
offset
,
long
chRefCon
,
TimeValue
time
,
short
writeType
,
long
refCon
)
{
#pragma
unused
(
offset
,
chRefCon
,
time
,
writeType
)
CodecFlags
ignore
;
v4mState
*
s
=
(
v4mState
*
)
refCon
;
ComponentResult
err
=
noErr
;
if
(
!
s
)
goto
bail
;
Rect
boundsRect
=
{
0
,
0
,
s
->
vsize
.
height
,
s
->
vsize
.
width
}
;
if
(
s
->
pgworld
)
{
if
(
s
->
decomseq
==
0
)
{
Rect
sourceRect
=
{
0
,
0
,
0
,
0
}
;
MatrixRecord
scaleMatrix
;
ImageDescriptionHandle
imageDesc
=
(
ImageDescriptionHandle
)
NewHandle
(
0
)
;
err
=
SGGetChannelSampleDescription
(
c
,
(
Handle
)
imageDesc
)
;
BailErr
(
err
)
;
ms
_
message
(
"raw image format: format=%c%c%c%c"
,
((
char
*
)
&
(
(**imageDesc).cType))[0],
((char*)
&
(
(**imageDesc).cType))[1],
((char*)
&
(
(**imageDesc).cType))[2],
((char*)
&
(
(**imageDesc).cType))[3]);
// make a scaling matrix for the sequence
sourceRect.right = (**imageDesc).width;
sourceRect.bottom = (**imageDesc).height;
RectMatrix(&scaleMatrix, &sourceRect, &(*GetPortPixMap(s->pgworld))->bounds);
err = DecompressSequenceBegin(&s->decomseq, // pointer to field to receive unique ID for sequence
imageDesc, // handle to image description structure
s->pgworld, // port for the DESTINATION image
NULL, // graphics device handle, if port is set, set to NULL
NULL, // source rectangle defining the portion of the image to decompress
&scaleMatrix, // transformation matrix
srcCopy, // transfer mode specifier
NULL, // clipping region in dest. coordinate system to use as a mask
0, // flags
codecHighQuality, //codecNormalQuality, // accuracy in decompression
bestSpeedCodec); // compressor identifier or special identifiers ie. bestSpeedCodec
BailErr(err);
DisposeHandle((Handle)imageDesc);
imageDesc = NULL;
}
// decompress a frame into the GWorld - can queue a frame for async decompression when passed in a completion proc
// once the image is in the GWorld it can be manipulated at will
err = DecompressSequenceFrameS(s->decomseq, // sequence ID returned by DecompressSequenceBegin
p, // pointer to compressed image data
len, // size of the buffer
0, // in flags
&ignore, // out flags
NULL); // async completion proc
BailErr(err);
PixMap * pixmap = *GetGWorldPixMap(s->pgworld);
uint8_t * data = (uint8_t *) GetPixBaseAddr(GetGWorldPixMap(s->pgworld));
if (s->pix_fmt==MS_YUY2)
{
int size = (s->vsize.width * s->vsize.height * 2);
mblk_t *buf;
buf=allocb(size,0);
memcpy(buf->b_wptr, data, size);
buf->b_wptr+=size;
putq(&s->rq, buf);
}
if (s->pix_fmt==MS_RGBA32)
{
mblk_t *buf;
int size = s->vsize.width * s->vsize.height * 4;
buf=allocb(size,0);
memcpy(buf->b_wptr, data, size);
buf->b_wptr+=size;
putq(&s->rq, buf);
}
if (s->pix_fmt==MS_RGB24)
{
unsigned line;
mblk_t *buf;
int size = s->vsize.width * s->vsize.height * 3;
buf=allocb(size,0);
unsigned rowBytes = pixmap->rowBytes & (((unsigned short) 0xFFFF) >> 2);
unsigned pixelSize = pixmap->pixelSize / 8; // Pixel size in bytes
unsigned lineOffset = rowBytes - s->vsize.width * pixelSize;
for (line = 0 ; line < s->vsize.height ; line++) {
unsigned offset = line * (s->vsize.width * pixelSize + lineOffset);
memcpy(buf->b_wptr + ((line * s->vsize.width) * pixelSize), data + offset, (rowBytes - lineOffset));
}
if (s->pix_fmt==MS_RGB24)
{
/* Conversion from top down bottom up (BGR to RGB and flip) */
unsigned long Index,nPixels;
unsigned char *blue;
unsigned char tmp;
short iPixelSize;
blue=buf->b_wptr;
nPixels=s->vsize.width*s->vsize.height;
iPixelSize=24/8;
for(Index=0;Index!=nPixels;Index++) // For each pixel
{
tmp=*blue;
*blue=*(blue+2);
*(blue+2)=tmp;
blue+=iPixelSize;
}
}
buf->b_wptr+=size;
putq(&s->rq, buf);
}
}
bail:
return err;
}
static int v4m_close(v4mState *s)
{
if(s->seqgrab)
CloseComponent(s->seqgrab);
s->seqgrab=NULL;
if (s->decomseq)
CDSequenceEnd(s->decomseq);
s->decomseq=0;
if (s->pgworld!=NULL)
DisposeGWorld(s->pgworld);
s->pgworld=NULL;
return 0;
}
unsigned char *stdToPascalString(char *buffer, char * str) {
if (strlen(str) <= 255) {
buffer[0] = strlen(str);
memcpy(buffer + 1, str, strlen(str));
return (unsigned char*)buffer;
} else {
return NULL;
}
}
static int sequence_grabber_start(v4mState *s)
{
OSErr err = noErr;
char *camName;
ms_warning("Opening component");
s->seqgrab = OpenDefaultComponent(SeqGrabComponentType, 0);
if (s->seqgrab == NULL) {
ms_warning("can't get default sequence grabber component");
return -1;
}
ms_warning("Initializing component");
err = SGInitialize(s->seqgrab);
if (err != noErr) {
ms_warning("can't initialize sequence grabber component");
return -1;
}
ms_warning("SetDataRef");
err = SGSetDataRef(s->seqgrab, 0, 0, seqGrabDontMakeMovie);
if (err != noErr) {
ms_warning("can't set the destination data reference");
return -1;
}
ms_warning("Creating new channel");
err = SGNewChannel(s->seqgrab, VideoMediaType, &s->sgchanvideo);
if (err != noErr) {
ms_warning("can't create a video channel");
return -1;
}
camName = alloca(strlen(s->name) + 1);
err = SGSetChannelDevice(s->sgchanvideo, stdToPascalString(camName, s->name));
if (err != noErr) {
ms_warning("can't set channel device");
return -1;
}
short input = atoi(s->id);
err = SGSetChannelDeviceInput(s->sgchanvideo,input);
if (err != noErr) {
ms_warning("can't set channel device input");
return -1;
}
ms_warning("createGWorld");
Rect theRect = {0, 0, s->vsize.height, s->vsize.width};
//err = QTNewGWorld(&(s->pgworld), // returned GWorld
// kYUVSPixelFormat, /* YUY2 */
// &theRect, // bounding rectangle
// 0, // color table
// NULL, // graphic device handle
// 0); // flags
VDCompressionListHandle h = (VDCompressionListHandle)NewHandle(0);
VideoDigitizerComponent vdig = SGGetVideoDigitizerComponent(s->sgchanvideo);
VDGetCompressionTypes(vdig,h);
unsigned long max = sizeof(**h) / sizeof(VDCompressionList);
for (int i=0; i<max;i++) {
VDCompressionList cl = (VDCompressionList)*h[i];
ms_message("codec format supported %c%c%c%c",
((char*)&(cl.cType))[0],
((char*)&(cl.cType))[1],
((char*)
&
(
cl
.
cType
))[
2
]
,
((
char
*
)
&
(
cl
.
cType
))[
3
])
;
}
if
(
s
->
pix
_
fmt
==
MS
_
YUY2
)
{
err
=
QTNewGWorld
(
&
(
s
->
pgworld
)
,
//
returned
GWorld
kYUVSPixelFormat
,
/*
YUY2
*/
&
theRect
,
//
bounding
rectangle
0
,
//
color
table
NULL
,
//
graphic
device
handle
0
)
;
if
(
err
!=
noErr
)
{
ms
_
message
(
"Failed to use YUY2"
)
;
}
}
if
(
s
->
pix
_
fmt
==
MS
_
RGBA32
)
{
err
=
QTNewGWorld
(
&
(
s
->
pgworld
)
,
//
returned
GWorld
k32RGBAPixelFormat
,
//
k24BGRPixelFormat
,
&
theRect
,
//
bounding
rectangle
0
,
//
color
table
NULL
,
//
graphic
device
handle
0
)
;
//
flags
if
(
err
!=
noErr
)
{
ms
_
message
(
"Failed to use RGBA32"
)
;
}
}
if
(
err
!=
noErr
)
{
return
-
1
;
}
if
(
!
LockPixels
(
GetPortPixMap
(
s
->
pgworld
)))
{
v4m
_
close
(
s
)
;
return
-
1
;
}
err
=
SGSetGWorld
(
s
->
seqgrab
,
s
->
pgworld
,
GetMainDevice
())
;
if
(
err
!=
noErr
)
{
ms
_
warning
(
"can't set GWorld"
)
;
return
-
1
;
}
ms
_
warning
(
"SGSetDataProc"
)
;
err
=
SGSetDataProc
(
s
->
seqgrab
,
NewSGDataUPP
(
sgdata
_
callback
)
,
(
long
)
s
)
;
if
(
err
!=
noErr
)
{
ms
_
warning
(
"can't set data proc"
)
;
return
-
1
;
}
ms
_
warning
(
"SGSetChannelUsage"
)
;
err
=
SGSetChannelUsage
(
s
->
sgchanvideo
,
seqGrabRecord
)
;
if
(
err
!=
noErr
)
{
ms
_
warning
(
"can't set channel usage"
)
;
return
-
1
;
}
ms
_
warning
(
"SGPrepare"
)
;
err
=
SGPrepare
(
s
->
seqgrab
,
false
,
true
)
;
if
(
err
!=
noErr
)
{
ms
_
warning
(
"can't prepare sequence grabber component"
)
;
return
-
1
;
}
err
=
SGSetChannelBounds
(
s
->
sgchanvideo
,
&
theRect
)
;
if
(
err
!=
noErr
)
{
v4m
_
close
(
s
)
;
return
-
1
;
}
err
=
SGStartRecord
(
s
->
seqgrab
)
;
if
(
err
!=
noErr
)
{
v4m
_
close
(
s
)
;
return
-
1
;
}
return
0
;
}
static
int
v4m
_
start
(
MSFilter
*
f
,
void
*
arg
)
{
v4mState
*
s
=
(
v4mState
*
)
f
->
data
;
int
err
=
0
;
err
=
sequence
_
grabber
_
start
(
s
)
;
if
(
err
!=
0
)
{
s
->
pix
_
fmt
=
MS
_
YUV420P
;
s
->
vsize
.
width
=
MS
_
VIDEO
_
SIZE
_
CIF
_
W
;
s
->
vsize
.
height
=
MS
_
VIDEO
_
SIZE
_
CIF
_
H
;
return
0
;
}
ms
_
message
(
"v4m video device opened."
)
;
return
0
;
}
static
void
v4m
_
start
_
capture
(
v4mState
*
s
){
if
(
s
->
seqgrab
!=
NULL
){
s
->
run
=
TRUE
;
}
}
static
int
v4m
_
stop
(
MSFilter
*
f
,
void
*
arg
){
v4mState
*
s
=
(
v4mState
*
)
f
->
data
;
if
(
s
->
seqgrab
!=
NULL
){
ms
_
mutex
_
lock
(
&
s
->
mutex
)
;
SGStop
(
s
->
seqgrab
)
;
v4m
_
close
(
s
)
;
flushq
(
&
s
->
rq
,
0
)
;
ms
_
mutex
_
unlock
(
&
s
->
mutex
)
;
}
return
0
;
}
static
void
v4m
_
stop
_
capture
(
v4mState
*
s
){
if
(
s
->
run
){
s
->
run
=
FALSE
;
ms
_
message
(
"v4m capture stopped."
)
;
}
}
static
void
v4m
_
uninit
(
MSFilter
*
f
){
v4mState
*
s
=
(
v4mState
*
)
f
->
data
;
if
(
s
->
seqgrab
!=
NULL
)
v4m
_
stop
(
f
,
NULL
)
;
//
ms
_
free
(
s
->
dev
)
;
flushq
(
&
s
->
rq
,
0
)
;
ms
_
mutex
_
destroy
(
&
s
->
mutex
)
;
freemsg
(
s
->
mire
)
;
ms
_
free
(
s
)
;
}
static
mblk
_
t
*
v4m
_
make
_
mire
(
v4mState
*
s
){
unsigned
char
*
data
;
int
i
,
j
,
line
,
pos
;
int
patternw
=
s
->
vsize
.
width
/
6
;
int
patternh
=
s
->
vsize
.
height
/
6
;
int
red
,
green
=
0
,
blue
=
0
;
if
(
s
->
mire
==
NULL
){
s
->
mire
=
allocb
(
s
->
vsize
.
width
*
s
->
vsize
.
height
*
3
,
0
)
;
s
->
mire
->
b
_
wptr
=
s
->
mire
->
b
_
datap
->
db
_
lim
;
}
data
=
s
->
mire
->
b
_
rptr
;
for
(
i
=
0
;
i
<
s
->
vsize
.
height
;++
i
){
line
=
i
*
s
->
vsize
.
width
*
3
;
if
(
((
i
+
s
->
frame
_
ind
)
/
patternh
)
&
0
x1
)
red
=
255
;
else
red
=
0
;
for
(
j
=
0
;
j
<
s
->
vsize
.
width
;++
j
){
pos
=
line
+
(
j
*
3
)
;
if
(
((
j
+
s
->
frame
_
ind
)
/
patternw
)
&
0
x1
)
blue
=
255
;
else
blue
=
0
;
data
[
pos
]
=
red
;
data
[
pos
+
1
]
=
green
;
data
[
pos
+
2
]
=
blue
;
}
}
s
->
frame
_
ind
++;
return
s
->
mire
;
}
static
mblk
_
t
*
v4m
_
make
_
nowebcam
(
v4mState
*
s
){
if
(
s
->
mire
==
NULL
&&
s
->
frame
_
ind
==
0
){
s
->
mire
=
ms
_
load
_
nowebcam
(
&
s
->
vsize
,
-
1
)
;
}
s
->
frame
_
ind
++;
return
s
->
mire
;
}
static
void
v4m
_
process
(
MSFilter
*
obj
){
v4mState
*
s
=
(
v4mState
*
)
obj
->
data
;
uint32
_
t
timestamp
;
int
cur
_
frame
;
if
(
s
->
frame
_
count
==-
1
){
s
->
start
_
time
=
obj
->
ticker
->
time
;
s
->
frame
_
count
=
0
;
}
ms
_
mutex
_
lock
(
&
s
->
mutex
)
;
if
(
s
->
seqgrab
!=
NULL
)
{
SGIdle
(
s
->
seqgrab
)
;
}
cur
_
frame
=
((
obj
->
ticker
->
time
-
s
->
start
_
time
)
*
s
->
fps
/
1000.0
)
;
if
(
cur
_
frame
>=
s
->
frame
_
count
){
mblk
_
t
*
om
=
NULL
;
/*
keep
the
most
recent
frame
if
several
frames
have
been
captured
*/
if
(
s
->
seqgrab
!=
NULL
){
om
=
getq
(
&
s
->
rq
)
;
}
else
{