Commit 9f84d217 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

MacOSX/Framework: Add VLCStreamSession, VLCStreamOutput to allow streaming/exporting.

parent 4e1a0224
......@@ -24,6 +24,7 @@
#import "VLCLibrary.h"
#import "VLCMediaListAspect.h"
#import "VLCStreamOutput.h"
/**
* Bridges functionality between libvlc and VLCMediaList implementation.
......@@ -83,6 +84,8 @@ extern void __catch_exception( void * e, const char * function, const char * fil
*/
- (id)initWithLibVLCMediaDescriptor:(void *)md;
+ (id)mediaWithMedia:(VLCMedia *)media andLibVLCOptions:(NSDictionary *)options;
/**
* Returns the receiver's internal media descriptor pointer.
* \return The receiver's internal media descriptor pointer.
......@@ -100,6 +103,8 @@ extern void __catch_exception( void * e, const char * function, const char * fil
* \param value
*/
- (void)setLength:(VLCTime *)value;
@end
/**
......@@ -171,3 +176,7 @@ extern void __catch_exception( void * e, const char * function, const char * fil
*/
- (id)initWithLibrary:(VLCLibrary *)library;
@end
@interface VLCStreamOutput (LibVLCBridge)
- (NSString *)representedLibVLCOptions;
@end
......@@ -35,6 +35,8 @@
#import <VLCKit/VLCTime.h>
#import <VLCKit/VLCVideoView.h>
#import <VLCKit/VLCVideoLayer.h>
#import <VLCKit/VLCStreamSession.h>
#import <VLCKit/VLCStreamOutput.h>
@class VLCMedia;
@class VLCMediaLibrary;
......
//
// VLCStreamOutput.h
// VLCKit
//
// Created by Pierre d'Herbemont on 1/12/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
extern NSString * VLCDefaultStreamOutputRTSP;
extern NSString * VLCDefaultStreamOutputRTP;
extern NSString * VLCDefaultStreamOutputRTP;
@interface VLCStreamOutput : NSObject {
NSMutableDictionary * options;
}
- (id)initWithOptionDictionary:(NSDictionary *)dictionary;
+ (id)streamOutputWithOptionDictionary:(NSDictionary *)dictionary;
+ (id)rtpBroadcastStreamOutputWithSAPAnnounce:(NSString *)announceName;
+ (id)rtpBroadcastStreamOutput;
+ (id)ipodStreamOutputWithFilePath:(NSString *)filePath;
@end
//
// VLCStreamSession.h
// VLCKit
//
// Created by Pierre d'Herbemont on 1/12/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <VLCKit/VLCStreamOutput.h>
#import <VLCKit/VLCMediaPlayer.h>
#import <VLCKit/VLCMedia.h>
@interface VLCStreamSession : VLCMediaPlayer {
VLCStreamOutput * streamOutput;
VLCMedia * originalMedia;
}
+ (id)streamSession;
@property (retain) VLCMedia * media;
@property (retain) VLCStreamOutput * streamOutput;
@property (readonly) BOOL isComplete;
- (void)startStreaming;
@end
......@@ -78,7 +78,8 @@ static void * DestroySharedLibraryAtExit( void )
const char * lib_vlc_params[] = {
"-I", "dummy", "--vout=opengllayer",
"--no-video-title-show"
"--no-video-title-show", "--no-sout-keep", "-vvv", "--encoder=ffmpeg"
//, "--control=motion", "--motion-use-rotate", "--video-filter=rotate"
};
instance = (void *)libvlc_new( sizeof(lib_vlc_params)/sizeof(lib_vlc_params[0]), lib_vlc_params, &ex );
......
......@@ -350,6 +350,19 @@ static void HandleMediaSubItemAdded(const libvlc_event_t * event, void * self)
{
return p_md;
}
+ (id)mediaWithMedia:(VLCMedia *)media andLibVLCOptions:(NSDictionary *)options
{
libvlc_media_descriptor_t * p_md;
p_md = libvlc_media_descriptor_duplicate( [media libVLCMediaDescriptor] );
for( NSString * key in [options allKeys] )
{
NSLog(@"Adding %@", [NSString stringWithFormat:@"--%@ %@", key, [options objectForKey:key]]);
libvlc_media_descriptor_add_option(p_md, [[NSString stringWithFormat:@"%@=#%@", key, [options objectForKey:key]] UTF8String], NULL);
}
return [VLCMedia mediaWithLibVLCMediaDescriptor:p_md];
}
@end
/******************************************************************************
......
//
// VLCStreamOutput.m
// VLCKit
//
// Created by Pierre d'Herbemont on 1/12/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "VLCStreamOutput.h"
#import "VLCLibVLCBridging.h"
@implementation VLCStreamOutput
- (id)initWithOptionDictionary:(NSDictionary *)dictionary
{
if( self = [super init] )
{
options = [NSMutableDictionary dictionaryWithDictionary:dictionary];
}
return self;
}
- (NSString *)description
{
return [self representedLibVLCOptions];
}
+ (id)streamOutputWithOptionDictionary:(NSDictionary *)dictionary
{
return [[[self alloc] initWithOptionDictionary:dictionary] autorelease];
}
+ (id)rtpBroadcastStreamOutputWithSAPAnnounce:(NSString *)announceName
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"ts", @"muxer",
@"file", @"access",
@"sap", @"sdp",
[announceName copy], @"name",
@"239.255.1.1", @"destination", nil
], @"rtpOptions",
nil
]
];
}
+ (id)rtpBroadcastStreamOutput
{
return [self rtpBroadcastStreamOutputWithSAPAnnounce:@"Helloworld!"];
}
+ (id)ipodStreamOutputWithFilePath:(NSString *)filePath
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"x264", @"videoCodec",
@"768", @"videoBitrate",
@"mp4a", @"audioCodec",
@"128", @"audioBitrate",
@"2", @"channels",
@"320", @"width",
@"240", @"canvasHeight",
@"Yes", @"audio-sync",
nil
], @"transcodingOptions",
[NSDictionary dictionaryWithObjectsAndKeys:
@"mp4", @"muxer",
@"file", @"access",
[filePath copy], @"destination", nil
], @"outputOptions",
nil
]
];
}
@end
@implementation VLCStreamOutput (LibVLCBridge)
- (NSString *)representedLibVLCOptions
{
NSString * representedOptions;
NSMutableArray * subOptions = [NSMutableArray array];
NSMutableArray * optionsAsArray = [NSMutableArray array];
NSDictionary * transcodingOptions = [options objectForKey:@"transcodingOptions"];
if( transcodingOptions )
{
NSString * videoCodec = [transcodingOptions objectForKey:@"videoCodec"];
NSString * audioCodec = [transcodingOptions objectForKey:@"audioCodec"];
NSString * videoBitrate = [transcodingOptions objectForKey:@"videoBitrate"];
NSString * audioBitrate = [transcodingOptions objectForKey:@"audioBitrate"];
NSString * channels = [transcodingOptions objectForKey:@"channels"];
NSString * height = [transcodingOptions objectForKey:@"height"];
NSString * canvasHeight = [transcodingOptions objectForKey:@"canvasHeight"];
NSString * width = [transcodingOptions objectForKey:@"width"];
NSString * audioSync = [transcodingOptions objectForKey:@"audioSync"];
if( videoCodec ) [subOptions addObject:[NSString stringWithFormat:@"vcodec=%@", videoCodec]];
if( videoBitrate ) [subOptions addObject:[NSString stringWithFormat:@"vb=%@", videoBitrate]];
if( width ) [subOptions addObject:[NSString stringWithFormat:@"width=%@", width]];
if( height ) [subOptions addObject:[NSString stringWithFormat:@"height=%@", height]];
if( canvasHeight ) [subOptions addObject:[NSString stringWithFormat:@"canvas-height=%@", canvasHeight]];
if( audioCodec ) [subOptions addObject:[NSString stringWithFormat:@"acodec=%@", audioCodec]];
if( audioBitrate ) [subOptions addObject:[NSString stringWithFormat:@"ab=%@", audioBitrate]];
if( channels ) [subOptions addObject:[NSString stringWithFormat:@"channels=%@", channels]];
if( audioSync ) [subOptions addObject:[NSString stringWithFormat:@"audioSync", width]];
[optionsAsArray addObject: [NSString stringWithFormat:@"transcode{%@}", [subOptions componentsJoinedByString:@","]]];
[subOptions removeAllObjects];
}
NSDictionary * outputOptions = [options objectForKey:@"outputOptions"];
if( outputOptions )
{
NSString * muxer = [outputOptions objectForKey:@"muxer"];
NSString * destination = [outputOptions objectForKey:@"destination"];
NSString * url = [outputOptions objectForKey:@"url"];
NSString * access = [outputOptions objectForKey:@"access"];
if( muxer ) [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", muxer]];
if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=\"%@\"", [destination stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]];
if( url ) [subOptions addObject:[NSString stringWithFormat:@"url=\"%@\"", [url stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]];
if( access ) [subOptions addObject:[NSString stringWithFormat:@"access=%@", access]];
[optionsAsArray addObject:[NSString stringWithFormat:@"std{%@}", [subOptions componentsJoinedByString:@","]]];
[subOptions removeAllObjects];
}
NSDictionary * rtpOptions = [options objectForKey:@"rtpOptions"];
if( rtpOptions )
{
NSString * muxer = [rtpOptions objectForKey:@"muxer"];
NSString * destination = [rtpOptions objectForKey:@"destination"];
NSString * sdp = [rtpOptions objectForKey:@"sdp"];
NSString * name = [rtpOptions objectForKey:@"name"];
if( muxer ) [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", muxer]];
if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=%@", destination]];
if( sdp ) [subOptions addObject:[NSString stringWithFormat:@"sdp=%@", sdp]];
if( name ) [subOptions addObject:[NSString stringWithFormat:@"name=\"%@\"", name]];
[optionsAsArray addObject:[NSString stringWithFormat:@"rtp{%@}", [subOptions componentsJoinedByString:@","]]];
[subOptions removeAllObjects];
}
representedOptions = [optionsAsArray componentsJoinedByString:@":"];
return representedOptions;
}
@end
//
// VLCStreamSession.m
// VLCKit
//
// Created by Pierre d'Herbemont on 1/12/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "VLCStreamSession.h"
#import "VLCLibVLCBridging.h"
@implementation VLCStreamSession
@synthesize media=originalMedia;
@synthesize streamOutput;
+ (id)streamSession
{
return [[[self alloc] init] autorelease];
}
- (void)startStreaming;
{
[self play];
}
- (void)play;
{
NSString * libvlcArgs;
if( self.drawable )
{
libvlcArgs = [NSString stringWithFormat:@"duplicate{dst=display,dst=\"%@\"}",[streamOutput representedLibVLCOptions]];
}
else
{
libvlcArgs = [streamOutput representedLibVLCOptions];
}
[super setMedia: [VLCMedia mediaWithMedia:originalMedia andLibVLCOptions:
[NSDictionary dictionaryWithObject: libvlcArgs
forKey: @"sout"]]];
[super play];
}
+ (NSSet *)keyPathsForValuesAffectingDescription
{
return [NSSet setWithObjects:@"isCompleted", @"state", nil];
}
- (NSString *)description
{
if([self isComplete])
return @"Done.";
else if([self state] == VLCMediaPlayerStateError)
return @"Error while Converting. Open Console.app to diagnose.";
else
return @"Converting...";
}
+ (NSSet *)keyPathsForValuesAffectingIsComplete
{
return [NSSet setWithObjects:@"playing", @"state", @"position", nil];
}
- (BOOL)isComplete
{
return ([self position] == 1.0 || [self state] == VLCMediaPlayerStateEnded || ([self state] == VLCMediaPlayerStateStopped && self.media));
}
@end
......@@ -49,6 +49,10 @@
/* Begin PBXBuildFile section */
6303C43A0CF45CAE0000ECC8 /* VLCMediaListAspect.m in Sources */ = {isa = PBXBuildFile; fileRef = 6303C4390CF45CAE0000ECC8 /* VLCMediaListAspect.m */; };
6303C43C0CF45CC30000ECC8 /* VLCMediaListAspect.h in Headers */ = {isa = PBXBuildFile; fileRef = 6303C43B0CF45CC30000ECC8 /* VLCMediaListAspect.h */; settings = {ATTRIBUTES = (Public, ); }; };
632A0E850D3835C400AFC99B /* VLCStreamSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 632A0E830D3835C400AFC99B /* VLCStreamSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
632A0E860D3835C400AFC99B /* VLCStreamSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 632A0E840D3835C400AFC99B /* VLCStreamSession.m */; };
632A0EC30D38392E00AFC99B /* VLCStreamOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */; settings = {ATTRIBUTES = (Public, ); }; };
632A0EC40D38392E00AFC99B /* VLCStreamOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */; };
6341FCAF0D2C0929002A97B7 /* VLCVideoLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6341FCAE0D2C0929002A97B7 /* VLCVideoLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
6341FCB10D2C0936002A97B7 /* VLCVideoLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6341FCB00D2C0936002A97B7 /* VLCVideoLayer.m */; };
637CFB940D2D280900A041B6 /* VLCLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 637CFB930D2D280800A041B6 /* VLCLibrary.h */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -118,6 +122,10 @@
63030CC70CCA652C0088ECD1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; };
6303C4390CF45CAE0000ECC8 /* VLCMediaListAspect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCMediaListAspect.m; sourceTree = "<group>"; };
6303C43B0CF45CC30000ECC8 /* VLCMediaListAspect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMediaListAspect.h; path = Public/VLCMediaListAspect.h; sourceTree = "<group>"; };
632A0E830D3835C400AFC99B /* VLCStreamSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCStreamSession.h; path = Public/VLCStreamSession.h; sourceTree = "<group>"; };
632A0E840D3835C400AFC99B /* VLCStreamSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCStreamSession.m; sourceTree = "<group>"; };
632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCStreamOutput.h; path = Public/VLCStreamOutput.h; sourceTree = "<group>"; };
632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCStreamOutput.m; sourceTree = "<group>"; };
6341FCAE0D2C0929002A97B7 /* VLCVideoLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCVideoLayer.h; path = Public/VLCVideoLayer.h; sourceTree = "<group>"; };
6341FCB00D2C0936002A97B7 /* VLCVideoLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCVideoLayer.m; sourceTree = "<group>"; };
637CFB930D2D280800A041B6 /* VLCLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLibrary.h; path = Public/VLCLibrary.h; sourceTree = "<group>"; };
......@@ -219,6 +227,7 @@
EF78BD450CAEEFF600354E6E /* VLCVideoView.m */,
EF78BD440CAEEFF600354E6E /* VLCTime.m */,
EF73118F0CB5797B009473B4 /* VLCAudio.m */,
632A0F7B0D38F78500AFC99B /* Stream */,
);
path = Sources;
sourceTree = "<group>";
......@@ -250,6 +259,24 @@
name = "Other Sources";
sourceTree = "<group>";
};
632A0F7B0D38F78500AFC99B /* Stream */ = {
isa = PBXGroup;
children = (
632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */,
632A0E840D3835C400AFC99B /* VLCStreamSession.m */,
);
name = Stream;
sourceTree = "<group>";
};
632A0F7C0D38F79200AFC99B /* Stream */ = {
isa = PBXGroup;
children = (
632A0E830D3835C400AFC99B /* VLCStreamSession.h */,
632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */,
);
name = Stream;
sourceTree = "<group>";
};
637CFB960D2D281900A041B6 /* Internal */ = {
isa = PBXGroup;
children = (
......@@ -283,6 +310,7 @@
EF78BD1A0CAEEEE700354E6E /* VLCVideoView.h */,
EF78BD190CAEEEE700354E6E /* VLCTime.h */,
EF73118E0CB5797B009473B4 /* VLCAudio.h */,
632A0F7C0D38F79200AFC99B /* Stream */,
);
path = Headers;
sourceTree = "<group>";
......@@ -309,6 +337,8 @@
6341FCAF0D2C0929002A97B7 /* VLCVideoLayer.h in Headers */,
637CFB940D2D280900A041B6 /* VLCLibrary.h in Headers */,
A7A0CEA40D2EF13000F2C039 /* VLCVideoCommon.h in Headers */,
632A0E850D3835C400AFC99B /* VLCStreamSession.h in Headers */,
632A0EC30D38392E00AFC99B /* VLCStreamOutput.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -467,6 +497,8 @@
637D5ADC0CF6F2720073EA45 /* VLCMediaDiscoverer.m in Sources */,
6341FCB10D2C0936002A97B7 /* VLCVideoLayer.m in Sources */,
A7A0CEA50D2EF13000F2C039 /* VLCVideoCommon.m in Sources */,
632A0E860D3835C400AFC99B /* VLCStreamSession.m in Sources */,
632A0EC40D38392E00AFC99B /* VLCStreamOutput.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
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