Commit ed415ced authored by Simon Morlat's avatar Simon Morlat
Browse files

Merge branch 'master' of git://git.linphone.org/mediastreamer2

parents 5be8e0f0 9499aa10
......@@ -166,6 +166,9 @@ void audio_stream_get_local_rtp_stats(AudioStream *stream, rtp_stats_t *stats);
*****************/
typedef void (*VideoStreamRenderCallback)(void *user_pointer, const MSPicture *local_view, const MSPicture *remote_view);
typedef void (*VideoStreamEventCallback)(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args);
typedef enum _VideoStreamDir{
VideoStreamSendRecv,
......@@ -194,6 +197,8 @@ struct _VideoStream
int corner; /*for selfview*/
VideoStreamRenderCallback rendercb;
void *render_pointer;
VideoStreamEventCallback eventcb;
void *event_pointer;
char *display_name;
unsigned long window_id;
unsigned long preview_window_id;
......@@ -211,6 +216,7 @@ VideoStream *video_stream_new(int locport, bool_t use_ipv6);
void video_stream_set_direction(VideoStream *vs, VideoStreamDir dir);
void video_stream_enable_adaptive_bitrate_control(VideoStream *s, bool_t yesno);
void video_stream_set_render_callback(VideoStream *s, VideoStreamRenderCallback cb, void *user_pointer);
void video_stream_set_event_callback(VideoStream *s, VideoStreamEventCallback cb, void *user_pointer);
void video_stream_set_display_filter_name(VideoStream *s, const char *fname);
int video_stream_start(VideoStream * stream, RtpProfile *profile, const char *remip, int remport, int rem_rtcp_port,
int payload, int jitt_comp, MSWebCam *device);
......
......@@ -58,7 +58,7 @@ typedef int (*MSFilterMethodFunc)(struct _MSFilter *f, void *arg);
* Structure for filter's methods used as a callback to notify events.
* @var MSFilterNotifyFunc
*/
typedef void (*MSFilterNotifyFunc)(void *userdata , unsigned int id, void *arg);
typedef void (*MSFilterNotifyFunc)(void *userdata, struct _MSFilter *f, unsigned int id, void *arg);
struct _MSFilterMethod{
int id;
......@@ -515,7 +515,8 @@ enum _MSFilterInterfaceId{
MSFilterPlayerInterface,
MSFilterRecorderInterface,
MSFilterVideoDisplayInterface,
MSFilterEchoCancellerInterface
MSFilterEchoCancellerInterface,
MSFilterVideoDecoderInterface
};
typedef enum _MSFilterInterfaceId MSFilterInterfaceId;
......
......@@ -87,7 +87,7 @@ typedef enum _MSPlayerState MSPlayerState;
MS_FILTER_METHOD(MSFilterPlayerInterface,5,int)
/** Interface definitions for echo cancellers*/
/** Interface definitions for echo cancellers */
/** sets the echo delay in milliseconds*/
#define MS_ECHO_CANCELLER_SET_DELAY \
......@@ -100,4 +100,9 @@ typedef enum _MSPlayerState MSPlayerState;
#define MS_ECHO_CANCELLER_SET_TAIL_LENGTH \
MS_FILTER_METHOD(MSFilterEchoCancellerInterface,2,int)
/** Interface definitions for video decoders */
#define MS_VIDEO_DECODER_DECODING_ERRORS \
MS_FILTER_EVENT_NO_ARG(MSFilterVideoDecoderInterface,0)
#endif
......@@ -75,7 +75,7 @@ static bool_t read_event(MSEventQueue *q){
evsize=argsize+16;
data=q->rptr+16;
if (f->notify!=NULL)
f->notify(f->notify_ud,id,argsize>0 ? data : NULL);
f->notify(f->notify_ud,f,id,argsize>0 ? data : NULL);
q->rptr+=evsize;
if (q->rptr>=q->endptr){
q->rptr=q->buffer;
......@@ -121,7 +121,7 @@ void ms_filter_notify(MSFilter *f, unsigned int id, void *arg){
if (f->notify!=NULL){
if (ms_global_event_queue==NULL){
/* synchronous notification */
f->notify(f->notify_ud,id,arg);
f->notify(f->notify_ud,f,id,arg);
}else{
write_event(ms_global_event_queue,f,id,arg);
}
......
......@@ -21,11 +21,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/rfc3984.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "ffmpeg-priv.h"
#include "ortp/b64.h"
static uint64_t fpu_last_requested_time=0;
typedef struct _DecData{
mblk_t *yuv_msg;
mblk_t *sps,*pps;
......@@ -130,36 +135,39 @@ static void update_pps(DecData *d, mblk_t *pps){
else d->pps=NULL;
}
static bool_t check_sps_pps_change(DecData *d, mblk_t *sps, mblk_t *pps){
bool_t ret1=FALSE,ret2=FALSE;
static bool_t check_sps_change(DecData *d, mblk_t *sps){
bool_t ret=FALSE;
if (d->sps){
if (sps){
ret1=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
if (ret1) {
update_sps(d,sps);
ms_message("SPS changed !");
update_pps(d,NULL);
}
ret=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
if (ret) {
ms_message("SPS changed ! %i,%i",msgdsize(sps),msgdsize(d->sps));
update_sps(d,sps);
update_pps(d,NULL);
}
}else if (sps) {
} else {
ms_message("Receiving first SPS");
update_sps(d,sps);
}
return ret;
}
static bool_t check_pps_change(DecData *d, mblk_t *pps){
bool_t ret=FALSE;
if (d->pps){
if (pps){
ret2=(msgdsize(pps)!=msgdsize(d->pps)) || (memcmp(d->pps->b_rptr,pps->b_rptr,msgdsize(pps))!=0);
if (ret2) {
ms_message("PPS changed ! %i,%i",msgdsize(pps),msgdsize(d->pps));
update_pps(d,pps);
}
ret=(msgdsize(pps)!=msgdsize(d->pps)) || (memcmp(d->pps->b_rptr,pps->b_rptr,msgdsize(pps))!=0);
if (ret) {
ms_message("PPS changed ! %i,%i",msgdsize(pps),msgdsize(d->pps));
update_pps(d,pps);
}
}else if (pps) {
}else {
ms_message("Receiving first PPS");
update_pps(d,pps);
}
return ret1 || ret2;
return ret;
}
static void enlarge_bitstream(DecData *d, int new_size){
d->bitstream_size=new_size;
d->bitstream=ms_realloc(d->bitstream,d->bitstream_size);
......@@ -184,9 +192,9 @@ static int nalusToFrame(DecData *d, MSQueue *naluq, bool_t *new_sps_pps){
}
nalu_type=(*src) & ((1<<5)-1);
if (nalu_type==7)
*new_sps_pps=check_sps_pps_change(d,im,NULL) || *new_sps_pps;
*new_sps_pps=check_sps_change(d,im) || *new_sps_pps;
if (nalu_type==8)
*new_sps_pps=check_sps_pps_change(d,NULL,im) || *new_sps_pps;
*new_sps_pps=check_pps_change(d,im) || *new_sps_pps;
if (start_picture || nalu_type==7/*SPS*/ || nalu_type==8/*PPS*/ ){
*dst++=0;
start_picture=FALSE;
......@@ -251,6 +259,10 @@ static void dec_process(MSFilter *f){
len=avcodec_decode_video2(&d->av_context,&orig,&got_picture,&pkt);
if (len<=0) {
ms_warning("ms_AVdecoder_process: error %i.",len);
if ((f->ticker->time - fpu_last_requested_time)>5000 || fpu_last_requested_time==0) {
fpu_last_requested_time=f->ticker->time;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
}
break;
}
if (got_picture) {
......
......@@ -170,8 +170,7 @@ MSWebCamDesc ms_android_video_capture_desc={
};
static void video_capture_detect(MSWebCamManager *obj){
// FIXME list available camera through a JNI call
// Currently only creates one camera
// Only creates one camera object whatever the real number of cameras.
ms_message("Detecting Android VIDEO cards");
MSWebCam *cam=ms_web_cam_new(&ms_android_video_capture_desc);
......@@ -233,14 +232,12 @@ static void rotate_plane(int wDest, int hDest, uint8_t* src, uint8_t* dst, int s
if (clockWise) {
// start writing destination buffer from top right
ms_warning("start writing destination buffer from top right");
// ms_warning("start writing destination buffer from top right");
dst += wDest - 1;
incr = 1;
signed_dst_stride = wDest;
} else {
ms_warning("start writing destination buffer from top right");
// start writing destination buffer from bottom left
// ms_warning("start writing destination buffer from top right");
dst += wDest * (hDest - 1);
incr = -1;
signed_dst_stride = -wDest;
......@@ -374,7 +371,7 @@ static mblk_t *copy_frame_to_true_yuv_portrait(jbyte* initial_frame, int rotatio
int uv_w = w/2;
int uv_h = h/2;
int uorvsize = uv_w * uv_h;
// int uorvsize = uv_w * uv_h;
// Copying U
uint8_t* srcu = (uint8_t*) initial_frame + (w * h);
......@@ -398,7 +395,8 @@ extern "C" void Java_org_linphone_core_AndroidCameraRecordImpl_putImage(JNIEnv*
// received buffer is always in landscape orientation
bool portrait = d->vsize.width < d->vsize.height;
ms_warning("PUT IMAGE: bo=%i, inv=%s, filter w=%i/h=%i", (int) jorientation, portrait? "portrait" : "landscape", d->vsize.width, d->vsize.height);
//ms_warning("PUT IMAGE: bo=%i, inv=%s, filter w=%i/h=%i", (int) jorientation,
// portrait? "portrait" : "landscape", d->vsize.width, d->vsize.height);
jboolean isCopied;
jbyte* jinternal_buff = env->GetByteArrayElements(jbadyuvframe, &isCopied);
......
......@@ -25,11 +25,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "rfc2429.h"
extern void ms_ffmpeg_check_init();
static uint64_t fpu_last_requested_time=0;
typedef struct DecState{
AVCodecContext av_context;
AVCodec *av_codec;
......@@ -65,6 +69,7 @@ static void dec_init(MSFilter *f, enum CodecID cid){
if (s->av_codec==NULL){
ms_error("Could not find decoder %i!",s->codec);
}
/*
s->av_context.width=MS_VIDEO_SIZE_QCIF_W;
s->av_context.height=MS_VIDEO_SIZE_QCIF_H;
......@@ -668,6 +673,10 @@ static void dec_process_frame(MSFilter *f, mblk_t *inm){
len=avcodec_decode_video2(&s->av_context,&orig,&got_picture,&pkt);
if (len<=0) {
ms_warning("ms_AVdecoder_process: error %i.",len);
if ((f->ticker->time - fpu_last_requested_time)>5000 || fpu_last_requested_time==0) {
fpu_last_requested_time=f->ticker->time;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
}
break;
}
if (got_picture) {
......@@ -690,6 +699,7 @@ static void dec_process(MSFilter *f){
}
static MSFilterMethod methods[]={
{ MS_FILTER_ADD_FMTP , dec_add_fmtp },
{ 0 , NULL }
......
......@@ -73,6 +73,14 @@ void video_stream_free (VideoStream * stream)
ms_free (stream);
}
static void event_cb(void *ud, MSFilter* f, unsigned int event, void *eventdata){
ms_message("event_cb called %u", event);
VideoStream *st=(VideoStream*)ud;
if (st->eventcb!=NULL){
st->eventcb(st->event_pointer,f,event,eventdata);
}
}
/*this function must be called from the MSTicker thread:
it replaces one filter by another one.
This is a dirty hack that works anyway.
......@@ -96,7 +104,7 @@ void video_stream_change_decoder(VideoStream *stream, int payload){
ms_filter_link (stream->rtprecv, 0, stream->decoder, 0);
ms_filter_link (stream->decoder,0 , stream->output, 0);
ms_filter_preprocess(stream->decoder,stream->ticker);
ms_filter_set_notify_callback(dec, event_cb, stream);
}else{
ms_warning("No decoder found for %s",pt->mime_type);
}
......@@ -223,6 +231,11 @@ void video_stream_set_render_callback (VideoStream *s, VideoStreamRenderCallback
s->render_pointer=user_pointer;
}
void video_stream_set_event_callback (VideoStream *s, VideoStreamEventCallback cb, void *user_pointer){
s->eventcb=cb;
s->event_pointer=user_pointer;
}
void video_stream_set_display_filter_name(VideoStream *s, const char *fname){
if (s->display_name!=NULL){
ms_free(s->display_name);
......@@ -232,7 +245,8 @@ void video_stream_set_display_filter_name(VideoStream *s, const char *fname){
s->display_name=ms_strdup(fname);
}
static void ext_display_cb(void *ud, unsigned int event, void *eventdata){
static void ext_display_cb(void *ud, MSFilter* f, unsigned int event, void *eventdata){
MSExtDisplayOutput *output=(MSExtDisplayOutput*)eventdata;
VideoStream *st=(VideoStream*)ud;
if (st->rendercb!=NULL){
......@@ -373,6 +387,8 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
ms_error("videostream.c: No decoder available for payload %i:%s.",payload,pt->mime_type);
return -1;
}
ms_filter_set_notify_callback(stream->decoder, event_cb, stream);
stream->rtprecv = ms_filter_new (MS_RTP_RECV_ID);
ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,stream->session);
......@@ -383,7 +399,7 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
if (stream->rendercb!=NULL){
stream->output=ms_filter_new(MS_EXT_DISPLAY_ID);
ms_filter_set_notify_callback (stream->output,ext_display_cb,stream);
ms_filter_set_notify_callback(stream->output,ext_display_cb,stream);
}else{
stream->output=ms_filter_new_from_name (stream->display_name);
}
......@@ -472,6 +488,8 @@ void video_stream_send_vfu(VideoStream *stream){
void
video_stream_stop (VideoStream * stream)
{
stream->eventcb = NULL;
stream->event_pointer = NULL;
if (stream->ticker){
if (stream->source)
ms_ticker_detach(stream->ticker,stream->source);
......
##
## Android.mk -Android build script-
##
##
## Copyright (C) 2010 Belledonne Communications, Grenoble, France
##
## 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 Library 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.
##
LOCAL_PATH:= $(call my-dir)/
include $(CLEAR_VARS)
LOCAL_MODULE := libring
LOCAL_SRC_FILES = \
ring_jni.c
LOCAL_CFLAGS += \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \
$(LOCAL_PATH)/../../oRTP/include \
$(LOCAL_PATH)/../include
LOCAL_LDLIBS += -llog -ldl
LOCAL_STATIC_LIBRARIES := \
libmediastreamer2 \
libortp \
libgsm \
ifeq ($(LINPHONE_VIDEO),1)
LOCAL_STATIC_LIBRARIES += \
libavcodec \
libswscale \
libavcore \
libavutil \
libmsx264 \
libx264
endif
LOCAL_STATIC_LIBRARIES += libspeex
LOCAL_MODULE_CLASS = SHARED_LIBRARIES
include $(BUILD_SHARED_LIBRARY)
/*
Ring.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.
*/
package org.mediastreamer2.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.linphone.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class Ring extends Activity {
Thread mWorkerThread = new Thread("Worker Thread");
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ring);
try {
try {
System.loadLibrary("ring");
} catch (UnsatisfiedLinkError e) {
Log.e("mediastreamer2", "cannot load libring.so, did you compile SDK with ndk-build RING=yes ", e);
}
final File lFileToPlay = new File("/data/data/"+this.getPackageName()+"/files/oldphone_mono.wav");
if (!lFileToPlay.exists()) {
FileOutputStream lOutputStream = openFileOutput ("oldphone_mono.wav", 0);
InputStream lInputStream = getResources().openRawResource(R.raw.oldphone_mono);
int readByte;
while (( readByte = lInputStream.read())!=-1) {
lOutputStream.write(readByte);
}
lOutputStream.flush();
lOutputStream.close();
lInputStream.close();
}
init();
mWorkerThread = new Thread(new Runnable() {
public void run() {
play(lFileToPlay.getAbsolutePath());
echo(44100);
}
},"Worker Thread");
mWorkerThread.start();
} catch (Exception e) {
Log.e("ring","error",e);
}
}
native void play(String file);
native void echo(int freq);
native void init();
}
\ No newline at end of file
/*
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 HAVE_CONFIG_H
#include "mediastreamer-config.h"
#endif
#include "mediastreamer2/mediastream.h"
#include <jni.h>
extern void ms_andsnd_register_card(JavaVM *jvm);
void Java_org_mediastreamer2_test_Ring_init(JNIEnv* env,jobject this){
ortp_init();
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
ms_init();
}
void Java_org_mediastreamer2_test_Ring_play(JNIEnv* env,jobject this,jstring jfile){
RingStream *r;
const char *file;
MSSndCard *sc;
const char * card_id=NULL;
file = (*env)->GetStringUTFChars(env, jfile, NULL);
sc=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),card_id);
r=ring_start(file,2000,sc);
ms_sleep(2);
ring_stop(r);
(*env)->ReleaseStringUTFChars(env, jfile, file);
return ;
}
void Java_org_mediastreamer2_test_Ring_echo(JNIEnv* env,jobject this,jint freq){
MSFilter *reader,*writer;
MSFilter *resampler=0;
MSSndCard *card_capture;
MSSndCard *card_playback;
MSTicker *ticker;
int read_rate = freq;
int write_rate = freq;
const char * card_id="ANDROID SND: Android Sound card";
card_capture = ms_snd_card_manager_get_card(ms_snd_card_manager_get(),card_id);
card_playback = ms_snd_card_manager_get_card(ms_snd_card_manager_get(),card_id);
if (card_playback==NULL || card_capture==NULL){
ms_error("No card.");
return ;
}
reader=ms_snd_card_create_reader(card_capture);
writer=ms_snd_card_create_writer(card_playback);
if (read_rate !=write_rate) {
resampler = ms_filter_new(MS_RESAMPLE_ID);
ms_filter_call_method(resampler,MS_FILTER_SET_SAMPLE_RATE,&read_rate);
ms_filter_call_method(resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&write_rate);
}
ms_filter_call_method (reader, MS_FILTER_SET_SAMPLE_RATE,
&read_rate);
ms_filter_call_method (writer, MS_FILTER_SET_SAMPLE_RATE,
&write_rate);
ticker=ms_ticker_new();
if (resampler) {
ms_filter_link(reader,0,resampler,0);
ms_filter_link(resampler,0,writer,0);
} else {
ms_filter_link(reader,0,writer,0);
}
ms_ticker_attach(ticker,reader);
while(1)
ms_sleep(1);
ms_ticker_detach(ticker,reader);
ms_ticker_destroy(ticker);
if (resampler) {
ms_filter_unlink(reader,0,resampler,0);
ms_filter_unlink(resampler,0,writer,0);
ms_filter_destroy(resampler);
} else {
ms_filter_unlink(reader,0,writer,0);
}
ms_filter_destroy(reader);
ms_filter_destroy(writer);
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved)
{
#ifdef ANDROID
ms_set_jvm(ajvm);
#endif /*ANDROID*/
return JNI_VERSION_1_2;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment