Commit 0eb18f17 authored by jehan's avatar jehan

capture/playback for IOS

parent 1706dc1f
......@@ -18,6 +18,7 @@ extern MSFilterDesc ms_channel_adapter_desc;
extern MSFilterDesc ms_audio_mixer_desc;
extern MSFilterDesc ms_itc_source_desc;
extern MSFilterDesc ms_itc_sink_desc;
extern MSFilterDesc ms_tone_detector_desc;
extern MSFilterDesc ms_speex_dec_desc;
extern MSFilterDesc ms_speex_enc_desc;
extern MSFilterDesc ms_speex_ec_desc;
......@@ -28,6 +29,21 @@ extern MSFilterDesc ms_file_rec_desc;
extern MSFilterDesc ms_resample_desc;
extern MSFilterDesc au_read_desc;
extern MSFilterDesc au_write_desc;
extern MSFilterDesc ms_mpeg4_dec_desc;
extern MSFilterDesc ms_h263_dec_desc;
extern MSFilterDesc ms_h263_old_dec_desc;
extern MSFilterDesc ms_snow_dec_desc;
extern MSFilterDesc ms_jpeg_dec_desc;
extern MSFilterDesc ms_mjpeg_dec_desc;
extern MSFilterDesc ms_pix_conv_desc;
extern MSFilterDesc ms_size_conv_desc;
extern MSFilterDesc ms_static_image_desc;
extern MSFilterDesc ms_h264_dec_desc;
extern MSFilterDesc ms_jpeg_writer_desc;
extern MSFilterDesc ms_mire_desc;
extern MSFilterDesc ms_ext_display_desc;
extern MSFilterDesc ms_iosdisplay_desc;
extern MSFilterDesc ms_v4ios_desc;
MSFilterDesc * ms_filter_descs[]={
&ms_alaw_dec_desc,
&ms_alaw_enc_desc,
......@@ -47,6 +63,7 @@ MSFilterDesc * ms_filter_descs[]={
&ms_audio_mixer_desc,
&ms_itc_source_desc,
&ms_itc_sink_desc,
&ms_tone_detector_desc,
&ms_speex_dec_desc,
&ms_speex_enc_desc,
&ms_speex_ec_desc,
......@@ -57,6 +74,21 @@ MSFilterDesc * ms_filter_descs[]={
&ms_resample_desc,
&au_read_desc,
&au_write_desc,
&ms_mpeg4_dec_desc,
&ms_h263_dec_desc,
&ms_h263_old_dec_desc,
&ms_snow_dec_desc,
&ms_jpeg_dec_desc,
&ms_mjpeg_dec_desc,
&ms_pix_conv_desc,
&ms_size_conv_desc,
&ms_static_image_desc,
&ms_h264_dec_desc,
&ms_jpeg_writer_desc,
&ms_mire_desc,
&ms_ext_display_desc,
&ms_iosdisplay_desc,
&ms_v4ios_desc,
NULL
};
......@@ -107,7 +107,9 @@ typedef enum MSFilterId{
MS_ANDROID_DISPLAY_ID,
MS_ANDROID_VIDEO_READ_ID,
MS_ANDROID_VIDEO_WRITE_ID,
MS_TONE_DETECTOR_ID
MS_TONE_DETECTOR_ID,
MY_FILTER_ID,
MS_IOS_DISPLAY_ID
} MSFilterId;
......
......@@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <ortp/ortp.h>
#include <time.h>
#if defined(__APPLE__)
#include "TargetConditionals.h"
#endif
#define ms_malloc ortp_malloc
#define ms_malloc0 ortp_malloc0
......
/*
filter-template.m
Copyright (C) 2011 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.
*/
#include "msfilter.h"
/*filter common method*/
struct my_filter_struct {
char toto;
};
static void filter_init(MSFilter *f){
f->data = ms_new0(struct my_filter_struct,1);
}
static void filter_preprocess(MSFilter *f){
}
static void filter_process(MSFilter *f){
}
static void filter_postprocess(MSFilter *f){
}
static void filter_unit(MSFilter *f){
}
/*filter specific method*/
static int filter_set_sample_rate(MSFilter *f, void *arg) {
return 0;
}
static int filter_get_sample_rate(MSFilter *f, void *arg) {
return 0;
}
static MSFilterMethod filter_methods[]={
{ MS_FILTER_SET_SAMPLE_RATE , filter_set_sample_rate },
{ MS_FILTER_GET_SAMPLE_RATE , filter_get_sample_rate },
{ 0, NULL}
};
MSFilterDesc my_filter_desc={
.id=MY_FILTER_ID, /* from Allfilters.h*/
.name="MyFilter",
.text="An empty filter.",
.category=MS_FILTER_OTHER,
.ninputs=1, /*number of inputs*/
.noutputs=0, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_unit,
.methods=filter_methods
};
\ No newline at end of file
This diff is collapsed.
/*
iosdisplay.m
Copyright (C) 2011 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.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface IOSDisplay : NSObject {
UIImageView* imageView;
}
//@property (nonatomic, retain) UIImageView* imageView;
@end
/*
iosdisplay.m
Copyright (C) 2011 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.
*/
#if defined(HAVE_CONFIG_H)
#include "mediastreamer-config.h"
#endif
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "mediastreamer2/msv4l.h"
#include "mediastreamer2/mswebcam.h"
#include "nowebcam.h"
#import <AVFoundation/AVFoundation.h>
#import "iosdisplay.h"
#include "msfilter.h"
#include "scaler.h"
@implementation IOSDisplay
-(void) updateImage:(UIImage*) image {
[imageView setImage:image];
[image release];
}
static void iosdisplay_init(MSFilter *f){
f->data = [[IOSDisplay alloc] init] ;
}
static void iosdisplay_process(MSFilter *f){
IOSDisplay* thiz=(IOSDisplay*)f->data;
MSPicture yuvbuf;
mblk_t *m=ms_queue_peek_last(f->inputs[0]);
if (m && ms_yuv_buf_init_from_mblk(&yuvbuf,m)==0){
CVPixelBufferRef imageBuffer = 0;
// create pixel buffer
int ret = CVPixelBufferCreate(kCFAllocatorDefault
, yuvbuf.w
, yuvbuf.h
, kCVPixelFormatType_32BGRA
, nil
, &imageBuffer);
if (ret != kCVReturnSuccess) {
ms_error("CVPixelBufferCreateWithBytes() failed : %d", ret);
goto end;
}
CVPixelBufferLockBaseAddress(imageBuffer, 0);
uint32_t* buff = CVPixelBufferGetBaseAddress(imageBuffer);
img_ycrcb420p_to_bgra(yuvbuf.planes,yuvbuf.w,yuvbuf.h,buff);
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// Create a device-dependent RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// Get the number of bytes per row for the pixel buffer
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(baseAddress
, yuvbuf.w
, yuvbuf.h
,8
,yuvbuf.w*4
,colorSpace
, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// Free up the context and color space
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// Create an image object from the Quartz image
UIImage *image = [[UIImage alloc ]initWithCGImage:quartzImage] ;
[thiz performSelectorOnMainThread:@selector(updateImage:) withObject:image waitUntilDone:NO];
// Release the Quartz image
CGImageRelease(quartzImage);
CVPixelBufferRelease(imageBuffer);
}
end:
ms_queue_flush(f->inputs[0]);
ms_queue_flush(f->inputs[1]);
}
static void iosdisplay_unit(MSFilter *f){
[(IOSDisplay*)(f->data) release];
}
/*filter specific method*/
static int iosdisplay_set_native_window(MSFilter *f, void *arg) {
IOSDisplay* thiz=(IOSDisplay*)f->data;
thiz->imageView = (UIImageView*)arg;
return 0;
}
static int iosdisplay_get_native_window(MSFilter *f, void *arg) {
IOSDisplay* thiz=(IOSDisplay*)f->data;
arg = thiz->imageView;
return 0;
}
static MSFilterMethod iosdisplay_methods[]={
{ MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID , iosdisplay_set_native_window },
{ MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID , iosdisplay_get_native_window },
{ 0, NULL}
};
@end
MSFilterDesc ms_iosdisplay_desc={
.id=MS_IOS_DISPLAY_ID, /* from Allfilters.h*/
.name="IOSDisplay",
.text="IOS Display filter.",
.category=MS_FILTER_OTHER,
.ninputs=2, /*number of inputs*/
.noutputs=0, /*number of outputs*/
.init=iosdisplay_init,
.preprocess=NULL,
.process=iosdisplay_process,
.postprocess=NULL,
.uninit=iosdisplay_unit,
.methods=iosdisplay_methods
};
MS_FILTER_DESC_EXPORT(ms_iosdisplay_desc)
\ No newline at end of file
......@@ -50,10 +50,7 @@ extern void libmsandroiddisplay_init(void);
#include <dlfcn.h>
#endif
#if defined(__APPLE__) && !defined(__GNUC__)
#import <Cocoa/Cocoa.h>
#include <Foundation/Foundation.h>
#endif
#ifdef ANDROID
#include <android/log.h>
......@@ -490,7 +487,7 @@ static MSSndCardDesc * ms_snd_card_descs[]={
&pulse_card_desc,
#endif
#ifdef __MACIOUNIT_ENABLED__
#ifdef __IOSIOUNIT_ENABLED__
&au_card_desc,
#endif
#ifdef ANDROID
......@@ -533,6 +530,9 @@ extern MSWebCamDesc mire_desc;
extern MSWebCamDesc ms_android_video_capture_desc;
#endif
#ifdef TARGET_OS_IPHONE
extern MSWebCamDesc ms_v4ios_cam_desc;
#endif
static MSWebCamDesc * ms_web_cam_descs[]={
#ifdef HAVE_LINUX_VIDEODEV2_H
&v4l2_card_desc,
......@@ -552,6 +552,9 @@ static MSWebCamDesc * ms_web_cam_descs[]={
#if defined (ANDROID)
&ms_android_video_capture_desc,
#endif
#ifdef TARGET_OS_IPHONE
&ms_v4ios_cam_desc,
#endif
#if !defined(NO_FFMPEG)
&mire_desc,
&static_image_desc,
......
......@@ -18,10 +18,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/msvideo.h"
#ifdef __ARM_NEON__
#include <arm_neon.h>
#define ARM 1
#endif
void ms_line_rgb2rgb565_4(const int16_t *r, const int16_t *g, const int16_t *b, uint16_t *dst, int width);
void ms_line_rgb2rgb565_8(const int16_t *r, const int16_t *g, const int16_t *b, uint16_t *dst, int width);
......@@ -43,6 +42,7 @@ typedef struct AndroidScalerCtx{
int dst_w_padded;
}AndroidScalerCtx;
#define ROUND_UP(i,p) ((i+(p-1)) & ~(p-1))
#define PAD 16
......@@ -68,7 +68,7 @@ static void init_premults(){
static int32_t yuvmax[4]={255<<13,255<<13,255<<13,255<<13};
#ifndef ARM
#if !defined (__ARM_NEON__)
static inline void yuv2rgb_4x2(const uint8_t *y1, const uint8_t *y2, const uint8_t *u, const uint8_t *v, int16_t *r1, int16_t *g1, int16_t *b1, int16_t *r2, int16_t *g2, int16_t *b2){
int32_t py1[4];
......@@ -119,8 +119,9 @@ static inline void yuv2rgb_4x2(const uint8_t *y1, const uint8_t *y2, const uint8
rub=vsetq_lane_s32(tmp,rub,2*i); \
rub=vsetq_lane_s32(tmp,rub,2*i+1); \
}
#endif
#if defined (__ARM_NEON__)
static inline void yuv2rgb_4x2(const uint8_t *y1, const uint8_t *y2, const uint8_t *u, const uint8_t *v, int16_t *r1, int16_t *g1, int16_t *b1, int16_t *r2, int16_t *g2, int16_t *b2){
int32x4_t ry1;
int32x4_t ry2;
......@@ -170,6 +171,47 @@ static inline void yuv2rgb_4x2(const uint8_t *y1, const uint8_t *y2, const uint8
#endif
void img_ycrcb420p_to_bgra(uint8_t* src[],unsigned short w,unsigned short h, uint32_t dest[]) {
unsigned int offset_y=0;
unsigned int offset_dest=0;
unsigned int offset_cbcr=0;
if (premult_initd == FALSE) {
init_premults();
}
for (int row=0;row<h;row+=2) {
offset_y=row*w;
offset_cbcr=offset_y>>2;
int col_crcb=0;
for (int col_y=0;col_y<w;col_y+=4) {
int16_t r1[4], g1[4], b1[4], r2[4], g2[4], b2[4];
yuv2rgb_4x2(src[0]+offset_y+col_y
,src[0]+offset_y+w+col_y
,(src[1]+offset_cbcr+col_crcb)
,(src[2]+offset_cbcr+col_crcb)
,r1
,g1
,b1
,r2
,g2
,b2);
for (int i =0;i<4;i++) {
*(uint8_t*)(dest+offset_dest+i) = b1[i];
*((uint8_t*)(dest+offset_dest+i)+1) = g1[i];
*((uint8_t*)(dest+offset_dest+i)+2) = r1[i];
*((uint8_t*)(dest+offset_dest+i)+3) = 255;
*(uint8_t*)(dest+w+offset_dest+i) = b2[i];
*((uint8_t*)(dest+w+offset_dest+i)+1) = g2[i];
*((uint8_t*)(dest+w+offset_dest+i)+2) = r2[i];
*((uint8_t*)(dest+w+offset_dest+i)+3) = 255;
}
col_crcb+=2;
offset_dest=offset_y+col_y;
}
}
}
static inline void line_yuv2rgb_2(const uint8_t *src_lines[], int src_strides[], int16_t *dst_lines[], int src_w, int dst_stride ){
int i;
int16_t *line2[3]={dst_lines[0]+dst_stride,dst_lines[1]+dst_stride,dst_lines[2]+dst_stride};
......@@ -202,7 +244,7 @@ static inline void line_yuv2rgb_2(const uint8_t *src_lines[], int src_strides[]
/*horizontal scaling of a single line (with 3 color planes)*/
static inline void line_horizontal_scale(AndroidScalerCtx * ctx, int16_t *src_lines[], int16_t *dst_lines[]){
#ifndef ARM
#ifndef __ARM_NEON__
int dst_w=ctx->dst_size.width;
int x=0;
int i,pos;
......@@ -258,7 +300,7 @@ static void img_yuv2rgb_hscale(AndroidScalerCtx * ctx, uint8_t *src[], int src_s
}
}
#ifndef ARM
#ifndef __ARM_NEON__
void ms_line_rgb2rgb565(const int16_t *r, const int16_t *g, const int16_t *b, uint16_t *dst, int width){
int i;
......@@ -287,7 +329,7 @@ static void img_yuv2rgb565_scale(AndroidScalerCtx *ctx, uint8_t *src[], int src_
p_src[0]=ctx->hscaled_img[0]+offset;
p_src[1]=ctx->hscaled_img[1]+offset;
p_src[2]=ctx->hscaled_img[2]+offset;
#ifndef ARM
#ifndef __ARM_NEON__
ms_line_rgb2rgb565(p_src[0],p_src[1],p_src[2],(uint16_t*)p_dst,ctx->dst_size.width);
#else
ms_line_rgb2rgb565_8(p_src[0],p_src[1],p_src[2],(uint16_t*)p_dst,ctx->dst_w_padded);
......@@ -363,3 +405,4 @@ MSScalerDesc ms_android_scaler={
android_scaler_context_free
};
/*
scaler.h mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006-2011 Belledonne Communications SARL
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 scaler_h
#define scaler_h
void img_ycrcb420p_to_bgra(uint8_t* src[],unsigned short w,unsigned short h, uint32_t dest[]) ;
#endif
......@@ -200,6 +200,8 @@ static void choose_display_name(VideoStream *stream){
stream->display_name=ms_strdup("MSAndroidDisplay");
#elif defined (HAVE_X11_EXTENSIONS_XV_H)
stream->display_name=ms_strdup("MSX11Video");
#elif defined (TARGET_OS_IPHONE)
stream->display_name=ms_strdup("IOSDisplay");
#else
stream->display_name=ms_strdup("MSVideoOut");
#endif
......
......@@ -44,7 +44,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef __APPLE__
#include <CoreFoundation/CFRunLoop.h>
#endif
#ifdef TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
extern void ms_set_video_stream(VideoStream* video);
#endif
static int cond=1;
static const char * capture_card=NULL;
......@@ -326,7 +329,9 @@ static void run_media_streams(int localport, const char *remote_ip, int remotepo
PayloadType *pt;
RtpProfile *profile=rtp_profile_clone_full(&av_profile);
OrtpEvQueue *q=ortp_ev_queue_new();
#ifdef TARGET_OS_IPHONE
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#endif
ms_init();
signal(SIGINT,stop_handler);
pt=rtp_profile_get_payload(profile,payload);
......@@ -389,7 +394,12 @@ static void run_media_streams(int localport, const char *remote_ip, int remotepo
video=video_stream_new(localport, ms_is_ipv6(remote_ip));
video_stream_set_sent_video_size(video,vs);
video_stream_use_preview_video_window(video,two_windows);
#ifdef TARGET_OS_IPHONE
NSBundle* myBundle = [NSBundle mainBundle];
const char* nowebcam = [[myBundle pathForResource:@"nowebcamCIF"ofType:@"jpg"] cStringUsingEncoding:[NSString defaultCStringEncoding]];
ms_static_image_set_default_image(nowebcam);
#endif
if (camera)
cam=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),camera);
if (cam==NULL)
......@@ -444,9 +454,13 @@ static void run_media_streams(int localport, const char *remote_ip, int remotepo
}else{ /* no interactive stuff - continuous debug output */
rtp_session_register_event_queue(session,q);
#ifdef __APPLE__
#ifdef TARGET_OS_MACOSX
CFRunLoopRun();
#else
#elif TARGET_OS_IPHONE
ms_set_video_stream(video);
int retVal = UIApplicationMain(0, nil, nil, nil);
[pool release];
#else
while(cond)
{
int n;
......
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