Commit 03b43c91 authored by Carola Nitz's avatar Carola Nitz

VLCTranscoder: Add class for transcoding

This adds a function to mux an mp4 file and srt file into mov

(cherry picked from commit e3dddedc)
parent 553a5da7
......@@ -40,6 +40,7 @@ FOUNDATION_EXPORT const unsigned char DynamicMobileVLCKitVersionString[];
#import <DynamicMobileVLCKit/VLCMediaListPlayer.h>
#import <DynamicMobileVLCKit/VLCMediaThumbnailer.h>
#import <DynamicMobileVLCKit/VLCTime.h>
#import <DynamicMobileVLCKit/VLCTranscoder.h>
#import <DynamicMobileVLCKit/VLCDialogProvider.h>
@class VLCMedia;
......
......@@ -31,6 +31,7 @@
#import <MobileVLCKit/VLCMediaThumbnailer.h>
#import <MobileVLCKit/VLCDialogProvider.h>
#import <MobileVLCKit/VLCTime.h>
#import <MobileVLCKit/VLCTranscoder.h>
#import <MobileVLCKit/VLCRendererDiscoverer.h>
#import <MobileVLCKit/VLCRendererItem.h>
......
......@@ -30,11 +30,12 @@
#import <VLCKit/VLCMediaDiscoverer.h>
#import <VLCKit/VLCMediaPlayer.h>
#import <VLCKit/VLCMediaThumbnailer.h>
#import <VLCKit/VLCStreamSession.h>
#import <VLCKit/VLCStreamOutput.h>
#import <VLCKit/VLCTime.h>
#import <VLCKit/VLCTranscoder.h>
#import <VLCKit/VLCVideoView.h>
#import <VLCKit/VLCVideoLayer.h>
#import <VLCKit/VLCStreamSession.h>
#import <VLCKit/VLCStreamOutput.h>
@class VLCMedia;
@class VLCMediaLibrary;
......
/*****************************************************************************
* VLCTranscoder.h: VLCKit.framework VLCTranscoder implementation
*****************************************************************************
* Copyright (C) 2018 Carola Nitz
* Copyright (C) 2018 VLC authors and VideoLAN
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
* 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
* (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 Lesser General Public License for more details.
*
* 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.
*****************************************************************************/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Transcoder delegate allows to be notified about transcoding state
*/
@class VLCTranscoder;
@protocol VLCTranscoderDelegate <NSObject>
@optional
/**
* Called when the transcoding finished
* \param transcoder the transcoder object that finished
* \param success if transcoding finished sucessfully or not
*/
- (void)transcode:(VLCTranscoder *)transcoder finishedSucessfully:(BOOL)success;
@end
/**
* Provides an object to convert a subtitle file and moviefile into one.
*/
@interface VLCTranscoder: NSObject
/**
* the delegate object implementing the optional protocol
*/
@property (weak, nonatomic) id<VLCTranscoderDelegate> delegate;
/**
* Reencode and remuxes an srt and mp4 file to an mkv file with embedded subtitles either with VideoToolbox-based H264 encoding or VP80 is Videotoolbox is not available
* \param srtPath path to srt file
* \param mp4Path path to mp4 file
* \param outPath path where the new file should be written to
* \return an BOOL with the success status, returns NO if the subtitle file is not an srt or mp4File is not an mp4 file or the files don't exist at that path or transcoding failed for other reasons
*/
- (BOOL)reencodeAndMuxSRTFile:(NSString *)srtPath toMP4File:(NSString *)mp4Path outputPath:(NSString *)outPath;
@end
NS_ASSUME_NONNULL_END
......@@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
0E159EC41BC6B2890015BA7C /* VLCAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49C5FB1BC3D7870052D40C /* VLCAudio.m */; };
0E159EC51BC6B2930015BA7C /* VLCAudio.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B49C5FD1BC3D7960052D40C /* VLCAudio.h */; };
41E1959721BEA28F00F10277 /* VLCTranscoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 41E1959621BEA28F00F10277 /* VLCTranscoder.m */; };
41E1959A21BEA4FD00F10277 /* VLCTranscoder.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 41E1959821BEA2AF00F10277 /* VLCTranscoder.h */; };
4B09CED21BC463B100695566 /* VLCAudio.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4B49C5FD1BC3D7960052D40C /* VLCAudio.h */; };
4B49C5FC1BC3D7870052D40C /* VLCAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49C5FB1BC3D7870052D40C /* VLCAudio.m */; };
6360B0E211E7F0C000EAD790 /* VLCMediaDiscoverer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6360B0E111E7F0C000EAD790 /* VLCMediaDiscoverer.m */; };
......@@ -261,6 +263,7 @@
dstPath = MobileVLCKit;
dstSubfolderSpec = 16;
files = (
41E1959A21BEA4FD00F10277 /* VLCTranscoder.h in Copy Headers */,
8D826AE1203F3CC500536EF7 /* VLCRendererDiscoverer.h in Copy Headers */,
8D826AE2203F3CC500536EF7 /* VLCRendererItem.h in Copy Headers */,
7D6695301CB5574C00F79C08 /* VLCDialogProvider.h in Copy Headers */,
......@@ -361,6 +364,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
41E1959621BEA28F00F10277 /* VLCTranscoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCTranscoder.m; path = Sources/VLCTranscoder.m; sourceTree = "<group>"; };
41E1959821BEA2AF00F10277 /* VLCTranscoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VLCTranscoder.h; path = Headers/Public/VLCTranscoder.h; sourceTree = "<group>"; };
4B49C5FB1BC3D7870052D40C /* VLCAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCAudio.m; path = Sources/VLCAudio.m; sourceTree = "<group>"; };
4B49C5FD1BC3D7960052D40C /* VLCAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCAudio.h; path = Headers/Public/VLCAudio.h; sourceTree = "<group>"; };
6360B0E111E7F0C000EAD790 /* VLCMediaDiscoverer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMediaDiscoverer.m; path = Sources/VLCMediaDiscoverer.m; sourceTree = "<group>"; };
......@@ -684,6 +689,7 @@
636E975711EBC67A002FE8A9 /* VLCMediaThumbnailer.m */,
6360B0E111E7F0C000EAD790 /* VLCMediaDiscoverer.m */,
7A5ECAC911DE8F7300F66AF3 /* VLCTime.m */,
41E1959621BEA28F00F10277 /* VLCTranscoder.m */,
7D34F5571C909E13008A39F0 /* Dialogs */,
7DB683D31C996187000C70BE /* VLCHelperCode.m */,
8D826AE0203F3CA700536EF7 /* Renderer */,
......@@ -717,6 +723,7 @@
6360B0E311E7F0D300EAD790 /* VLCMediaDiscoverer.h */,
7D803EB71C8F21EF00864A9C /* VLCDialogProvider.h */,
7A5ECAD811DE8FAB00F66AF3 /* VLCTime.h */,
41E1959821BEA2AF00F10277 /* VLCTranscoder.h */,
8D2CE647203DCC48004BB7F6 /* VLCRendererDiscoverer.h */,
8D2CE64E203EEA47004BB7F6 /* VLCRendererItem.h */,
7DEBDADE203C56BC000A7D2F /* libvlc */,
......@@ -1371,6 +1378,7 @@
7D803EC91C8F2B0900864A9C /* VLCDialogProvider.m in Sources */,
7A5ECACE11DE8F7300F66AF3 /* VLCMediaList.m in Sources */,
7A5ECACF11DE8F7300F66AF3 /* VLCMediaPlayer.m in Sources */,
41E1959721BEA28F00F10277 /* VLCTranscoder.m in Sources */,
7A5ECAD011DE8F7300F66AF3 /* VLCTime.m in Sources */,
6360B0E211E7F0C000EAD790 /* VLCMediaDiscoverer.m in Sources */,
7DB683D61C996187000C70BE /* VLCHelperCode.m in Sources */,
......
/*****************************************************************************
* VLCTranscoder.m: VLCKit.framework VLCTranscoder implementation
*****************************************************************************
* Copyright (C) 2018 Carola Nitz
* Copyright (C) 2018 VLC authors and VideoLAN
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
* 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
* (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 Lesser General Public License for more details.
*
* 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.
*****************************************************************************/
#import "VLCTranscoder.h"
#import "VLCEventManager.h"
#import "VLCLibrary.h"
#import "VLCLibVLCBridging.h"
#include <vlc/vlc.h>
@interface VLCTranscoder()
{
libvlc_media_player_t *_p_mp; //player instance used for transcoding
dispatch_queue_t _libVLCTranscoderQueue;
}
- (void)registerObserversForMuxWithPlayer:(libvlc_media_player_t *)player;
- (void)unregisterObserversForMuxWithPlayer:(libvlc_media_player_t *)player;
@end
@implementation VLCTranscoder
- (instancetype)init
{
if (self = [super init]) {
_libVLCTranscoderQueue = dispatch_queue_create("libVLCTranscoderQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (BOOL)reencodeAndMuxSRTFile:(NSString *)srtPath toMP4File:(NSString *)mp4Path outputPath:(NSString *)outPath
{
libvlc_media_t* p_media = libvlc_media_new_path([[VLCLibrary sharedLibrary] instance], [mp4Path UTF8String]);
if (p_media == NULL) {
NSAssert(0, @"p_media wasn't allocated");
return NO;
}
NSString *transcodingOptions = [NSString stringWithFormat:@":sout=#transcode{venc={module=avcodec{codec=h264_videotoolbox}, vcodec=h264},venc={module=vpx{quality-mode=2},vcodec=VP80},samplerate=44100,soverlay}:file{dst='%@',mux=mkv}", outPath];
libvlc_media_add_option(p_media, [[NSString stringWithFormat:@"--sub-file=%@", srtPath] UTF8String]);
libvlc_media_add_option(p_media, [transcodingOptions UTF8String]);
_p_mp = libvlc_media_player_new_from_media( p_media );
if (_p_mp == NULL) {
NSAssert(0, @"_p_mp wasn't allocated");
return NO;
}
[self registerObserversForMuxWithPlayer:_p_mp];
BOOL canPlay = libvlc_media_player_play( _p_mp ) == 0;
if (!canPlay) {
NSAssert(0, @"playback failed");
[self unregisterObserversForMuxWithPlayer:_p_mp];
return NO;
}
return canPlay;
}
- (void)registerObserversForMuxWithPlayer:(libvlc_media_player_t *)player
{
__block libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(player);
if (!p_em)
return;
CFBridgingRetain(self);
dispatch_sync(_libVLCTranscoderQueue,^{
libvlc_event_attach(p_em, libvlc_MediaPlayerPaused,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
libvlc_event_attach(p_em, libvlc_MediaPlayerStopped,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
libvlc_event_attach(p_em, libvlc_MediaPlayerEncounteredError,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
});
}
- (void)unregisterObserversForMuxWithPlayer:(libvlc_media_player_t *)player
{
libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(player);
if (!p_em)
return;
dispatch_sync(_libVLCTranscoderQueue,^{
libvlc_event_detach(p_em, libvlc_MediaPlayerStopped,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
libvlc_event_detach(p_em, libvlc_MediaPlayerPaused,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
libvlc_event_detach(p_em, libvlc_MediaPlayerEncounteredError,
HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
});
CFBridgingRelease((__bridge CFTypeRef _Nullable)(self));
}
- (void)mediaPlayerStateChangeForMux:(NSNumber *)newState
{
if (_p_mp) {
[self unregisterObserversForMuxWithPlayer:_p_mp];
libvlc_media_player_stop( _p_mp );
if (self.delegate && [self.delegate respondsToSelector:@selector(transcode:finishedSucessfully:)]) {
BOOL success = ![newState isEqualToNumber: @(VLCMediaPlayerStateError)];
[self.delegate transcode:self finishedSucessfully:success];
}
}
}
static void HandleMuxMediaInstanceStateChanged(const libvlc_event_t * event, void * self)
{
VLCMediaPlayerState newState;
if (event->type == libvlc_MediaPlayerPaused) {
newState = VLCMediaPlayerStatePaused;
} else if(event->type == libvlc_MediaPlayerStopped) {
newState = VLCMediaPlayerStateStopped;
} else {
newState = VLCMediaPlayerStateError;
}
@autoreleasepool {
[[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
withMethod:@selector(mediaPlayerStateChangeForMux:)
withArgumentAsObject:@(newState)];
}
}
- (void)dealloc
{
libvlc_media_player_release(_p_mp);
}
@end
......@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
41657C232059D49200AB915B /* VLCRendererDiscoverer.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C212059D49200AB915B /* VLCRendererDiscoverer.h */; };
41657C242059D49200AB915B /* VLCRendererItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C222059D49200AB915B /* VLCRendererItem.h */; };
4102567221B56E6E00253ECF /* VLCTranscoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 4102566F21B56C7500253ECF /* VLCTranscoder.m */; };
41657C282059D56900AB915B /* TVVLCKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C272059D56900AB915B /* TVVLCKit.h */; };
41657C2B2059D57900AB915B /* DynamicTVVLCKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C292059D57800AB915B /* DynamicTVVLCKit.h */; };
41657C2C2059D57900AB915B /* DynamicMobileVLCKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C2A2059D57800AB915B /* DynamicMobileVLCKit.h */; };
......@@ -18,6 +19,7 @@
41657C3F2059D99E00AB915B /* VLCiOSLegacyDialogProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 41657C3C2059D99E00AB915B /* VLCiOSLegacyDialogProvider.h */; };
41657C422059DE7B00AB915B /* VLCRendererDiscoverer.m in Sources */ = {isa = PBXBuildFile; fileRef = 41657C402059DE7B00AB915B /* VLCRendererDiscoverer.m */; };
41657C432059DE7B00AB915B /* VLCRendererItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 41657C412059DE7B00AB915B /* VLCRendererItem.m */; };
41BD71FA21B9666000795629 /* VLCTranscoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4102566E21B56C7500253ECF /* VLCTranscoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
7DC28D4B2019406B002D05C4 /* StaticLibVLC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC28D4A2019406B002D05C4 /* StaticLibVLC.m */; };
7DC28D4E20194117002D05C4 /* VLCEventManager.h in Headers */ = {isa = PBXBuildFile; fileRef = EF78BD0D0CAEEEC300354E6E /* VLCEventManager.h */; settings = {ATTRIBUTES = (); }; };
7DC28D4F20194117002D05C4 /* VLCKit.h in Headers */ = {isa = PBXBuildFile; fileRef = EF78BD120CAEEEE700354E6E /* VLCKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -153,6 +155,8 @@
0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
32DBCF5E0370ADEE00C91783 /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = Headers/PCH/Prefix.pch; sourceTree = "<group>"; };
4102566E21B56C7500253ECF /* VLCTranscoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VLCTranscoder.h; path = Public/VLCTranscoder.h; sourceTree = "<group>"; };
4102566F21B56C7500253ECF /* VLCTranscoder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCTranscoder.m; sourceTree = "<group>"; };
41657C212059D49200AB915B /* VLCRendererDiscoverer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCRendererDiscoverer.h; path = Public/VLCRendererDiscoverer.h; sourceTree = "<group>"; };
41657C222059D49200AB915B /* VLCRendererItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCRendererItem.h; path = Public/VLCRendererItem.h; sourceTree = "<group>"; };
41657C272059D56900AB915B /* TVVLCKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TVVLCKit.h; path = Public/TVVLCKit.h; sourceTree = "<group>"; };
......@@ -362,6 +366,7 @@
EF78BD450CAEEFF600354E6E /* VLCVideoView.m */,
EF78BD440CAEEFF600354E6E /* VLCTime.m */,
EF73118F0CB5797B009473B4 /* VLCAudio.m */,
4102566F21B56C7500253ECF /* VLCTranscoder.m */,
7DF7A2041D197E8E0001FF69 /* VLCHelperCode.m */,
7D34F56C1C90A990008A39F0 /* Dialogs */,
632A0F7B0D38F78500AFC99B /* Stream */,
......@@ -593,6 +598,7 @@
EF78BD190CAEEEE700354E6E /* VLCTime.h */,
6341FCAE0D2C0929002A97B7 /* VLCVideoLayer.h */,
EF78BD1A0CAEEEE700354E6E /* VLCVideoView.h */,
4102566E21B56C7500253ECF /* VLCTranscoder.h */,
);
name = Public;
sourceTree = "<group>";
......@@ -630,6 +636,7 @@
7DC28D5420194117002D05C4 /* VLCTime.h in Headers */,
7DC28D5520194117002D05C4 /* VLCVideoView.h in Headers */,
7DC28D5620194117002D05C4 /* VLCMediaPlayer.h in Headers */,
41BD71FA21B9666000795629 /* VLCTranscoder.h in Headers */,
7DC28D5720194117002D05C4 /* VLCAudio.h in Headers */,
7DC28D5820194117002D05C4 /* VLCLibVLCBridging.h in Headers */,
7DC28D5B20194117002D05C4 /* VLCMediaDiscoverer.h in Headers */,
......@@ -814,6 +821,7 @@
7DC28D6920194117002D05C4 /* VLCMediaLibrary.m in Sources */,
7DC28D6A20194117002D05C4 /* VLCMediaList.m in Sources */,
7DC28D6B20194117002D05C4 /* VLCTime.m in Sources */,
4102567221B56E6E00253ECF /* VLCTranscoder.m in Sources */,
7DC28D6C20194117002D05C4 /* VLCVideoView.m in Sources */,
7DC28D6D20194117002D05C4 /* VLCCustomDialogProvider.m in Sources */,
41657C422059DE7B00AB915B /* VLCRendererDiscoverer.m in Sources */,
......
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