VapxMP4Decoder.m 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Tencent is pleased to support the open source community by making vap available.
  2. //
  3. // Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
  4. //
  5. // Licensed under the MIT License (the "License"); you may not use this file except in
  6. // compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://opensource.org/licenses/MIT
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License is
  11. // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12. // either express or implied. See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "VapxMP4Decoder.h"
  15. #import "AppDelegate.h"
  16. @implementation VapxMP4Decoder
  17. + (NSString *)encodeWithDir:(NSString *)directory outputName:(NSString *)output fps:(NSInteger)fps bitRate:(NSString *)bitRate audioPath:(NSString *)audioPath {
  18. VapxMP4Decoder *encoder = [VapxMP4Decoder new];
  19. encoder.resourceDirectory = directory;
  20. encoder.outputName = output;
  21. encoder.fps = fps;
  22. encoder.bitRate = bitRate;
  23. encoder.audioPath = audioPath;
  24. return [encoder encode];
  25. }
  26. - (NSString *)encode {
  27. NSFileManager *fileManager = [NSFileManager defaultManager];
  28. if (self.resourceDirectory.length == 0 || ![fileManager fileExistsAtPath:self.resourceDirectory]) {
  29. return nil;
  30. }
  31. if (!self.outputName) {
  32. return nil;
  33. }
  34. NSString *ffmpegPath = [[NSBundle mainBundle] pathForResource:@"ffmpeg" ofType:@""];
  35. NSString *inputPath = [self.resourceDirectory stringByAppendingPathComponent:@"*.png"];
  36. __block NSString *outputName = self.outputName;
  37. __block BOOL isVp9;
  38. dispatch_sync(dispatch_get_main_queue(), ^{
  39. isVp9 = [[(AppDelegate *)[NSApplication sharedApplication].delegate encoder] isEqualToString:@"libvpx-vp9"];
  40. if (isVp9) {
  41. outputName = [outputName stringByReplacingOccurrencesOfString:@"mp4" withString:@"webm"];
  42. }
  43. });
  44. __block BOOL isH265;
  45. dispatch_sync(dispatch_get_main_queue(), ^{
  46. isH265 = [[(AppDelegate *)[NSApplication sharedApplication].delegate encoder] isEqualToString:@"libx265"];
  47. });
  48. NSString *output = [self.resourceDirectory stringByAppendingPathComponent:outputName];
  49. if ([fileManager fileExistsAtPath:output]) {
  50. NSError *error = nil;
  51. [[NSFileManager defaultManager] removeItemAtPath:output error:&error];
  52. if (error) {
  53. NSLog(@"removeItemAtPath:%@ fail!", output);
  54. return nil;
  55. }
  56. }
  57. NSMutableArray *arguments = nil;
  58. // high 3.0 main 4.0
  59. if (isH265) {
  60. arguments = [@[@"-r", [NSString stringWithFormat:@"%@", @(MAX(self.fps, 1))],
  61. @"-pattern_type", @"glob",
  62. @"-i", inputPath,
  63. @"-c:v", @"libx265",
  64. @"-pix_fmt", self.yuvFormat?:@"yuv420p",
  65. @"-profile:v", self.profile?:@"main",
  66. @"-level",@"4.0",
  67. @"-b:v", self.bitRate?: @"2000k",
  68. /*@"-bf", @"0",*/
  69. /*@"-crf", @"28",*/
  70. @"-tag:v", @"hvc1",
  71. @"-bufsize", @"2000k", output] mutableCopy];
  72. } else if (isVp9) {
  73. arguments = [@[@"-framerate", [NSString stringWithFormat:@"%@", @(MAX(self.fps, 1))],
  74. @"-pattern_type", @"glob",
  75. @"-i", inputPath,
  76. @"-c:v", @"libvpx-vp9",
  77. @"-pix_fmt", self.yuvFormat?:@"yuv420p",
  78. @"-b:v", self.bitRate?: @"2000k",
  79. @"-bufsize", @"2000k", output] mutableCopy];
  80. } else {
  81. arguments = [@[@"-r", [NSString stringWithFormat:@"%@", @(MAX(self.fps, 1))],
  82. @"-pattern_type", @"glob",
  83. @"-i", inputPath,
  84. @"-c:v", @"libx264",
  85. @"-pix_fmt", self.yuvFormat?:@"yuv420p",
  86. @"-profile:v", self.profile?:@"main",
  87. @"-level",@"4.0",
  88. @"-b:v", self.bitRate?: @"2000k",
  89. @"-bf", @"0",
  90. /*@"-crf", @"28",*/
  91. @"-bufsize", @"2000k", output] mutableCopy];
  92. }
  93. if (self.audioPath.length > 0) {
  94. if (isVp9) {
  95. [arguments insertObjects:@[@"-i",self.audioPath,@"-c:a",@"libopus",@"-ab", @"112k"] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(6, 6)]];
  96. } else {
  97. [arguments insertObjects:@[@"-i",self.audioPath,@"-c:a",@"aac",@"-ab", @"112k"] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(6, 6)]];
  98. }
  99. }
  100. NSPipe *pipe = [NSPipe pipe];
  101. NSFileHandle * read = [pipe fileHandleForReading];
  102. NSTask *task = [[NSTask alloc] init];
  103. [task setLaunchPath: ffmpegPath];
  104. [task setArguments: arguments];
  105. [task setStandardOutput: pipe];
  106. [task launch];
  107. [task waitUntilExit];
  108. NSData* data = [read readDataToEndOfFile];
  109. NSString* stringOutput = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  110. NSLog(@"stringOutput:%@, terminationStatus:%i",stringOutput, [task terminationStatus]);
  111. return output;
  112. }
  113. @end