VLCStreamOutput.m 9.05 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * VLCStreamOutput.m: VLCKit.framework VLCStreamOutput implementation
 *****************************************************************************
 * Copyright (C) 2008 Pierre d'Herbemont
5
 * Copyright (C) 2008, 2014 VLC authors and VideoLAN
6
 * Copyright (C) 2012 Brendon Justin
7 8 9
 * $Id$
 *
 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
10
 *          Brendon Justin <brendonjustin # gmail.com>
11
 *
12 13 14
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
15 16 17 18
 * (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
19 20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
21
 *
22 23 24
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25
 *****************************************************************************/
26 27 28 29

#import "VLCStreamOutput.h"
#import "VLCLibVLCBridging.h"

30 31 32 33 34 35
@interface VLCStreamOutput ()
{
    NSMutableDictionary *_options;
}
@end

36
@implementation VLCStreamOutput
37 38 39 40 41 42

- (instancetype)init
{
    return [self initWithOptionDictionary:nil];
}

43
- (instancetype)initWithOptionDictionary:(NSDictionary *)dictionary
44
{
45 46 47
    if (self = [super init])
        _options = [dictionary mutableCopy];

48 49 50 51 52 53
    return self;
}
- (NSString *)description
{
    return [self representedLibVLCOptions];
}
54
+ (instancetype)streamOutputWithOptionDictionary:(NSDictionary *)dictionary
55
{
56
    return [[self alloc] initWithOptionDictionary:dictionary];
57 58 59
}
+ (id)rtpBroadcastStreamOutputWithSAPAnnounce:(NSString *)announceName
{
60 61 62 63 64 65 66 67 68 69
    return [self streamOutputWithOptionDictionary:@{
        @"rtpOptions" : @{
            @"muxer" : @"ts",
            @"access" : @"file",
            @"sdp" : @"sdp",
            @"sap" : @"sap",
            @"name" : [announceName copy],
            @"destination" : @"239.255.1.1"
        }
    }];
70 71 72 73 74 75 76 77 78
}

+ (id)rtpBroadcastStreamOutput
{
    return [self rtpBroadcastStreamOutputWithSAPAnnounce:@"Helloworld!"];
}

+ (id)ipodStreamOutputWithFilePath:(NSString *)filePath
{
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    return [self streamOutputWithOptionDictionary:@{
        @"transcodingOptions" : @{
            @"videoCodec" : @"h264",
            @"videoBitrate" : @"1024",
            @"audioCodec" : @"mp3",
            @"audioBitrate" : @"128",
            @"channels" : @"2",
            @"width" : @"640",
            @"height" : @"480",
            @"audio-sync" : @"Yes"
        },
        @"outputOptions" : @{
            @"muxer" : @"mp4",
            @"access" : @"file",
            @"destination" : [[NSURL URLWithString:filePath] absoluteString]
        }
    }];
96
}
97 98 99

+ (id)mpeg4StreamOutputWithFilePath:(NSString *)filePath
{
100 101 102 103 104 105 106 107 108 109 110 111 112
    return [self streamOutputWithOptionDictionary:@{
        @"transcodingOptions" : @{
            @"videoCodec" : @"mp4v",
            @"videoBitrate" : @"1024",
            @"audioCodec" : @"mp4a",
            @"audioBitrate" : @"192"
        },
        @"outputOptions" : @{
            @"muxer" : @"mp4",
            @"access" : @"file",
            @"destination" : [filePath copy]
        }
    }];
113 114
}

115
+ (instancetype)streamOutputWithFilePath:(NSString *)filePath
116
{
117 118 119 120 121 122 123
    return [self streamOutputWithOptionDictionary:@{
        @"outputOptions" : @{
            @"muxer" : @"ps",
            @"access" : @"file",
            @"destination" : [filePath copy]
        }
    }];
124 125 126 127
}

+ (id)mpeg2StreamOutputWithFilePath:(NSString *)filePath;
{
128 129 130 131 132 133 134 135 136 137 138 139 140 141
    return [self streamOutputWithOptionDictionary:@{
        @"transcodingOptions" : @{
            @"videoCodec" : @"mp2v",
            @"videoBitrate" : @"1024",
            @"audioCodec" : @"mpga",
            @"audioBitrate" : @"128",
            @"audio-sync" : @"Yes"
        },
        @"outputOptions" : @{
            @"muxer" : @"ps",
            @"access" : @"file",
            @"destination" : [filePath copy]
        }
    }];
142
}
143 144 145 146 147 148 149 150
@end

@implementation VLCStreamOutput (LibVLCBridge)
- (NSString *)representedLibVLCOptions
{
    NSString * representedOptions;
    NSMutableArray * subOptions = [NSMutableArray array];
    NSMutableArray * optionsAsArray = [NSMutableArray array];
151
    NSDictionary * transcodingOptions = _options[@"transcodingOptions"];
152 153
    if( transcodingOptions )
    {
154 155 156 157 158 159 160 161 162 163 164 165 166
        NSString * videoCodec = transcodingOptions[@"videoCodec"];
        NSString * audioCodec = transcodingOptions[@"audioCodec"];
        NSString * subtitleCodec = transcodingOptions[@"subtitleCodec"];
        NSString * videoBitrate = transcodingOptions[@"videoBitrate"];
        NSString * audioBitrate = transcodingOptions[@"audioBitrate"];
        NSString * channels = transcodingOptions[@"channels"];
        NSString * height = transcodingOptions[@"height"];
        NSString * canvasHeight = transcodingOptions[@"canvasHeight"];
        NSString * width = transcodingOptions[@"width"];
        NSString * audioSync = transcodingOptions[@"audioSync"];
        NSString * videoEncoder = transcodingOptions[@"videoEncoder"];
        NSString * subtitleEncoder = transcodingOptions[@"subtitleEncoder"];
        NSString * subtitleOverlay = transcodingOptions[@"subtitleOverlay"];
167
        if( videoEncoder )   [subOptions addObject:[NSString stringWithFormat:@"venc=%@", videoEncoder]];
168 169 170 171 172 173 174 175
        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]];
176
        if( audioSync ) [subOptions addObject:@"audioSync"];
177 178 179
        if( subtitleCodec ) [subOptions addObject:[NSString stringWithFormat:@"scodec=%@", subtitleCodec]];
        if( subtitleEncoder ) [subOptions addObject:[NSString stringWithFormat:@"senc=%@", subtitleEncoder]];
        if( subtitleOverlay ) [subOptions addObject:@"soverlay"];
180
        [optionsAsArray addObject: [NSString stringWithFormat:@"#transcode{%@}", [subOptions componentsJoinedByString:@","]]];
181 182
        [subOptions removeAllObjects];
    }
183

184
    NSDictionary * outputOptions = _options[@"outputOptions"];
185 186
    if( outputOptions )
    {
187 188 189 190
        NSString * muxer = outputOptions[@"muxer"];
        NSString * destination = outputOptions[@"destination"];
        NSString * url = outputOptions[@"url"];
        NSString * access = outputOptions[@"access"];
191
        if( muxer )       [subOptions addObject:[NSString stringWithFormat:@"mux=%@", muxer]];
192 193 194
        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]];
195 196 197 198 199
        NSString *std = [NSString stringWithFormat:@"std{%@}", [subOptions componentsJoinedByString:@","]];
        if ( !transcodingOptions )
            std = [NSString stringWithFormat:@"#%@", std];

        [optionsAsArray addObject:std];
200 201 202
        [subOptions removeAllObjects];
    }

203
    NSDictionary * rtpOptions = _options[@"rtpOptions"];
204 205
    if( rtpOptions )
    {
206 207 208 209 210
        NSString * muxer = rtpOptions[@"muxer"];
        NSString * destination = rtpOptions[@"destination"];
        NSString * sdp = rtpOptions[@"sdp"];
        NSString * name = rtpOptions[@"name"];
        NSString * sap = rtpOptions[@"sap"];
211 212 213
        if( muxer )       [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", muxer]];
        if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=%@", destination]];
        if( sdp )      [subOptions addObject:[NSString stringWithFormat:@"sdp=%@", sdp]];
214
        if( sap )      [subOptions addObject:@"sap"];
215
        if( name )      [subOptions addObject:[NSString stringWithFormat:@"name=\"%@\"", name]];
216 217 218 219 220
        NSString *rtp = [NSString stringWithFormat:@"#rtp{%@}", [subOptions componentsJoinedByString:@","]];
        if ( !transcodingOptions )
            rtp = [NSString stringWithFormat:@"#%@", rtp];

        [optionsAsArray addObject:rtp];
221 222 223 224 225 226
        [subOptions removeAllObjects];
    }
    representedOptions = [optionsAsArray componentsJoinedByString:@":"];
    return representedOptions;
}
@end