VLCTranscoder.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*****************************************************************************
  2. * VLCTranscoder.m: VLCKit.framework VLCTranscoder implementation
  3. *****************************************************************************
  4. * Copyright (C) 2018 Carola Nitz
  5. * Copyright (C) 2018 VLC authors and VideoLAN
  6. * $Id$
  7. *
  8. * Authors: Carola Nitz <caro # videolan.org>
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation; either version 2.1 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public License
  21. * along with this program; if not, write to the Free Software Foundation,
  22. * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23. *****************************************************************************/
  24. #import "VLCTranscoder.h"
  25. #import "VLCEventManager.h"
  26. #import "VLCLibrary.h"
  27. #import "VLCLibVLCBridging.h"
  28. #include <vlc/vlc.h>
  29. @interface VLCTranscoder()
  30. {
  31. libvlc_media_player_t *_p_mp; //player instance used for transcoding
  32. dispatch_queue_t _libVLCTranscoderQueue;
  33. }
  34. - (void)registerObserversForMuxWithPlayer:(libvlc_media_player_t *)player;
  35. - (void)unregisterObserversForMuxWithPlayer:(libvlc_media_player_t *)player;
  36. @end
  37. @implementation VLCTranscoder
  38. - (instancetype)init
  39. {
  40. if (self = [super init]) {
  41. _libVLCTranscoderQueue = dispatch_queue_create("libVLCTranscoderQueue", DISPATCH_QUEUE_SERIAL);
  42. }
  43. return self;
  44. }
  45. - (BOOL)reencodeAndMuxSRTFile:(NSString *)srtPath toMP4File:(NSString *)mp4Path outputPath:(NSString *)outPath
  46. {
  47. libvlc_media_t* p_media = libvlc_media_new_path([[VLCLibrary sharedLibrary] instance], [mp4Path UTF8String]);
  48. if (p_media == NULL) {
  49. NSAssert(0, @"p_media wasn't allocated");
  50. return NO;
  51. }
  52. 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];
  53. libvlc_media_add_option(p_media, [[NSString stringWithFormat:@"--sub-file=%@", srtPath] UTF8String]);
  54. libvlc_media_add_option(p_media, [transcodingOptions UTF8String]);
  55. _p_mp = libvlc_media_player_new_from_media( p_media );
  56. if (_p_mp == NULL) {
  57. NSAssert(0, @"_p_mp wasn't allocated");
  58. return NO;
  59. }
  60. [self registerObserversForMuxWithPlayer:_p_mp];
  61. BOOL canPlay = libvlc_media_player_play( _p_mp ) == 0;
  62. if (!canPlay) {
  63. NSAssert(0, @"playback failed");
  64. [self unregisterObserversForMuxWithPlayer:_p_mp];
  65. return NO;
  66. }
  67. return canPlay;
  68. }
  69. - (void)registerObserversForMuxWithPlayer:(libvlc_media_player_t *)player
  70. {
  71. __block libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(player);
  72. if (!p_em)
  73. return;
  74. CFBridgingRetain(self);
  75. dispatch_sync(_libVLCTranscoderQueue,^{
  76. libvlc_event_attach(p_em, libvlc_MediaPlayerPaused,
  77. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  78. libvlc_event_attach(p_em, libvlc_MediaPlayerStopped,
  79. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  80. libvlc_event_attach(p_em, libvlc_MediaPlayerEncounteredError,
  81. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  82. });
  83. }
  84. - (void)unregisterObserversForMuxWithPlayer:(libvlc_media_player_t *)player
  85. {
  86. libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(player);
  87. if (!p_em)
  88. return;
  89. dispatch_sync(_libVLCTranscoderQueue,^{
  90. libvlc_event_detach(p_em, libvlc_MediaPlayerStopped,
  91. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  92. libvlc_event_detach(p_em, libvlc_MediaPlayerPaused,
  93. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  94. libvlc_event_detach(p_em, libvlc_MediaPlayerEncounteredError,
  95. HandleMuxMediaInstanceStateChanged, (__bridge void *)(self));
  96. });
  97. CFBridgingRelease((__bridge CFTypeRef _Nullable)(self));
  98. }
  99. - (void)mediaPlayerStateChangeForMux:(NSNumber *)newState
  100. {
  101. if (_p_mp) {
  102. [self unregisterObserversForMuxWithPlayer:_p_mp];
  103. libvlc_media_player_stop_async( _p_mp );
  104. if (self.delegate && [self.delegate respondsToSelector:@selector(transcode:finishedSucessfully:)]) {
  105. BOOL success = ![newState isEqualToNumber: @(VLCMediaPlayerStateError)];
  106. [self.delegate transcode:self finishedSucessfully:success];
  107. }
  108. }
  109. }
  110. static void HandleMuxMediaInstanceStateChanged(const libvlc_event_t * event, void * self)
  111. {
  112. VLCMediaPlayerState newState;
  113. if (event->type == libvlc_MediaPlayerPaused) {
  114. newState = VLCMediaPlayerStatePaused;
  115. } else if(event->type == libvlc_MediaPlayerStopped) {
  116. newState = VLCMediaPlayerStateStopped;
  117. } else {
  118. newState = VLCMediaPlayerStateError;
  119. }
  120. @autoreleasepool {
  121. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  122. withMethod:@selector(mediaPlayerStateChangeForMux:)
  123. withArgumentAsObject:@(newState)];
  124. }
  125. }
  126. - (void)dealloc
  127. {
  128. libvlc_media_player_release(_p_mp);
  129. }
  130. @end