From c00520929c82f6be77273c5c6e7b9e64fcde6d94 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 8 Dec 2021 16:47:35 +0400 Subject: [PATCH] Initial video sticker implementation --- .../FFMpegBinding/FFMpegAVFormatContext.h | 3 + .../Public/FFMpegBinding/FFMpegAVFrame.h | 6 ++ .../Sources/FFMpegAVFormatContext.m | 6 ++ .../FFMpegBinding/Sources/FFMpegAVFrame.m | 9 +++ .../FFMpegMediaVideoFrameDecoder.swift | 59 ++++++++++++++----- .../Sources/SoftwareVideoSource.swift | 6 +- .../UniversalSoftwareVideoSource.swift | 14 +++-- .../ChatMessageAnimatedStickerItemNode.swift | 57 +++++++++++++++++- .../TelegramUI/Sources/ChatMessageItem.swift | 4 ++ .../SoftwareVideoLayerFrameManager.swift | 6 +- submodules/ffmpeg/BUILD | 38 ++++++++++++ .../Sources/FFMpeg/build-ffmpeg-bazel.sh | 6 +- submodules/ffmpeg/Sources/FFMpeg/pkg-config | 24 +++++++- 13 files changed, 209 insertions(+), 29 deletions(-) diff --git a/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFormatContext.h b/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFormatContext.h index 33db0a7308..ba5b196d01 100644 --- a/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFormatContext.h +++ b/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFormatContext.h @@ -27,6 +27,7 @@ typedef struct FFMpegStreamMetrics { extern int FFMpegCodecIdH264; extern int FFMpegCodecIdHEVC; extern int FFMpegCodecIdMPEG4; +extern int FFMpegCodecIdVP9; @class FFMpegAVCodecContext; @@ -47,6 +48,8 @@ extern int FFMpegCodecIdMPEG4; - (FFMpegFpsAndTimebase)fpsAndTimebaseForStreamIndex:(int32_t)streamIndex defaultTimeBase:(CMTime)defaultTimeBase; - (FFMpegStreamMetrics)metricsForStreamAtIndex:(int32_t)streamIndex; +- (void)forceVideoCodecId:(int)videoCodecId; + @end NS_ASSUME_NONNULL_END diff --git a/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFrame.h b/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFrame.h index e87eaaac8a..03451f42c4 100644 --- a/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFrame.h +++ b/submodules/FFMpegBinding/Public/FFMpegBinding/FFMpegAVFrame.h @@ -7,6 +7,11 @@ typedef NS_ENUM(NSUInteger, FFMpegAVFrameColorRange) { FFMpegAVFrameColorRangeFull }; +typedef NS_ENUM(NSUInteger, FFMpegAVFramePixelFormat) { + FFMpegAVFramePixelFormatYUV, + FFMpegAVFramePixelFormatYUVA +}; + @interface FFMpegAVFrame : NSObject @property (nonatomic, readonly) int32_t width; @@ -16,6 +21,7 @@ typedef NS_ENUM(NSUInteger, FFMpegAVFrameColorRange) { @property (nonatomic, readonly) int64_t pts; @property (nonatomic, readonly) int64_t duration; @property (nonatomic, readonly) FFMpegAVFrameColorRange colorRange; +@property (nonatomic, readonly) FFMpegAVFramePixelFormat pixelFormat; - (instancetype)init; diff --git a/submodules/FFMpegBinding/Sources/FFMpegAVFormatContext.m b/submodules/FFMpegBinding/Sources/FFMpegAVFormatContext.m index 5d91d6b080..992e6dabac 100644 --- a/submodules/FFMpegBinding/Sources/FFMpegAVFormatContext.m +++ b/submodules/FFMpegBinding/Sources/FFMpegAVFormatContext.m @@ -9,6 +9,7 @@ int FFMpegCodecIdH264 = AV_CODEC_ID_H264; int FFMpegCodecIdHEVC = AV_CODEC_ID_HEVC; int FFMpegCodecIdMPEG4 = AV_CODEC_ID_MPEG4; +int FFMpegCodecIdVP9 = AV_CODEC_ID_VP9; @interface FFMpegAVFormatContext () { AVFormatContext *_impl; @@ -144,4 +145,9 @@ int FFMpegCodecIdMPEG4 = AV_CODEC_ID_MPEG4; return (FFMpegStreamMetrics){ .width = _impl->streams[streamIndex]->codecpar->width, .height = _impl->streams[streamIndex]->codecpar->height, .rotationAngle = rotationAngle, .extradata = _impl->streams[streamIndex]->codecpar->extradata, .extradataSize = _impl->streams[streamIndex]->codecpar->extradata_size }; } +- (void)forceVideoCodecId:(int)videoCodecId { + _impl->video_codec_id = videoCodecId; + _impl->video_codec = avcodec_find_decoder(videoCodecId); +} + @end diff --git a/submodules/FFMpegBinding/Sources/FFMpegAVFrame.m b/submodules/FFMpegBinding/Sources/FFMpegAVFrame.m index e905c08431..9c8218e0fe 100644 --- a/submodules/FFMpegBinding/Sources/FFMpegAVFrame.m +++ b/submodules/FFMpegBinding/Sources/FFMpegAVFrame.m @@ -62,4 +62,13 @@ return _impl; } +- (FFMpegAVFramePixelFormat)pixelFormat { + switch (_impl->format) { + case AV_PIX_FMT_YUVA420P: + return FFMpegAVFramePixelFormatYUVA; + default: + return FFMpegAVFramePixelFormatYUV; + } +} + @end diff --git a/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift b/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift index 83e84af1f3..22b1b863e0 100644 --- a/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift +++ b/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift @@ -258,6 +258,17 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { } var pixelBufferRef: CVPixelBuffer? + + let pixelFormat: OSType + switch frame.pixelFormat { + case .YUV: + pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange + case .YUVA: + pixelFormat = kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanar + default: + pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange + } + if let pixelBufferPool = self.pixelBufferPool { let auxAttributes: [String: Any] = [kCVPixelBufferPoolAllocationThresholdKey as String: bufferCount as NSNumber]; let err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, pixelBufferPool, auxAttributes as CFDictionary, &pixelBufferRef) @@ -271,55 +282,55 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { var options: [String: Any] = [kCVPixelBufferBytesPerRowAlignmentKey as String: frame.lineSize[0] as NSNumber] options[kCVPixelBufferIOSurfacePropertiesKey as String] = ioSurfaceProperties - + CVPixelBufferCreate(kCFAllocatorDefault, Int(frame.width), Int(frame.height), - kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, + pixelFormat, options as CFDictionary, &pixelBufferRef) } - + guard let pixelBuffer = pixelBufferRef else { return nil } - + let srcPlaneSize = Int(frame.lineSize[1]) * Int(frame.height / 2) let dstPlaneSize = srcPlaneSize * 2 - + let dstPlane = malloc(dstPlaneSize)!.assumingMemoryBound(to: UInt8.self) defer { free(dstPlane) } - + for i in 0 ..< srcPlaneSize { dstPlane[2 * i] = frame.data[1]![i] dstPlane[2 * i + 1] = frame.data[2]![i] } - + let status = CVPixelBufferLockBaseAddress(pixelBuffer, []) if status != kCVReturnSuccess { return nil } - - let bytePerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) - + + let bytesPerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) let bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1) - + let bytesPerRowA = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 2) + var base = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0)! - if bytePerRowY == frame.lineSize[0] { - memcpy(base, frame.data[0]!, bytePerRowY * Int(frame.height)) + if bytesPerRowY == frame.lineSize[0] { + memcpy(base, frame.data[0]!, bytesPerRowY * Int(frame.height)) } else { var dest = base var src = frame.data[0]! let linesize = Int(frame.lineSize[0]) for _ in 0 ..< Int(frame.height) { memcpy(dest, src, linesize) - dest = dest.advanced(by: bytePerRowY) + dest = dest.advanced(by: bytesPerRowY) src = src.advanced(by: linesize) } } - + base = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1)! if bytesPerRowUV == frame.lineSize[1] * 2 { memcpy(base, dstPlane, Int(frame.height / 2) * bytesPerRowUV) @@ -333,7 +344,23 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { src = src.advanced(by: linesize) } } - + + if case .YUVA = frame.pixelFormat { + base = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 2)! + if bytesPerRowA == frame.lineSize[3] { + memcpy(base, frame.data[3]!, bytesPerRowA * Int(frame.height)) + } else { + var dest = base + var src = frame.data[3]! + let linesize = Int(frame.lineSize[3]) + for _ in 0 ..< Int(frame.height) { + memcpy(dest, src, linesize) + dest = dest.advanced(by: bytesPerRowA) + src = src.advanced(by: linesize) + } + } + } + CVPixelBufferUnlockBaseAddress(pixelBuffer, []) var formatRef: CMVideoFormatDescription? diff --git a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift index 1e3ac2a531..16ece5bc68 100644 --- a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift +++ b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift @@ -57,7 +57,7 @@ public final class SoftwareVideoSource { private var enqueuedFrames: [(MediaTrackFrame, CGFloat, CGFloat, Bool)] = [] private var hasReadToEnd: Bool = false - public init(path: String) { + public init(path: String, hintVP9: Bool) { let _ = FFMpegMediaFrameSourceContextHelpers.registerFFMpegGlobals var s = stat() @@ -74,7 +74,9 @@ public final class SoftwareVideoSource { self.path = path let avFormatContext = FFMpegAVFormatContext() - + if hintVP9 { + avFormatContext.forceVideoCodecId(FFMpegCodecIdVP9) + } let ioBufferSize = 64 * 1024 let avIoContext = FFMpegAVIOContext(bufferSize: Int32(ioBufferSize), opaqueContext: Unmanaged.passUnretained(self).toOpaque(), readPacket: readPacketCallback, writePacket: nil, seek: seekCallback) diff --git a/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift b/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift index 7317f7fb2e..8bd13e88f8 100644 --- a/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift +++ b/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift @@ -111,7 +111,7 @@ private final class UniversalSoftwareVideoSourceImpl { fileprivate var currentNumberOfReads: Int = 0 fileprivate var currentReadBytes: Int = 0 - init?(mediaBox: MediaBox, fileReference: FileMediaReference, state: ValuePromise, cancelInitialization: Signal, automaticallyFetchHeader: Bool) { + init?(mediaBox: MediaBox, fileReference: FileMediaReference, state: ValuePromise, cancelInitialization: Signal, automaticallyFetchHeader: Bool, hintVP9: Bool = false) { guard let size = fileReference.media.size else { return nil } @@ -134,6 +134,9 @@ private final class UniversalSoftwareVideoSourceImpl { self.avIoContext = avIoContext let avFormatContext = FFMpegAVFormatContext() + if hintVP9 { + avFormatContext.forceVideoCodecId(FFMpegCodecIdVP9) + } avFormatContext.setIO(avIoContext) if !avFormatContext.openInput() { @@ -286,19 +289,22 @@ private final class UniversalSoftwareVideoSourceThreadParams: NSObject { let state: ValuePromise let cancelInitialization: Signal let automaticallyFetchHeader: Bool + let hintVP9: Bool init( mediaBox: MediaBox, fileReference: FileMediaReference, state: ValuePromise, cancelInitialization: Signal, - automaticallyFetchHeader: Bool + automaticallyFetchHeader: Bool, + hintVP9: Bool ) { self.mediaBox = mediaBox self.fileReference = fileReference self.state = state self.cancelInitialization = cancelInitialization self.automaticallyFetchHeader = automaticallyFetchHeader + self.hintVP9 = hintVP9 } } @@ -381,8 +387,8 @@ public final class UniversalSoftwareVideoSource { } } - public init(mediaBox: MediaBox, fileReference: FileMediaReference, automaticallyFetchHeader: Bool = false) { - self.thread = Thread(target: UniversalSoftwareVideoSourceThread.self, selector: #selector(UniversalSoftwareVideoSourceThread.entryPoint(_:)), object: UniversalSoftwareVideoSourceThreadParams(mediaBox: mediaBox, fileReference: fileReference, state: self.stateValue, cancelInitialization: self.cancelInitialization.get(), automaticallyFetchHeader: automaticallyFetchHeader)) + public init(mediaBox: MediaBox, fileReference: FileMediaReference, automaticallyFetchHeader: Bool = false, hintVP9: Bool = false) { + self.thread = Thread(target: UniversalSoftwareVideoSourceThread.self, selector: #selector(UniversalSoftwareVideoSourceThread.entryPoint(_:)), object: UniversalSoftwareVideoSourceThreadParams(mediaBox: mediaBox, fileReference: fileReference, state: self.stateValue, cancelInitialization: self.cancelInitialization.get(), automaticallyFetchHeader: automaticallyFetchHeader, hintVP9: hintVP9)) self.thread.name = "UniversalSoftwareVideoSource" self.thread.start() } diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index b635febb2d..2937ace7e5 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1,5 +1,6 @@ import Foundation import UIKit +import AVFoundation import AsyncDisplayKit import Display import SwiftSignalKit @@ -53,6 +54,34 @@ extension SlotMachineAnimationNode: GenericAnimatedStickerNode { } } +private class VideoStickerNode: ASDisplayNode, GenericAnimatedStickerNode { + private var layerHolder: SampleBufferLayer? + var manager: SoftwareVideoLayerFrameManager? + + func setOverlayColor(_ color: UIColor?, animated: Bool) { + + } + + func update(context: AccountContext, fileReference: FileMediaReference, size: CGSize) { + let layerHolder = takeSampleBufferLayer() + layerHolder.layer.videoGravity = AVLayerVideoGravity.resizeAspectFill + layerHolder.layer.frame = CGRect(origin: CGPoint(), size: size) + self.layer.addSublayer(layerHolder.layer) + self.layerHolder = layerHolder + + let manager = SoftwareVideoLayerFrameManager(account: context.account, fileReference: fileReference, layerHolder: layerHolder, hintVP9: true) + self.manager = manager + manager.start() + } + + var currentFrameIndex: Int { + return 0 + } + + func setFrameIndex(_ frameIndex: Int) { + } +} + class ChatMessageShareButton: HighlightableButtonNode { private let backgroundNode: NavigationBackgroundNode private let iconNode: ASImageNode @@ -172,6 +201,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { private var didSetUpAnimationNode = false private var isPlaying = false + private var displayLink: ConstantDisplayLinkAnimator? + private var displayLinkTimestamp: Double = 0.0 + private var additionalAnimationNodes: [ChatMessageTransitionNode.DecorationItemNode] = [] private var overlayMeshAnimationNode: ChatMessageTransitionNode.DecorationItemNode? private var enqueuedAdditionalAnimations: [(Int, Double)] = [] @@ -432,6 +464,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } self.animationNode = animationNode } + } else if let telegramFile = self.telegramFile, let fileName = telegramFile.fileName, fileName.hasSuffix(".webm") { + let videoNode = VideoStickerNode() + videoNode.update(context: item.context, fileReference: .standalone(media: telegramFile), size: CGSize(width: 184.0, height: 184.0)) + self.animationNode = videoNode } else { let animationNode = AnimatedStickerNode() animationNode.started = { [weak self] in @@ -548,7 +584,24 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { return } - if let animationNode = self.animationNode as? AnimatedStickerNode { + let isPlaying = self.visibilityStatus && !self.forceStopAnimations + if let _ = self.animationNode as? VideoStickerNode { + let displayLink: ConstantDisplayLinkAnimator + if let current = self.displayLink { + displayLink = current + } else { + displayLink = ConstantDisplayLinkAnimator { [weak self] in + guard let strongSelf = self, let animationNode = strongSelf.animationNode as? VideoStickerNode else { + return + } + animationNode.manager?.tick(timestamp: strongSelf.displayLinkTimestamp) + strongSelf.displayLinkTimestamp += 1.0 / 30.0 + } + displayLink.frameInterval = 2 + self.displayLink = displayLink + } + self.displayLink?.isPaused = !isPlaying + } else if let animationNode = self.animationNode as? AnimatedStickerNode { let isPlaying = self.visibilityStatus && !self.forceStopAnimations if !isPlaying { @@ -722,6 +775,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { imageSize = dimensions.cgSize.aspectFitted(displaySize) } else if let thumbnailSize = telegramFile.previewRepresentations.first?.dimensions { imageSize = thumbnailSize.cgSize.aspectFitted(displaySize) + } else { + imageSize = displaySize } } else if let emojiFile = emojiFile { isEmoji = true diff --git a/submodules/TelegramUI/Sources/ChatMessageItem.swift b/submodules/TelegramUI/Sources/ChatMessageItem.swift index a3ee2422ae..bcca9e881e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageItem.swift @@ -380,6 +380,10 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { loop: for media in self.message.media { if let telegramFile = media as? TelegramMediaFile { + if let fileName = telegramFile.fileName, fileName.hasSuffix(".webm") { + viewClassName = ChatMessageAnimatedStickerItemNode.self + break loop + } if telegramFile.isAnimatedSticker, let size = telegramFile.size, size > 0 && size <= 128 * 1024 { if self.message.id.peerId.namespace == Namespaces.Peer.SecretChat { if telegramFile.fileId.namespace == Namespaces.Media.CloudFile { diff --git a/submodules/TelegramUI/Sources/SoftwareVideoLayerFrameManager.swift b/submodules/TelegramUI/Sources/SoftwareVideoLayerFrameManager.swift index 007ddb0013..859da17ac8 100644 --- a/submodules/TelegramUI/Sources/SoftwareVideoLayerFrameManager.swift +++ b/submodules/TelegramUI/Sources/SoftwareVideoLayerFrameManager.swift @@ -14,6 +14,7 @@ final class SoftwareVideoLayerFrameManager { private let fetchDisposable: Disposable private var dataDisposable = MetaDisposable() private let source = Atomic(value: nil) + private let hintVP9: Bool private var baseTimestamp: Double? private var frames: [MediaTrackFrame] = [] @@ -31,7 +32,7 @@ final class SoftwareVideoLayerFrameManager { private var layerRotationAngleAndAspect: (CGFloat, CGFloat)? - init(account: Account, fileReference: FileMediaReference, layerHolder: SampleBufferLayer) { + init(account: Account, fileReference: FileMediaReference, layerHolder: SampleBufferLayer, hintVP9: Bool = false) { var resource = fileReference.media.resource var secondaryResource: MediaResource? for attribute in fileReference.media.attributes { @@ -46,6 +47,7 @@ final class SoftwareVideoLayerFrameManager { nextWorker += 1 self.account = account self.resource = resource + self.hintVP9 = hintVP9 self.secondaryResource = secondaryResource self.queue = ThreadPoolQueue(threadPool: workers) self.layerHolder = layerHolder @@ -108,7 +110,7 @@ final class SoftwareVideoLayerFrameManager { let size = fileSize(path) Logger.shared.log("SoftwareVideo", "loaded video from \(stringForResource(resource)) (file size: \(String(describing: size))") - let _ = strongSelf.source.swap(SoftwareVideoSource(path: path)) + let _ = strongSelf.source.swap(SoftwareVideoSource(path: path, hintVP9: strongSelf.hintVP9)) } })) } diff --git a/submodules/ffmpeg/BUILD b/submodules/ffmpeg/BUILD index 441192876b..f963d9e76f 100644 --- a/submodules/ffmpeg/BUILD +++ b/submodules/ffmpeg/BUILD @@ -120,6 +120,24 @@ filegroup( srcs = source_files, ) +vpx_headers = [ + "vp8.h", + "vp8cx.h", + "vp8dx.h", + "vpx_codec.h", + "vpx_decoder.h", + "vpx_encoder.h", + "vpx_frame_buffer.h", + "vpx_image.h", + "vpx_integer.h", + "vpx_version.h", + "vpx_ext_ratectrl.h", +] + +vpx_libs = [ + "VPX", +] + opus_headers = [ "opus.h", "opus_defines.h", @@ -136,6 +154,10 @@ genrule( name = "libffmpeg_build", srcs = [ ":FFMpegSources" + ] + [ + "//third-party/libvpx:Public/vpx/{}".format(x) for x in vpx_headers + ] + [ + "//third-party/libvpx:Public/vpx/lib{}.a".format(x) for x in vpx_libs ] + [ "//third-party/opus:Public/opus/{}".format(x) for x in opus_headers ] + [ @@ -153,6 +175,21 @@ genrule( cp -R "submodules/ffmpeg/Sources/FFMpeg" "$$SOURCE_PATH" + mkdir "$$SOURCE_PATH/libvpx" + mkdir -p "$$SOURCE_PATH/libvpx/include/vpx" + mkdir -p "$$SOURCE_PATH/libvpx/lib" + """ + + "\n" + + "\n".join([ + "cp $(location //third-party/libvpx:Public/vpx/{}) $$SOURCE_PATH/libvpx/include/vpx/".format(x) for x in vpx_headers + ]) + + "\n" + + "\n".join([ + "cp $(location //third-party/libvpx:Public/vpx/libVPX.a) $$SOURCE_PATH/libvpx/lib/".format(x) for x in vpx_libs + ]) + + "\n" + + """ + mkdir "$$SOURCE_PATH/libopus" mkdir -p "$$SOURCE_PATH/libopus/include/opus" mkdir -p "$$SOURCE_PATH/libopus/lib" @@ -231,6 +268,7 @@ objc_library( ], deps = [ ":ffmpeg_lib", + "//third-party/libvpx:vpx", "//third-party/opus:opus", ], visibility = [ diff --git a/submodules/ffmpeg/Sources/FFMpeg/build-ffmpeg-bazel.sh b/submodules/ffmpeg/Sources/FFMpeg/build-ffmpeg-bazel.sh index 3f2f119e19..50f4990e21 100755 --- a/submodules/ffmpeg/Sources/FFMpeg/build-ffmpeg-bazel.sh +++ b/submodules/ffmpeg/Sources/FFMpeg/build-ffmpeg-bazel.sh @@ -45,9 +45,10 @@ CONFIGURE_FLAGS="--enable-cross-compile --disable-programs \ --enable-avformat \ --disable-xlib \ --enable-libopus \ + --enable-libvpx \ --enable-audiotoolbox \ --enable-bsf=aac_adtstoasc \ - --enable-decoder=h264,hevc,libopus,mp3,aac,flac,alac_at,pcm_s16le,pcm_s24le,gsm_ms_at \ + --enable-decoder=h264,libvpx_vp9,hevc,libopus,mp3,aac,flac,alac_at,pcm_s16le,pcm_s24le,gsm_ms_at \ --enable-demuxer=aac,mov,m4v,mp3,ogg,libopus,flac,wav,aiff,matroska \ --enable-parser=aac,h264,mp3,libopus \ --enable-protocol=file \ @@ -122,6 +123,7 @@ then pushd "$SCRATCH/$RAW_ARCH" LIBOPUS_PATH="$SOURCE_DIR/libopus" + LIBVPX_PATH="$SOURCE_DIR/libvpx" CFLAGS="$EXTRA_CFLAGS -arch $ARCH" if [ "$RAW_ARCH" = "i386" -o "$RAW_ARCH" = "x86_64" ] @@ -174,7 +176,7 @@ then --extra-ldflags="$LDFLAGS" \ --prefix="$THIN/$RAW_ARCH" \ --pkg-config="$PKG_CONFIG" \ - --pkg-config-flags="--libopus_path $LIBOPUS_PATH" \ + --pkg-config-flags="--libopus_path $LIBOPUS_PATH --libvpx_path $LIBVPX_PATH" \ || exit 1 echo "$CONFIGURE_FLAGS" > "$CONFIGURED_MARKER" fi diff --git a/submodules/ffmpeg/Sources/FFMpeg/pkg-config b/submodules/ffmpeg/Sources/FFMpeg/pkg-config index 8454d47d24..528dec7f26 100755 --- a/submodules/ffmpeg/Sources/FFMpeg/pkg-config +++ b/submodules/ffmpeg/Sources/FFMpeg/pkg-config @@ -14,6 +14,8 @@ elif [ "$1" == "--exists" ]; then exit 0 elif [ "$NAME" == "opus" ]; then exit 0 + elif [ "$NAME" == "vpx" ]; then + exit 0 else if [ "PRINT_ERRORS" == "1" ]; then echo "Package $NAME was not found in the pkg-config search path." @@ -25,9 +27,15 @@ elif [ "$1" == "--exists" ]; then elif [ "$1" == "--cflags" ]; then NAME="$2" LIBOPUS_PATH="" + LIBVPX_PATH="" if [ "$2" == "--libopus_path" ]; then LIBOPUS_PATH="$3" - NAME="$4" + NAME="$6" + else + exit 1 + fi + if [ "$4" == "--libvpx_path" ]; then + LIBVPX_PATH="$5" else exit 1 fi @@ -37,15 +45,24 @@ elif [ "$1" == "--cflags" ]; then elif [ "$NAME" == "opus" ]; then echo "-I$LIBOPUS_PATH/include/opus" exit 0 + elif [ "$NAME" == "vpx" ]; then + echo "-I$LIBVPX_PATH/include" + exit 0 else exit 1 fi elif [ "$1" == "--libs" ]; then NAME="$2" LIBOPUS_PATH="" + LIBVPX_PATH="" if [ "$2" == "--libopus_path" ]; then LIBOPUS_PATH="$3" - NAME="$4" + NAME="$6" + else + exit 1 + fi + if [ "$4" == "--libvpx_path" ]; then + LIBVPX_PATH="$5" else exit 1 fi @@ -55,6 +72,9 @@ elif [ "$1" == "--libs" ]; then elif [ "$NAME" == "opus" ]; then echo "-L$LIBOPUS_PATH/lib -lopus" exit 0 + elif [ "$NAME" == "vpx" ]; then + echo "-L$LIBVPX_PATH/lib -lVPX" + exit 0 else exit 1 fi