Merge commit 'eb480074fd2c8af22080fcbf98ed3f013787b473' into features/64-bit

This commit is contained in:
Ali 2021-07-01 18:22:08 +04:00
commit 645686b2a6
444 changed files with 158761 additions and 3388 deletions

View File

@ -5,6 +5,7 @@ import TelegramVoip
import SwiftSignalKit
import BuildConfig
import BroadcastUploadHelpers
import AudioToolbox
private func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
@ -12,22 +13,11 @@ private func rootPathForBasePath(_ appGroupPath: String) -> String {
@available(iOS 10.0, *)
@objc(BroadcastUploadSampleHandler) class BroadcastUploadSampleHandler: RPBroadcastSampleHandler {
/*private var ipcContext: IpcGroupCallBroadcastContext?
private var callContext: OngoingGroupCallContext?
private var videoCapturer: OngoingCallVideoCapturer?
private var requestDisposable: Disposable?
private var joinPayloadDisposable: Disposable?
private var joinResponsePayloadDisposable: Disposable?*/
private var screencastBufferClientContext: IpcGroupCallBufferBroadcastContext?
private var statusDisposable: Disposable?
private var audioConverter: CustomAudioConverter?
deinit {
/*self.requestDisposable?.dispose()
self.joinPayloadDisposable?.dispose()
self.joinResponsePayloadDisposable?.dispose()
self.callContext?.stop()*/
self.statusDisposable?.dispose()
}
@ -55,6 +45,7 @@ private func rootPathForBasePath(_ appGroupPath: String) -> String {
}
}
override public func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
guard let appBundleIdentifier = Bundle.main.bundleIdentifier, let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
self.finish(with: .error)
@ -89,57 +80,8 @@ private func rootPathForBasePath(_ appGroupPath: String) -> String {
strongSelf.finish(with: reason)
}
})
/*let ipcContext = IpcGroupCallBroadcastContext(basePath: rootPath + "/broadcast-coordination")
self.ipcContext = ipcContext
self.requestDisposable = (ipcContext.request
|> timeout(3.0, queue: .mainQueue(), alternate: .single(.failed))
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] request in
guard let strongSelf = self else {
return
}
switch request {
case .request:
strongSelf.beginWithRequest()
case .failed:
strongSelf.finishWithGenericError()
}
})*/
}
/*private func beginWithRequest() {
let videoCapturer = OngoingCallVideoCapturer(isCustom: true)
self.videoCapturer = videoCapturer
let callContext = OngoingGroupCallContext(video: videoCapturer, requestMediaChannelDescriptions: { _, _ in return EmptyDisposable }, audioStreamData: nil, rejoinNeeded: {
}, outgoingAudioBitrateKbit: nil, videoContentType: .screencast, enableNoiseSuppression: false)
self.callContext = callContext
self.joinPayloadDisposable = (callContext.joinPayload
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] joinPayload in
guard let strongSelf = self, let ipcContext = strongSelf.ipcContext else {
return
}
ipcContext.setJoinPayload(joinPayload.0)
strongSelf.joinResponsePayloadDisposable = (ipcContext.joinResponsePayload
|> take(1)
|> deliverOnMainQueue).start(next: { joinResponsePayload in
guard let strongSelf = self, let callContext = strongSelf.callContext, let ipcContext = strongSelf.ipcContext else {
return
}
callContext.setConnectionMode(.rtc, keepBroadcastConnectedIfWasEnabled: false)
callContext.setJoinResponse(payload: joinResponsePayload)
ipcContext.beginActiveIndication()
})
})
}*/
override public func broadcastPaused() {
}
@ -154,7 +96,7 @@ private func rootPathForBasePath(_ appGroupPath: String) -> String {
case RPSampleBufferType.video:
processVideoSampleBuffer(sampleBuffer: sampleBuffer)
case RPSampleBufferType.audioApp:
break
processAudioSampleBuffer(sampleBuffer: sampleBuffer)
case RPSampleBufferType.audioMic:
break
@unknown default:
@ -175,25 +117,166 @@ private func rootPathForBasePath(_ appGroupPath: String) -> String {
if let data = serializePixelBuffer(buffer: pixelBuffer) {
self.screencastBufferClientContext?.setCurrentFrame(data: data, orientation: orientation)
}
}
//self.videoCapturer?.injectSampleBuffer(sampleBuffer)
/*if CMSampleBufferGetNumSamples(sampleBuffer) != 1 {
private func processAudioSampleBuffer(sampleBuffer: CMSampleBuffer) {
guard let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) else {
return
}
if !CMSampleBufferIsValid(sampleBuffer) {
guard let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription) else {
return
}
if !CMSampleBufferDataIsReady(sampleBuffer) {
/*guard let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else {
return
}*/
let format = CustomAudioConverter.Format(
numChannels: Int(asbd.pointee.mChannelsPerFrame),
sampleRate: Int(asbd.pointee.mSampleRate)
)
if self.audioConverter?.format != format {
self.audioConverter = CustomAudioConverter(asbd: asbd)
}
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
if let audioConverter = self.audioConverter {
if let data = audioConverter.convert(sampleBuffer: sampleBuffer) {
self.screencastBufferClientContext?.writeAudioData(data: data)
}
}
let pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)
CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly)*/
}
}
private final class CustomAudioConverter {
struct Format: Equatable {
let numChannels: Int
let sampleRate: Int
}
let format: Format
var currentInputDescription: UnsafePointer<AudioStreamBasicDescription>?
var currentBuffer: AudioBuffer?
var currentBufferOffset: UInt32 = 0
init(asbd: UnsafePointer<AudioStreamBasicDescription>) {
self.format = Format(
numChannels: Int(asbd.pointee.mChannelsPerFrame),
sampleRate: Int(asbd.pointee.mSampleRate)
)
}
func convert(sampleBuffer: CMSampleBuffer) -> Data? {
guard let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) else {
return nil
}
guard let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription) else {
return nil
}
var bufferList = AudioBufferList()
var blockBuffer: CMBlockBuffer? = nil
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
bufferListSizeNeededOut: nil,
bufferListOut: &bufferList,
bufferListSize: MemoryLayout<AudioBufferList>.size,
blockBufferAllocator: nil,
blockBufferMemoryAllocator: nil,
flags: kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
blockBufferOut: &blockBuffer
)
let size = bufferList.mBuffers.mDataByteSize
guard size != 0, let mData = bufferList.mBuffers.mData else {
return nil
}
var outputDescription = AudioStreamBasicDescription(
mSampleRate: 48000.0,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked,
mBytesPerPacket: 2,
mFramesPerPacket: 1,
mBytesPerFrame: 2,
mChannelsPerFrame: 1,
mBitsPerChannel: 16,
mReserved: 0
)
var maybeAudioConverter: AudioConverterRef?
let _ = AudioConverterNew(asbd, &outputDescription, &maybeAudioConverter)
guard let audioConverter = maybeAudioConverter else {
return nil
}
self.currentBuffer = AudioBuffer(
mNumberChannels: asbd.pointee.mChannelsPerFrame,
mDataByteSize: UInt32(size),
mData: mData
)
self.currentBufferOffset = 0
self.currentInputDescription = asbd
var numPackets: UInt32?
let outputSize = 32768 * 2
var outputBuffer = Data(count: outputSize)
outputBuffer.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) -> Void in
var outputBufferList = AudioBufferList()
outputBufferList.mNumberBuffers = 1
outputBufferList.mBuffers.mNumberChannels = outputDescription.mChannelsPerFrame
outputBufferList.mBuffers.mDataByteSize = UInt32(outputSize)
outputBufferList.mBuffers.mData = outputBytes.baseAddress!
var outputDataPacketSize = UInt32(outputSize) / outputDescription.mBytesPerPacket
let result = AudioConverterFillComplexBuffer(
audioConverter,
converterComplexInputDataProc,
Unmanaged.passUnretained(self).toOpaque(),
&outputDataPacketSize,
&outputBufferList,
nil
)
if result == noErr {
numPackets = outputDataPacketSize
}
}
AudioConverterDispose(audioConverter)
if let numPackets = numPackets {
outputBuffer.count = Int(numPackets * outputDescription.mBytesPerPacket)
return outputBuffer
} else {
return nil
}
}
}
private func converterComplexInputDataProc(inAudioConverter: AudioConverterRef, ioNumberDataPackets: UnsafeMutablePointer<UInt32>, ioData: UnsafeMutablePointer<AudioBufferList>, ioDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>?>?, inUserData: UnsafeMutableRawPointer?) -> Int32 {
guard let inUserData = inUserData else {
ioNumberDataPackets.pointee = 0
return 0
}
let instance = Unmanaged<CustomAudioConverter>.fromOpaque(inUserData).takeUnretainedValue()
guard let currentBuffer = instance.currentBuffer else {
ioNumberDataPackets.pointee = 0
return 0
}
guard let currentInputDescription = instance.currentInputDescription else {
ioNumberDataPackets.pointee = 0
return 0
}
let numPacketsInBuffer = currentBuffer.mDataByteSize / currentInputDescription.pointee.mBytesPerPacket
let numPacketsAvailable = numPacketsInBuffer - instance.currentBufferOffset / currentInputDescription.pointee.mBytesPerPacket
let numPacketsToRead = min(ioNumberDataPackets.pointee, numPacketsAvailable)
ioNumberDataPackets.pointee = numPacketsToRead
ioData.pointee.mNumberBuffers = 1
ioData.pointee.mBuffers.mData = currentBuffer.mData?.advanced(by: Int(instance.currentBufferOffset))
ioData.pointee.mBuffers.mDataByteSize = currentBuffer.mDataByteSize - instance.currentBufferOffset
ioData.pointee.mBuffers.mNumberChannels = currentBuffer.mNumberChannels
instance.currentBufferOffset += numPacketsToRead * currentInputDescription.pointee.mBytesPerPacket
return 0
}

View File

@ -6504,6 +6504,9 @@ Sorry for the inconvenience.";
"ImportStickerPack.StickerCount_many" = "%@ Stickers";
"ImportStickerPack.StickerCount_0" = "%@ Stickers";
"ImportStickerPack.CreateStickerSet" = "Create Sticker Set";
"ImportStickerPack.CreateNewStickerSet" = "Create a New Sticker Set";
"ImportStickerPack.AddToExistingStickerSet" = "Add to an Existing Sticker Set";
"ImportStickerPack.ChooseStickerSet" = "Choose Sticker Set";
"ImportStickerPack.RemoveFromImport" = "Remove From Import";
"ImportStickerPack.ChooseName" = "Choose Name";
"ImportStickerPack.ChooseNameDescription" = "Please choose a name for your set.";
@ -6524,7 +6527,6 @@ Sorry for the inconvenience.";
"Conversation.InputMenu" = "Menu";
"Conversation.MessageDoesntExist" = "Message doesn't exist";
"Settings.CheckPasswordTitle" = "Is %@ still your number?";
"Settings.CheckPasswordText" = "Your account is protected by 2-Step Verification. Do you still remember your password?";
"Settings.KeepPassword" = "Yes, definitely";
"Settings.TryEnterPassword" = "Not sure, let me try";

View File

@ -57,6 +57,7 @@ public final class PeerSelectionControllerParams {
public protocol PeerSelectionController: ViewController {
var peerSelected: ((Peer) -> Void)? { get set }
var multiplePeersSelected: (([Peer], NSAttributedString) -> Void)? { get set }
var inProgress: Bool { get set }
var customDismiss: (() -> Void)? { get set }
}

View File

@ -30,6 +30,7 @@ import InstantPageUI
import ChatInterfaceState
import ShareController
import UndoUI
import TextFormat
private enum ChatListTokenId: Int32 {
case filter
@ -107,6 +108,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
private var suggestedFilters: [ChatListSearchFilter]?
private let suggestedFiltersDisposable = MetaDisposable()
private var shareStatusDisposable: MetaDisposable?
private var stateValue = ChatListSearchContainerNodeSearchState()
private let statePromise = ValuePromise<ChatListSearchContainerNodeSearchState>()
@ -415,6 +418,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
self.activeActionDisposable.dispose()
self.presentationDataDisposable?.dispose()
self.suggestedFiltersDisposable.dispose()
self.shareStatusDisposable?.dispose()
}
private func updateState(_ f: (ChatListSearchContainerNodeSearchState) -> ChatListSearchContainerNodeSearchState) {
@ -902,7 +906,83 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
}).start()
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled]))
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText in
guard let strongSelf = self, let strongController = peerSelectionController else {
return
}
strongController.dismiss()
for peer in peers {
var result: [EnqueueMessage] = []
if messageText.string.count > 0 {
let inputText = convertMarkdownToAttributes(messageText)
for text in breakChatInputText(trimChatInputText(inputText)) {
if text.length != 0 {
var attributes: [MessageAttribute] = []
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
}
}
}
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
})
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|> deliverOnMainQueue).start(next: { messageIds in
if let strongSelf = self {
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
guard let id = id else {
return nil
}
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
if status != nil {
return .never()
} else {
return .single(true)
}
}
|> take(1)
})
if strongSelf.shareStatusDisposable == nil {
strongSelf.shareStatusDisposable = MetaDisposable()
}
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|> deliverOnMainQueue).start())
}
})
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peers.count == 1, let peerId = peers.first?.id, peerId == strongSelf.context.account.peerId {
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
} else {
text = ""
}
}
(strongSelf.navigationController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
}
peerSelectionController.peerSelected = { [weak self, weak peerSelectionController] peer in
let peerId = peer.id
if let strongSelf = self, let _ = peerSelectionController {

View File

@ -773,9 +773,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
guard let item = self.item, item.editing else {
return
}
if case let .peer(_, _, _, _, _, _, _, _, promoInfo, _, _, _) = item.content {
if promoInfo == nil {
item.interaction.togglePeerSelected(item.index.messageIndex.id.peerId)
if case let .peer(_, peer, _, _, _, _, _, _, promoInfo, _, _, _) = item.content {
if promoInfo == nil, let mainPeer = peer.chatMainPeer {
item.interaction.togglePeerSelected(mainPeer)
}
}
}

View File

@ -51,7 +51,7 @@ public final class ChatListNodeInteraction {
let activateSearch: () -> Void
let peerSelected: (Peer, ChatListNodeEntryPromoInfo?) -> Void
let disabledPeerSelected: (Peer) -> Void
let togglePeerSelected: (PeerId) -> Void
let togglePeerSelected: (Peer) -> Void
let additionalCategorySelected: (Int) -> Void
let messageSelected: (Peer, Message, ChatListNodeEntryPromoInfo?) -> Void
let groupSelected: (PeerGroupId) -> Void
@ -70,7 +70,7 @@ public final class ChatListNodeInteraction {
public var searchTextHighightState: String?
var highlightedChatLocation: ChatListHighlightedLocation?
public init(activateSearch: @escaping () -> Void, peerSelected: @escaping (Peer, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (Peer) -> Void, togglePeerSelected: @escaping (PeerId) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (Peer, Message, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (PeerGroupId) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setItemPinned: @escaping (PinnedItemId, Bool) -> Void, setPeerMuted: @escaping (PeerId, Bool) -> Void, deletePeer: @escaping (PeerId, Bool) -> Void, updatePeerGrouping: @escaping (PeerId, Bool) -> Void, togglePeerMarkedUnread: @escaping (PeerId, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (PeerId) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) {
public init(activateSearch: @escaping () -> Void, peerSelected: @escaping (Peer, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (Peer) -> Void, togglePeerSelected: @escaping (Peer) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (Peer, Message, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (PeerGroupId) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setItemPinned: @escaping (PinnedItemId, Bool) -> Void, setPeerMuted: @escaping (PeerId, Bool) -> Void, deletePeer: @escaping (PeerId, Bool) -> Void, updatePeerGrouping: @escaping (PeerId, Bool) -> Void, togglePeerMarkedUnread: @escaping (PeerId, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (PeerId) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) {
self.activateSearch = activateSearch
self.peerSelected = peerSelected
self.disabledPeerSelected = disabledPeerSelected
@ -111,13 +111,17 @@ public struct ChatListNodeState: Equatable {
public var archiveShouldBeTemporaryRevealed: Bool
public var selectedAdditionalCategoryIds: Set<Int>
public var hiddenPsaPeerId: PeerId?
public var foundPeers: [Peer]
public var selectedPeerMap: [PeerId: Peer]
public init(presentationData: ChatListPresentationData, editing: Bool, peerIdWithRevealedOptions: PeerId?, selectedPeerIds: Set<PeerId>, selectedAdditionalCategoryIds: Set<Int>, peerInputActivities: ChatListNodePeerInputActivities?, pendingRemovalPeerIds: Set<PeerId>, pendingClearHistoryPeerIds: Set<PeerId>, archiveShouldBeTemporaryRevealed: Bool, hiddenPsaPeerId: PeerId?) {
public init(presentationData: ChatListPresentationData, editing: Bool, peerIdWithRevealedOptions: PeerId?, selectedPeerIds: Set<PeerId>, foundPeers: [Peer], selectedPeerMap: [PeerId: Peer], selectedAdditionalCategoryIds: Set<Int>, peerInputActivities: ChatListNodePeerInputActivities?, pendingRemovalPeerIds: Set<PeerId>, pendingClearHistoryPeerIds: Set<PeerId>, archiveShouldBeTemporaryRevealed: Bool, hiddenPsaPeerId: PeerId?) {
self.presentationData = presentationData
self.editing = editing
self.peerIdWithRevealedOptions = peerIdWithRevealedOptions
self.selectedPeerIds = selectedPeerIds
self.selectedAdditionalCategoryIds = selectedAdditionalCategoryIds
self.foundPeers = foundPeers
self.selectedPeerMap = selectedPeerMap
self.peerInputActivities = peerInputActivities
self.pendingRemovalPeerIds = pendingRemovalPeerIds
self.pendingClearHistoryPeerIds = pendingClearHistoryPeerIds
@ -138,6 +142,12 @@ public struct ChatListNodeState: Equatable {
if lhs.selectedPeerIds != rhs.selectedPeerIds {
return false
}
if arePeerArraysEqual(lhs.foundPeers, rhs.foundPeers) {
return false
}
if arePeerDictionariesEqual(lhs.selectedPeerMap, rhs.selectedPeerMap) {
return false
}
if lhs.selectedAdditionalCategoryIds != rhs.selectedAdditionalCategoryIds {
return false
}
@ -283,7 +293,11 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: status, enabled: enabled, selection: editing ? .selectable(selected: selected) : .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
if let chatPeer = chatPeer {
nodeInteraction.peerSelected(chatPeer, nil)
if editing {
nodeInteraction.togglePeerSelected(chatPeer)
} else {
nodeInteraction.peerSelected(chatPeer, nil)
}
}
}, disabledAction: { _ in
if let chatPeer = chatPeer {
@ -360,7 +374,11 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: status, enabled: enabled, selection: editing ? .selectable(selected: selected) : .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
if let chatPeer = chatPeer {
nodeInteraction.peerSelected(chatPeer, nil)
if editing {
nodeInteraction.togglePeerSelected(chatPeer)
} else {
nodeInteraction.peerSelected(chatPeer, nil)
}
}
}, disabledAction: { _ in
if let chatPeer = chatPeer {
@ -545,6 +563,7 @@ public final class ChatListNode: ListView {
let preloadItems = Promise<[ChatHistoryPreloadItem]>([])
var didBeginSelectingChats: (() -> Void)?
public var selectionCountChanged: ((Int) -> Void)?
public init(context: AccountContext, groupId: PeerGroupId, chatListFilter: ChatListFilter? = nil, previewing: Bool, fillPreloadItems: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
self.context = context
@ -559,7 +578,7 @@ public final class ChatListNode: ListView {
isSelecting = true
}
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: isSelecting, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), selectedAdditionalCategoryIds: Set(), peerInputActivities: nil, pendingRemovalPeerIds: Set(), pendingClearHistoryPeerIds: Set(), archiveShouldBeTemporaryRevealed: false, hiddenPsaPeerId: nil)
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: isSelecting, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), foundPeers: [], selectedPeerMap: [:], selectedAdditionalCategoryIds: Set(), peerInputActivities: nil, pendingRemovalPeerIds: Set(), pendingClearHistoryPeerIds: Set(), archiveShouldBeTemporaryRevealed: false, hiddenPsaPeerId: nil)
self.statePromise = ValuePromise(self.currentState, ignoreRepeated: true)
self.theme = theme
@ -583,22 +602,26 @@ public final class ChatListNode: ListView {
if let strongSelf = self, let disabledPeerSelected = strongSelf.disabledPeerSelected {
disabledPeerSelected(peer)
}
}, togglePeerSelected: { [weak self] peerId in
}, togglePeerSelected: { [weak self] peer in
var didBeginSelecting = false
var count = 0
self?.updateState { state in
var state = state
if state.selectedPeerIds.contains(peerId) {
state.selectedPeerIds.remove(peerId)
if state.selectedPeerIds.contains(peer.id) {
state.selectedPeerIds.remove(peer.id)
} else {
if state.selectedPeerIds.count < 100 {
if state.selectedPeerIds.isEmpty {
didBeginSelecting = true
}
state.selectedPeerIds.insert(peerId)
state.selectedPeerIds.insert(peer.id)
state.selectedPeerMap[peer.id] = peer
}
}
count = state.selectedPeerIds.count
return state
}
self?.selectionCountChanged?(count)
if didBeginSelecting {
self?.didBeginSelectingChats?()
}
@ -772,7 +795,7 @@ public final class ChatListNode: ListView {
let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault)
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.view, state: state, savedMessagesPeer: savedMessagesPeer, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, mode: mode)
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.view, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, mode: mode)
let entries = rawEntries.filter { entry in
switch entry {
case let .PeerEntry(_, _, _, _, _, _, peer, _, _, _, _, _, _, _, _, _):

View File

@ -282,7 +282,7 @@ private func offsetPinnedIndex(_ index: ChatListIndex, offset: UInt16) -> ChatLi
}
}
func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, savedMessagesPeer: Peer?, hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, mode: ChatListNodeMode) -> (entries: [ChatListNodeEntry], loading: Bool) {
func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, savedMessagesPeer: Peer?, foundPeers: [Peer], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, mode: ChatListNodeMode) -> (entries: [ChatListNodeEntry], loading: Bool) {
var result: [ChatListNodeEntry] = []
var pinnedIndexOffset: UInt16 = 0
@ -299,6 +299,11 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
return item.info.peerId != state.hiddenPsaPeerId
}
var foundPeerIds = Set<PeerId>()
for peer in foundPeers {
foundPeerIds.insert(peer.id)
}
if view.laterIndex == nil && savedMessagesPeer == nil {
pinnedIndexOffset += UInt16(filteredAdditionalItemEntries.count)
}
@ -306,7 +311,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
loop: for entry in view.entries {
switch entry {
case let .MessageEntry(index, messages, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
if let savedMessagesPeer = savedMessagesPeer, savedMessagesPeer.id == index.messageIndex.id.peerId {
if let savedMessagesPeer = savedMessagesPeer, savedMessagesPeer.id == index.messageIndex.id.peerId || foundPeerIds.contains(index.messageIndex.id.peerId) {
continue loop
}
if state.pendingRemovalPeerIds.contains(index.messageIndex.id.peerId) {
@ -331,6 +336,17 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1))
if let savedMessagesPeer = savedMessagesPeer {
if !foundPeers.isEmpty {
var foundPinningIndex: UInt16 = UInt16(foundPeers.count)
for peer in foundPeers.reversed() {
let messageIndex = MessageIndex(id: MessageId(peerId: peer.id, namespace: 0, id: 0), timestamp: 1)
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: foundPinningIndex, messageIndex: messageIndex), presentationData: state.presentationData, messages: [], readState: nil, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: peer.id, peers: SimpleDictionary([peer.id: peer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: state.selectedPeerIds.contains(peer.id), inputActivities: nil, promoInfo: nil, hasFailedMessages: false, isContact: false))
if foundPinningIndex != 0 {
foundPinningIndex -= 1
}
}
}
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, messages: [], readState: nil, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, promoInfo: nil, hasFailedMessages: false, isContact: false))
} else {
if !filteredAdditionalItemEntries.isEmpty {

View File

@ -874,11 +874,14 @@ public final class ContactListNode: ASDisplayNode {
private var authorizationNode: PermissionContentNode
private let displayPermissionPlaceholder: Bool
public var multipleSelection = false
public init(context: AccountContext, presentation: Signal<ContactListPresentation, NoError>, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) {
self.context = context
self.filters = filters
self.displayPermissionPlaceholder = displayPermissionPlaceholder
self.contextAction = contextAction
self.multipleSelection = multipleSelection
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.presentationData = presentationData

View File

@ -69,8 +69,10 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
private let contentContainerNode: ASDisplayNode
private let contentBackgroundNode: ASImageNode
private let contentGridNode: GridNode
private let installActionButtonNode: ASButtonNode
private let installActionSeparatorNode: ASDisplayNode
private let createActionButtonNode: ASButtonNode
private let createActionSeparatorNode: ASDisplayNode
private let addToExistingActionButtonNode: ASButtonNode
private let addToExistingActionSeparatorNode: ASDisplayNode
private let contentTitleNode: ImmediateTextNode
private let contentSeparatorNode: ASDisplayNode
@ -128,9 +130,13 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.contentGridNode = GridNode()
self.installActionButtonNode = HighlightTrackingButtonNode()
self.installActionButtonNode.displaysAsynchronously = false
self.installActionButtonNode.titleNode.displaysAsynchronously = false
self.createActionButtonNode = HighlightTrackingButtonNode()
self.createActionButtonNode.displaysAsynchronously = false
self.createActionButtonNode.titleNode.displaysAsynchronously = false
self.addToExistingActionButtonNode = HighlightTrackingButtonNode()
self.addToExistingActionButtonNode.displaysAsynchronously = false
self.addToExistingActionButtonNode.titleNode.displaysAsynchronously = false
self.contentTitleNode = ImmediateTextNode()
self.contentTitleNode.displaysAsynchronously = false
@ -140,9 +146,13 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.contentSeparatorNode = ASDisplayNode()
self.contentSeparatorNode.isLayerBacked = true
self.installActionSeparatorNode = ASDisplayNode()
self.installActionSeparatorNode.isLayerBacked = true
self.installActionSeparatorNode.displaysAsynchronously = false
self.createActionSeparatorNode = ASDisplayNode()
self.createActionSeparatorNode.isLayerBacked = true
self.createActionSeparatorNode.displaysAsynchronously = false
self.addToExistingActionSeparatorNode = ASDisplayNode()
self.addToExistingActionSeparatorNode.isLayerBacked = true
self.addToExistingActionSeparatorNode.displaysAsynchronously = false
self.radialStatus = RadialStatusNode(backgroundNodeColor: .clear)
self.radialStatus.alpha = 0.0
@ -193,14 +203,17 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.wrappingScrollNode.addSubnode(self.cancelButtonNode)
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
self.installActionButtonNode.addTarget(self, action: #selector(self.installActionButtonPressed), forControlEvents: .touchUpInside)
self.createActionButtonNode.addTarget(self, action: #selector(self.createActionButtonPressed), forControlEvents: .touchUpInside)
self.addToExistingActionButtonNode.addTarget(self, action: #selector(self.addToExistingActionButtonPressed), forControlEvents: .touchUpInside)
self.wrappingScrollNode.addSubnode(self.contentBackgroundNode)
self.wrappingScrollNode.addSubnode(self.contentContainerNode)
self.contentContainerNode.addSubnode(self.contentGridNode)
self.contentContainerNode.addSubnode(self.installActionSeparatorNode)
self.contentContainerNode.addSubnode(self.installActionButtonNode)
self.contentContainerNode.addSubnode(self.createActionSeparatorNode)
self.contentContainerNode.addSubnode(self.createActionButtonNode)
self.contentContainerNode.addSubnode(self.addToExistingActionSeparatorNode)
self.contentContainerNode.addSubnode(self.addToExistingActionButtonNode)
self.wrappingScrollNode.addSubnode(self.contentTitleNode)
self.wrappingScrollNode.addSubnode(self.contentSeparatorNode)
@ -211,7 +224,8 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.wrappingScrollNode.addSubnode(self.progressText)
self.wrappingScrollNode.addSubnode(self.infoText)
self.installActionButtonNode.setTitle(self.presentationData.strings.ImportStickerPack_CreateStickerSet, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
self.createActionButtonNode.setTitle(self.presentationData.strings.ImportStickerPack_CreateNewStickerSet, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
self.addToExistingActionButtonNode.setTitle(self.presentationData.strings.ImportStickerPack_AddToExistingStickerSet, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
self.contentGridNode.presentationLayoutUpdated = { [weak self] presentationLayout, transition in
self?.gridPresentationLayoutUpdated(presentationLayout, transition: transition)
@ -283,6 +297,18 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.presentationData = presentationData
let theme = presentationData.theme
let solidBackground = generateImage(CGSize(width: 1.0, height: 1.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemBackgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
})?.stretchableImage(withLeftCapWidth: 16, topCapHeight: 1)
let highlightedSolidBackground = generateImage(CGSize(width: 1.0, height: 1.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemHighlightedBackgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
})?.stretchableImage(withLeftCapWidth: 16, topCapHeight: 1)
let halfRoundedBackground = generateImage(CGSize(width: 32.0, height: 32.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemBackgroundColor.cgColor)
@ -305,12 +331,21 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.cancelButtonNode.setBackgroundImage(roundedBackground, for: .normal)
self.cancelButtonNode.setBackgroundImage(highlightedRoundedBackground, for: .highlighted)
self.installActionButtonNode.setBackgroundImage(halfRoundedBackground, for: .normal)
self.installActionButtonNode.setBackgroundImage(highlightedHalfRoundedBackground, for: .highlighted)
if self.addToExistingActionButtonNode.supernode != nil {
self.createActionButtonNode.setBackgroundImage(solidBackground, for: .normal)
self.createActionButtonNode.setBackgroundImage(highlightedSolidBackground, for: .highlighted)
} else {
self.createActionButtonNode.setBackgroundImage(halfRoundedBackground, for: .normal)
self.createActionButtonNode.setBackgroundImage(highlightedHalfRoundedBackground, for: .highlighted)
}
self.addToExistingActionButtonNode.setBackgroundImage(halfRoundedBackground, for: .normal)
self.addToExistingActionButtonNode.setBackgroundImage(highlightedHalfRoundedBackground, for: .highlighted)
self.contentSeparatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor
self.installActionSeparatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor
self.createActionSeparatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor
self.addToExistingActionSeparatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor
self.cancelButtonNode.setTitle(presentationData.strings.Common_Cancel, with: Font.medium(20.0), with: presentationData.theme.actionSheet.standardActionTextColor, for: .normal)
self.contentTitleNode.linkHighlightColor = presentationData.theme.actionSheet.controlAccentColor.withAlphaComponent(0.5)
@ -330,6 +365,8 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
insets.top = max(10.0, insets.top)
let cleanInsets = layout.insets(options: [.statusBar])
let hasAddToExistingButton = self.addToExistingActionButtonNode.supernode != nil
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
var bottomInset: CGFloat = 10.0 + cleanInsets.bottom
@ -395,17 +432,20 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
let minimallyRevealedRowCount: CGFloat = 3.5
let initiallyRevealedRowCount = min(minimallyRevealedRowCount, CGFloat(rowCount))
var bottomGridInset = buttonHeight
var bottomGridInset = hasAddToExistingButton ? 2.0 * buttonHeight : buttonHeight
if let _ = self.progress {
bottomGridInset += 210.0
}
let topInset = max(0.0, contentFrame.size.height - initiallyRevealedRowCount * itemWidth - titleAreaHeight - bottomGridInset)
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
let installButtonOffset = buttonHeight
transition.updateFrame(node: self.installActionButtonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - installButtonOffset), size: CGSize(width: contentContainerFrame.size.width, height: buttonHeight)))
transition.updateFrame(node: self.installActionSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - installButtonOffset - UIScreenPixel), size: CGSize(width: contentContainerFrame.size.width, height: UIScreenPixel)))
let createButtonOffset = hasAddToExistingButton ? 2.0 * buttonHeight : buttonHeight
transition.updateFrame(node: self.createActionButtonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - createButtonOffset), size: CGSize(width: contentContainerFrame.size.width, height: buttonHeight)))
transition.updateFrame(node: self.createActionSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - createButtonOffset - UIScreenPixel), size: CGSize(width: contentContainerFrame.size.width, height: UIScreenPixel)))
transition.updateFrame(node: self.addToExistingActionButtonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - buttonHeight), size: CGSize(width: contentContainerFrame.size.width, height: buttonHeight)))
transition.updateFrame(node: self.addToExistingActionSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentContainerFrame.size.height - buttonHeight - UIScreenPixel), size: CGSize(width: contentContainerFrame.size.width, height: UIScreenPixel)))
let gridSize = CGSize(width: contentFrame.size.width, height: max(32.0, contentFrame.size.height - titleAreaHeight))
self.contentGridNode.transaction(GridNodeTransaction(deleteItems: transaction?.deletions ?? [], insertItems: transaction?.insertions ?? [], updateItems: transaction?.updates ?? [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: gridSize, insets: UIEdgeInsets(top: topInset, left: 0.0, bottom: bottomGridInset, right: 0.0), preloadSize: 80.0, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemWidth), fillWidth: nil, lineSpacing: 0.0, itemSpacing: nil)), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil), completion: { _ in })
@ -463,9 +503,11 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
transition.updateAlpha(node: self.infoText, alpha: 1.0)
transition.updateAlpha(node: self.radialCheck, alpha: 1.0)
transition.updateAlpha(node: self.radialStatusBackground, alpha: 1.0)
transition.updateAlpha(node: self.installActionButtonNode, alpha: 0.0)
transition.updateAlpha(node: self.createActionButtonNode, alpha: 0.0)
transition.updateAlpha(node: self.contentSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.installActionSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.createActionSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.addToExistingActionButtonNode, alpha: 0.0)
transition.updateAlpha(node: self.addToExistingActionSeparatorNode, alpha: 0.0)
}
self.radialStatusText.attributedText = NSAttributedString(string: "\(Int(effectiveProgress * 100.0))%", font: Font.with(size: floor(36.0 * maxK), design: .round, weight: .semibold), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
@ -660,7 +702,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}))
}
@objc func installActionButtonPressed() {
@objc private func createActionButtonPressed() {
var proceedImpl: ((String, String?) -> Void)?
let titleController = importStickerPackTitleController(context: self.context, title: self.presentationData.strings.ImportStickerPack_ChooseName, text: self.presentationData.strings.ImportStickerPack_ChooseNameDescription, placeholder: self.presentationData.strings.ImportStickerPack_NamePlaceholder, value: nil, maxLength: 128, apply: { [weak self] title in
if let strongSelf = self, let title = title {
@ -688,6 +730,10 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.present?(titleController, nil)
}
@objc private func addToExistingActionButtonPressed() {
}
func animateIn() {
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
@ -770,7 +816,8 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.contentGridNode.layer.animateAlpha(from: self.contentGridNode.alpha, to: 1.0, duration: 0.2)
let buttonTransition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)
buttonTransition.updateAlpha(node: self.installActionButtonNode, alpha: self.stickerPackReady ? 1.0 : 0.3)
buttonTransition.updateAlpha(node: self.createActionButtonNode, alpha: self.stickerPackReady ? 1.0 : 0.3)
buttonTransition.updateAlpha(node: self.addToExistingActionButtonNode, alpha: self.stickerPackReady ? 1.0 : 0.3)
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
@ -782,7 +829,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = self.installActionButtonNode.hitTest(self.installActionButtonNode.convert(point, from: self), with: event) {
if let result = self.createActionButtonNode.hitTest(self.createActionButtonNode.convert(point, from: self), with: event) {
return result
}
if self.bounds.contains(point) {

View File

@ -686,10 +686,10 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
var rightNavigationButton: ItemListNavigationButton?
var toolbarItem: ItemListToolbarItem?
if let packCount = packCount, packCount != 0 {
if case .modal = mode {
rightNavigationButton = nil
} else {
if state.editing {
if state.editing {
if case .modal = mode {
rightNavigationButton = nil
} else {
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
updateState {
$0.withUpdatedEditing(false).withUpdatedSelectedPackIds(nil)
@ -698,75 +698,97 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
dismissImpl?()
}
})
let selectedCount = Int32(state.selectedPackIds?.count ?? 0)
toolbarItem = StickersToolbarItem(selectedCount: selectedCount, actions: [.init(title: presentationData.strings.StickerPacks_ActionDelete, isEnabled: selectedCount > 0, action: {
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.StickerPacks_DeleteStickerPacksConfirmation(selectedCount), color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
}
let selectedCount = Int32(state.selectedPackIds?.count ?? 0)
toolbarItem = StickersToolbarItem(selectedCount: selectedCount, actions: [.init(title: presentationData.strings.StickerPacks_ActionDelete, isEnabled: selectedCount > 0, action: {
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.StickerPacks_DeleteStickerPacksConfirmation(selectedCount), color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if case .modal = mode {
updateState {
$0.withUpdatedEditing(true).withUpdatedSelectedPackIds(nil)
}
} else {
updateState {
$0.withUpdatedEditing(false).withUpdatedSelectedPackIds(nil)
}
var packIds: [ItemCollectionId] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
packIds.append(entry.id)
}
}
var packIds: [ItemCollectionId] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
packIds.append(entry.id)
}
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .delete).start()
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, nil)
}), .init(title: presentationData.strings.StickerPacks_ActionArchive, isEnabled: selectedCount > 0, action: {
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.StickerPacks_ArchiveStickerPacksConfirmation(selectedCount), color: .destructive, action: { [weak actionSheet] in
}
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .delete).start()
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, nil)
}), .init(title: presentationData.strings.StickerPacks_ActionArchive, isEnabled: selectedCount > 0, action: {
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.StickerPacks_ArchiveStickerPacksConfirmation(selectedCount), color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if case .modal = mode {
updateState {
$0.withUpdatedEditing(true).withUpdatedSelectedPackIds(nil)
}
} else {
updateState {
$0.withUpdatedEditing(false).withUpdatedSelectedPackIds(nil)
}
var packIds: [ItemCollectionId] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
packIds.append(entry.id)
}
}
var packIds: [ItemCollectionId] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
packIds.append(entry.id)
}
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .archive).start()
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, nil)
}), .init(title: presentationData.strings.StickerPacks_ActionShare, isEnabled: selectedCount > 0, action: {
}
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .archive).start()
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, nil)
}), .init(title: presentationData.strings.StickerPacks_ActionShare, isEnabled: selectedCount > 0, action: {
if case .modal = mode {
updateState {
$0.withUpdatedEditing(true).withUpdatedSelectedPackIds(nil)
}
} else {
updateState {
$0.withUpdatedEditing(false).withUpdatedSelectedPackIds(nil)
}
var packNames: [String] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
if let info = entry.info as? StickerPackCollectionInfo {
packNames.append(info.shortName)
}
}
var packNames: [String] = []
for entry in stickerPacks {
if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) {
if let info = entry.info as? StickerPackCollectionInfo {
packNames.append(info.shortName)
}
}
let text = packNames.map { "https://t.me/addstickers/\($0)" }.joined(separator: "\n")
let shareController = ShareController(context: context, subject: .text(text), externalShare: true)
presentControllerImpl?(shareController, nil)
})])
}
let text = packNames.map { "https://t.me/addstickers/\($0)" }.joined(separator: "\n")
let shareController = ShareController(context: context, subject: .text(text), externalShare: true)
presentControllerImpl?(shareController, nil)
})])
} else {
if case .modal = mode {
rightNavigationButton = nil
} else {
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: {
updateState {

View File

@ -734,8 +734,10 @@ public final class ManagedAudioSession {
switch type {
case .voiceCall:
mode = .voiceChat
options.insert(.mixWithOthers)
case .videoCall:
mode = .videoChat
options.insert(.mixWithOthers)
default:
mode = .default
}

View File

@ -613,6 +613,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
private var screencastFramesDisposable: Disposable?
private var screencastAudioDataDisposable: Disposable?
private var screencastStateDisposable: Disposable?
init(
@ -881,6 +882,13 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
screencastCapturer.injectPixelBuffer(screencastFrame.0, rotation: screencastFrame.1)
})
self.screencastAudioDataDisposable = (screencastBufferServerContext.audioData
|> deliverOnMainQueue).start(next: { [weak self] data in
guard let strongSelf = self else {
return
}
strongSelf.genericCallContext?.addExternalAudioData(data: data)
})
self.screencastStateDisposable = (screencastBufferServerContext.isActive
|> distinctUntilChanged
|> deliverOnMainQueue).start(next: { [weak self] isActive in
@ -941,6 +949,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.peerUpdatesSubscription?.dispose()
self.screencastFramesDisposable?.dispose()
self.screencastAudioDataDisposable?.dispose()
self.screencastStateDisposable?.dispose()
}

View File

@ -189,21 +189,23 @@ public func rootPathForBasePath(_ appGroupPath: String) -> String {
}
public func performAppGroupUpgrades(appGroupPath: String, rootPath: String) {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: rootPath), withIntermediateDirectories: true, attributes: nil)
DispatchQueue.global(qos: .default).async {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: rootPath), withIntermediateDirectories: true, attributes: nil)
if let items = FileManager.default.enumerator(at: URL(fileURLWithPath: appGroupPath), includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) {
let allowedDirectories: [String] = [
"telegram-data",
"Library"
]
if let items = FileManager.default.enumerator(at: URL(fileURLWithPath: appGroupPath), includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) {
let allowedDirectories: [String] = [
"telegram-data",
"Library"
]
for url in items {
guard let url = url as? URL else {
continue
}
if let isDirectory = try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory, isDirectory {
if !allowedDirectories.contains(url.lastPathComponent) {
let _ = try? FileManager.default.removeItem(at: url)
for url in items {
guard let url = url as? URL else {
continue
}
if let isDirectory = try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory, isDirectory {
if !allowedDirectories.contains(url.lastPathComponent) {
let _ = try? FileManager.default.removeItem(at: url)
}
}
}
}

View File

@ -1613,7 +1613,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} |> deliverOnMainQueue).start(next: { [weak self] peers in
if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId {
@ -10852,6 +10851,82 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
controller.present(textAlertController(context: context, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
controller.multiplePeersSelected = { [weak self, weak controller] peers, messageText in
guard let strongSelf = self, let strongController = controller else {
return
}
strongController.dismiss()
for peer in peers {
var result: [EnqueueMessage] = []
if messageText.string.count > 0 {
let inputText = convertMarkdownToAttributes(messageText)
for text in breakChatInputText(trimChatInputText(inputText)) {
if text.length != 0 {
var attributes: [MessageAttribute] = []
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
}
}
}
result.append(contentsOf: messages.map { message -> EnqueueMessage in
return .forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil)
})
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|> deliverOnMainQueue).start(next: { messageIds in
if let strongSelf = self {
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
guard let id = id else {
return nil
}
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
if status != nil {
return .never()
} else {
return .single(true)
}
}
|> take(1)
})
if strongSelf.shareStatusDisposable == nil {
strongSelf.shareStatusDisposable = MetaDisposable()
}
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|> deliverOnMainQueue).start())
}
})
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peers.count == 1, let peerId = peers.first?.id, peerId == strongSelf.context.account.peerId {
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
} else {
text = ""
}
}
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
}
controller.peerSelected = { [weak self, weak controller] peer in
let peerId = peer.id

View File

@ -1046,16 +1046,16 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
let mediaRecordingState = interfaceState.inputTextPanelState.mediaRecordingState
var inputHasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
inputHasText = true
}
var hasMenuButton = false
var menuButtonExpanded = false
if let peer = interfaceState.renderedPeer?.peer as? TelegramUser, let _ = peer.botInfo, interfaceState.hasBotCommands && interfaceState.editMessageState == nil {
hasMenuButton = true
var inputHasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
inputHasText = true
}
if !inputHasText {
switch interfaceState.inputMode {
case .none, .inputButtons:
@ -1501,12 +1501,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
self.slowmodePlaceholderNode = nil
slowmodePlaceholderNode.removeFromSupernode()
}
var inputHasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
inputHasText = true
}
if (interfaceState.slowmodeState != nil && !isScheduledMessages && interfaceState.editMessageState == nil) || interfaceState.inputTextPanelState.contextPlaceholder != nil {
self.textPlaceholderNode.isHidden = true
self.slowmodePlaceholderNode?.isHidden = inputHasText
@ -1552,13 +1547,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
}
var hasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
hasText = true
hideMicButton = true
}
if self.extendedSearchLayout {
if inputHasText || self.extendedSearchLayout {
hideMicButton = true
}
@ -1574,7 +1563,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
self.actionButtons.micButton.fadeDisabled = mediaInputDisabled
self.updateActionButtons(hasText: hasText, hideMicButton: hideMicButton, animated: transition.isAnimated)
self.updateActionButtons(hasText: inputHasText, hideMicButton: hideMicButton, animated: transition.isAnimated)
if let prevInputPanelNode = self.prevInputPanelNode {
prevInputPanelNode.frame = CGRect(origin: .zero, size: prevInputPanelNode.frame.size)

View File

@ -71,7 +71,7 @@ final class CommandMenuChatInputContextPanelNode: ChatInputContextPanelNode {
self.listView.clipsToBounds = false
self.listView.isOpaque = false
self.listView.stackFromBottom = true
self.listView.keepBottomItemOverscrollBackground = theme.list.plainBackgroundColor
// self.listView.keepBottomItemOverscrollBackground = theme.list.plainBackgroundColor
self.listView.limitHitTestToNodes = true
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
self.listView.accessibilityPageScrolledString = { row, count in

View File

@ -1531,6 +1531,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
private let selectAddMemberDisposable = MetaDisposable()
private let addMemberDisposable = MetaDisposable()
private let preloadHistoryDisposable = MetaDisposable()
private var shareStatusDisposable: MetaDisposable?
private let editAvatarDisposable = MetaDisposable()
private let updateAvatarDisposable = MetaDisposable()
@ -2864,6 +2865,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
self.enqueueMediaMessageDisposable.dispose()
self.supportPeerDisposable.dispose()
self.tipsPeerDisposable.dispose()
self.shareStatusDisposable?.dispose()
}
override func didLoad() {
@ -3694,7 +3696,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
items.append(.separator)
}
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Channel_LeaveChannel, textColor: .destructive, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Logout"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
@ -3720,7 +3722,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
items.append(.separator)
}
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Group_LeaveGroup, textColor: .destructive, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Logout"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
@ -3735,7 +3737,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
items.append(.separator)
}
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Group_LeaveGroup, textColor: .destructive, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Logout"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
@ -5639,7 +5641,83 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
func forwardMessages(messageIds: Set<MessageId>?) {
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled]))
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText in
guard let strongSelf = self, let strongController = peerSelectionController else {
return
}
strongController.dismiss()
for peer in peers {
var result: [EnqueueMessage] = []
if messageText.string.count > 0 {
let inputText = convertMarkdownToAttributes(messageText)
for text in breakChatInputText(trimChatInputText(inputText)) {
if text.length != 0 {
var attributes: [MessageAttribute] = []
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
}
}
}
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
})
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|> deliverOnMainQueue).start(next: { messageIds in
if let strongSelf = self {
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
guard let id = id else {
return nil
}
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
if status != nil {
return .never()
} else {
return .single(true)
}
}
|> take(1)
})
if strongSelf.shareStatusDisposable == nil {
strongSelf.shareStatusDisposable = MetaDisposable()
}
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|> deliverOnMainQueue).start())
}
})
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let text: String
var savedMessages = false
if peers.count == 1, let peerId = peers.first?.id, peerId == strongSelf.context.account.peerId {
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
savedMessages = true
} else {
if peers.count == 1, let peer = peers.first {
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
} else if let peer = peers.first {
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
} else {
text = ""
}
}
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
}
peerSelectionController.peerSelected = { [weak self, weak peerSelectionController] peer in
let peerId = peer.id

View File

@ -20,6 +20,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
private var customTitle: String?
public var peerSelected: ((Peer) -> Void)?
public var multiplePeersSelected: (([Peer], NSAttributedString) -> Void)?
private let filter: ChatListNodePeersFilter
private let attemptSelection: ((Peer) -> Void)?
@ -124,6 +125,10 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self?.activateSearch()
})
self.navigationBar?.setContentNode(self.searchContentNode, animated: false)
if params.multipleSelection {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Select, style: .plain, target: self, action: #selector(self.beginSelection))
}
}
required public init(coder aDecoder: NSCoder) {
@ -152,6 +157,10 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.peerSelectionNode.navigationBar = self.navigationBar
self.peerSelectionNode.requestSend = { [weak self] peers, text in
self?.multiplePeersSelected?(peers, text)
}
self.peerSelectionNode.requestDeactivateSearch = { [weak self] in
self?.deactivateSearch()
}
@ -220,6 +229,11 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.peerSelectionNode.containerLayoutUpdated(layout, navigationBarHeight: self.cleanNavigationHeight, actualNavigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
}
@objc private func beginSelection() {
self.navigationItem.rightBarButtonItem = nil
self.peerSelectionNode.beginSelection()
}
@objc func cancelPressed() {
if let customDismiss = self.customDismiss {
customDismiss()

View File

@ -21,6 +21,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
private let filter: ChatListNodePeersFilter
private let hasGlobalSearch: Bool
private var presentationInterfaceState: ChatPresentationInterfaceState
private var interfaceInteraction: ChatPanelInterfaceInteraction?
var inProgress: Bool = false {
didSet {
@ -33,6 +36,8 @@ final class PeerSelectionControllerNode: ASDisplayNode {
private let toolbarSeparatorNode: ASDisplayNode?
private let segmentedControlNode: SegmentedControlNode?
private var textInputPanelNode: PeerSelectionTextInputPanelNode?
var contactListNode: ContactListNode?
let chatListNode: ChatListNode
@ -51,6 +56,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var requestOpenDisabledPeer: ((Peer) -> Void)?
var requestOpenPeerFromSearch: ((Peer) -> Void)?
var requestOpenMessageFromSearch: ((Peer, MessageId) -> Void)?
var requestSend: (([Peer], NSAttributedString) -> Void)?
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
@ -70,6 +76,8 @@ final class PeerSelectionControllerNode: ASDisplayNode {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.presentationData = presentationData
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil)
if hasChatListSelector && hasContactSelector {
self.toolbarBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
@ -107,6 +115,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
self.chatListNode.selectionCountChanged = { [weak self] count in
self?.textInputPanelNode?.updateSendButtonEnabled(count > 0, animated: true)
}
self.chatListNode.accessibilityPageScrolledString = { row, count in
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
}
@ -163,6 +174,112 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if !hasChatListSelector && hasContactSelector {
self.indexChanged(1)
}
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
}, setupEditMessage: { _, _ in
}, beginMessageSelection: { _, _ in
}, deleteSelectedMessages: {
}, reportSelectedMessages: {
}, reportMessages: { _, _ in
}, blockMessageAuthor: { _, _ in
}, deleteMessages: { _, _, f in
f(.default)
}, forwardSelectedMessages: {
}, forwardCurrentForwardMessages: {
}, forwardMessages: { _ in
}, shareSelectedMessages: {
}, updateTextInputStateAndMode: { [weak self] f in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, { state in
let (updatedState, updatedMode) = f(state.interfaceState.effectiveInputState, state.inputMode)
return state.updatedInterfaceState { interfaceState in
return interfaceState.withUpdatedEffectiveInputState(updatedState)
}.updatedInputMode({ _ in updatedMode })
})
}
}, updateInputModeAndDismissedButtonKeyboardMessageId: { [weak self] f in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, {
let (updatedInputMode, updatedClosedButtonKeyboardMessageId) = f($0)
return $0.updatedInputMode({ _ in return updatedInputMode }).updatedInterfaceState({
$0.withUpdatedMessageActionsState({ value in
var value = value
value.closedButtonKeyboardMessageId = updatedClosedButtonKeyboardMessageId
return value
})
})
})
}
}, openStickers: {
}, editMessage: {
}, beginMessageSearch: { _, _ in
}, dismissMessageSearch: {
}, updateMessageSearch: { _ in
}, openSearchResults: {
}, navigateMessageSearch: { _ in
}, openCalendarSearch: {
}, toggleMembersSearch: { _ in
}, navigateToMessage: { _, _, _, _ in
}, navigateToChat: { _ in
}, navigateToProfile: { _ in
}, openPeerInfo: {
}, togglePeerNotifications: {
}, sendContextResult: { _, _, _, _ in
return false
}, sendBotCommand: { _, _ in
}, sendBotStart: { _ in
}, botSwitchChatWithPayload: { _, _ in
}, beginMediaRecording: { _ in
}, finishMediaRecording: { _ in
}, stopMediaRecording: {
}, lockMediaRecording: {
}, deleteRecordedMedia: {
}, sendRecordedMedia: { _ in
}, displayRestrictedInfo: { _, _ in
}, displayVideoUnmuteTip: { _ in
}, switchMediaRecordingMode: {
}, setupMessageAutoremoveTimeout: {
}, sendSticker: { _, _, _, _ in
return false
}, unblockPeer: {
}, pinMessage: { _, _ in
}, unpinMessage: { _, _, _ in
}, unpinAllMessages: {
}, openPinnedList: { _ in
}, shareAccountContact: {
}, reportPeer: {
}, presentPeerContact: {
}, dismissReportPeer: {
}, deleteChat: {
}, beginCall: { _ in
}, toggleMessageStickerStarred: { _ in
}, presentController: { _, _ in
}, getNavigationController: {
return nil
}, presentGlobalOverlayController: { _, _ in
}, navigateFeed: {
}, openGrouping: {
}, toggleSilentPost: {
}, requestUnvoteInMessage: { _ in
}, requestStopPollInMessage: { _ in
}, updateInputLanguage: { _ in
}, unarchiveChat: {
}, openLinkEditing: {
}, reportPeerIrrelevantGeoLocation: {
}, displaySlowmodeTooltip: { _, _ in
}, displaySendMessageOptions: { _, _ in
}, openScheduledMessages: {
}, openPeersNearby: {
}, displaySearchResultsTooltip: { _, _ in
}, unarchivePeer: {
}, scrollToTop: {
}, viewReplies: { _, _ in
}, activatePinnedListPreview: { _, _ in
}, joinGroupCall: { _ in
}, presentInviteMembers: {
}, presentGigagroupHelp: {
}, editMessageMedia: { _, _ in
}, updateShowCommands: { _ in }, statuses: nil)
self.readyValue.set(self.chatListNode.ready)
}
@ -171,6 +288,89 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.presentationDataDisposable?.dispose()
}
private func updateChatPresentationInterfaceState(animated: Bool = true, _ f: (ChatPresentationInterfaceState) -> ChatPresentationInterfaceState, completion: @escaping (ContainedViewLayoutTransition) -> Void = { _ in }) {
self.updateChatPresentationInterfaceState(transition: animated ? .animated(duration: 0.4, curve: .spring) : .immediate, f, completion: completion)
}
private func updateChatPresentationInterfaceState(transition: ContainedViewLayoutTransition, _ f: (ChatPresentationInterfaceState) -> ChatPresentationInterfaceState, completion externalCompletion: @escaping (ContainedViewLayoutTransition) -> Void = { _ in }) {
let presentationInterfaceState = f(self.presentationInterfaceState)
let updateInputTextState = self.presentationInterfaceState.interfaceState.effectiveInputState != presentationInterfaceState.interfaceState.effectiveInputState
self.presentationInterfaceState = presentationInterfaceState
if let textInputPanelNode = self.textInputPanelNode, updateInputTextState {
textInputPanelNode.updateInputTextState(presentationInterfaceState.interfaceState.effectiveInputState, animated: transition.isAnimated)
}
if let (layout, navigationBarHeight, actualNavigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, actualNavigationBarHeight: actualNavigationBarHeight, transition: transition)
}
}
func beginSelection() {
if let _ = self.textInputPanelNode {
} else {
let textInputPanelNode = PeerSelectionTextInputPanelNode(presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) })
textInputPanelNode.interfaceInteraction = self.interfaceInteraction
textInputPanelNode.sendMessage = { [weak self] in
guard let strongSelf = self else {
return
}
if strongSelf.contactListActive {
strongSelf.contactListNode?.multipleSelection = true
let selectedContactPeers = strongSelf.contactListNode?.selectedPeers ?? []
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
var selectedPeers: [Peer] = []
for contactPeer in selectedContactPeers {
if case let .peer(peer, _, _) = contactPeer {
selectedPeers.append(peer)
}
}
if !selectedPeers.isEmpty {
strongSelf.requestSend?(selectedPeers, effectiveInputText)
}
} else {
var selectedPeerIds: [PeerId] = []
var selectedPeerMap: [PeerId: Peer] = [:]
strongSelf.chatListNode.updateState { state in
selectedPeerIds = Array(state.selectedPeerIds)
selectedPeerMap = state.selectedPeerMap
return state
}
if !selectedPeerIds.isEmpty {
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
var selectedPeers: [Peer] = []
for peerId in selectedPeerIds {
if let peer = selectedPeerMap[peerId] {
selectedPeers.append(peer)
}
}
strongSelf.requestSend?(selectedPeers, effectiveInputText)
}
}
}
self.addSubnode(textInputPanelNode)
self.textInputPanelNode = textInputPanelNode
if let (layout, navigationBarHeight, actualNavigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, actualNavigationBarHeight: actualNavigationBarHeight, transition: .animated(duration: 0.3, curve: .spring))
}
}
if self.contactListActive {
self.contactListNode?.updateSelectionState({ _ in
return ContactListNodeGroupSelectionState()
})
} else {
self.chatListNode.updateState { state in
var state = state
state.editing = true
return state
}
}
}
private func updateThemeAndStrings() {
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
self.searchDisplayController?.updatePresentationData(self.presentationData)
@ -185,20 +385,48 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.containerLayout = (layout, navigationBarHeight, actualNavigationBarHeight)
let cleanInsets = layout.insets(options: [])
var insets = layout.insets(options: [.input])
var toolbarHeight: CGFloat = cleanInsets.bottom
var textPanelHeight: CGFloat?
if let textInputPanelNode = self.textInputPanelNode {
var panelTransition = transition
if textInputPanelNode.frame.width.isZero {
panelTransition = .immediate
}
var panelHeight = textInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height / 2.0, isSecondary: false, transition: panelTransition, interfaceState: self.presentationInterfaceState, metrics: layout.metrics)
if self.searchDisplayController == nil {
panelHeight += insets.bottom
} else {
panelHeight += cleanInsets.bottom
}
textPanelHeight = panelHeight
let panelFrame = CGRect(x: 0.0, y: layout.size.height - panelHeight, width: layout.size.width, height: panelHeight)
if textInputPanelNode.frame.width.isZero {
var initialPanelFrame = panelFrame
initialPanelFrame.origin.y = layout.size.height
textInputPanelNode.frame = initialPanelFrame
}
transition.updateFrame(node: textInputPanelNode, frame: panelFrame)
}
if let segmentedControlNode = self.segmentedControlNode, let toolbarBackgroundNode = self.toolbarBackgroundNode, let toolbarSeparatorNode = self.toolbarSeparatorNode {
toolbarHeight += 44.0
if let textPanelHeight = textPanelHeight {
toolbarHeight = textPanelHeight
} else {
toolbarHeight += 44.0
}
transition.updateFrame(node: toolbarBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: toolbarHeight)))
toolbarBackgroundNode.update(size: toolbarBackgroundNode.bounds.size, transition: transition)
transition.updateFrame(node: toolbarSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
let controlSize = segmentedControlNode.updateLayout(.sizeToFit(maximumWidth: layout.size.width, minimumWidth: 200.0, height: 32.0), transition: transition)
transition.updateFrame(node: segmentedControlNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - controlSize.width) / 2.0), y: layout.size.height - toolbarHeight + floor((44.0 - controlSize.height) / 2.0)), size: controlSize))
let controlOrigin = layout.size.height - (textPanelHeight == nil ? toolbarHeight : 0.0) + floor((44.0 - controlSize.height) / 2.0)
transition.updateFrame(node: segmentedControlNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - controlSize.width) / 2.0), y: controlOrigin), size: controlSize))
}
var insets = layout.insets(options: [.input])
insets.top += navigationBarHeight
insets.bottom = max(insets.bottom, cleanInsets.bottom + 44.0)
insets.left += layout.safeInsets.left
@ -239,7 +467,45 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if self.chatListNode.supernode != nil {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ChatListSearchContainerNode(context: self.context, filter: self.filter, groupId: .root, displaySearchFilters: false, openPeer: { [weak self] peer, _ in
if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch {
guard let strongSelf = self else {
return
}
var updated = false
var count = 0
strongSelf.chatListNode.updateState { state in
if state.editing {
updated = true
var state = state
var foundPeers = state.foundPeers
var selectedPeerMap = state.selectedPeerMap
selectedPeerMap[peer.id] = peer
var exists = false
for foundPeer in foundPeers {
if peer.id == foundPeer.id {
exists = true
break
}
}
if !exists {
foundPeers.insert(peer, at: 0)
}
if state.selectedPeerIds.contains(peer.id) {
state.selectedPeerIds.remove(peer.id)
} else {
state.selectedPeerIds.insert(peer.id)
}
state.foundPeers = foundPeers
state.selectedPeerMap = selectedPeerMap
count = state.selectedPeerIds.count
return state
} else {
return state
}
}
if updated {
strongSelf.textInputPanelNode?.updateSendButtonEnabled(count > 0, animated: true)
strongSelf.requestDeactivateSearch?()
} else if let requestOpenPeerFromSearch = strongSelf.requestOpenPeerFromSearch {
requestOpenPeerFromSearch(peer)
}
}, openDisabledPeer: { [weak self] peer in
@ -276,17 +542,48 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ContactsSearchContainerNode(context: self.context, onlyWriteable: true, categories: categories, addContact: nil, openPeer: { [weak self] peer in
if let strongSelf = self {
switch peer {
case let .peer(peer, _, _):
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peer.id)
} |> deliverOnMainQueue).start(next: { peer in
if let strongSelf = self, let peer = peer {
strongSelf.requestOpenPeerFromSearch?(peer)
var updated = false
var count = 0
strongSelf.contactListNode?.updateSelectionState { state -> ContactListNodeGroupSelectionState? in
if let state = state {
updated = true
var foundPeers = state.foundPeers
var selectedPeerMap = state.selectedPeerMap
selectedPeerMap[peer.id] = peer
var exists = false
for foundPeer in foundPeers {
if peer.id == foundPeer.id {
exists = true
break
}
})
case .deviceContact:
break
}
if !exists {
foundPeers.insert(peer, at: 0)
}
let updatedState = state.withToggledPeerId(peer.id).withFoundPeers(foundPeers).withSelectedPeerMap(selectedPeerMap)
count = updatedState.selectedPeerIndices.count
return updatedState
} else {
return nil
}
}
if updated {
strongSelf.textInputPanelNode?.updateSendButtonEnabled(count > 0, animated: true)
strongSelf.requestDeactivateSearch?()
} else {
switch peer {
case let .peer(peer, _, _):
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peer.id)
} |> deliverOnMainQueue).start(next: { peer in
if let strongSelf = self, let peer = peer {
strongSelf.requestOpenPeerFromSearch?(peer)
}
})
case .deviceContact:
break
}
}
}
}, contextAction: nil), cancel: { [weak self] in
@ -342,6 +639,11 @@ final class PeerSelectionControllerNode: ASDisplayNode {
let contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: [], includeChatList: false)))
self.contactListNode = contactListNode
contactListNode.enableUpdates = true
contactListNode.selectionStateUpdated = { [weak self] selectionState in
if let strongSelf = self {
strongSelf.textInputPanelNode?.updateSendButtonEnabled((selectionState?.selectedPeerIndices.count ?? 0) > 0, animated: true)
}
}
contactListNode.activateSearch = { [weak self] in
self?.requestActivateSearch?()
}
@ -394,7 +696,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
} else if let contactListNode = self.contactListNode {
contactListNode.enableUpdates = false
self.insertSubnode(chatListNode, aboveSubnode: contactListNode)
self.insertSubnode(self.chatListNode, aboveSubnode: contactListNode)
contactListNode.removeFromSupernode()
}
}

View File

@ -0,0 +1,935 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import SwiftSignalKit
import Postbox
import TelegramCore
import SyncCore
import MobileCoreServices
import TelegramPresentationData
import TextFormat
import AccountContext
import TouchDownGesture
import ActivityIndicator
import Speak
private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers])
private let minInputFontSize = chatTextInputMinFontSize
private func calclulateTextFieldMinHeight(_ presentationInterfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
var result: CGFloat
if baseFontSize.isEqual(to: 26.0) {
result = 42.0
} else if baseFontSize.isEqual(to: 23.0) {
result = 38.0
} else if baseFontSize.isEqual(to: 17.0) {
result = 31.0
} else if baseFontSize.isEqual(to: 19.0) {
result = 33.0
} else if baseFontSize.isEqual(to: 21.0) {
result = 35.0
} else {
result = 31.0
}
if case .regular = metrics.widthClass {
result = max(33.0, result)
}
return result
}
private func calculateTextFieldRealInsets(_ presentationInterfaceState: ChatPresentationInterfaceState) -> UIEdgeInsets {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
let top: CGFloat
let bottom: CGFloat
if baseFontSize.isEqual(to: 14.0) {
top = 2.0
bottom = 1.0
} else if baseFontSize.isEqual(to: 15.0) {
top = 1.0
bottom = 1.0
} else if baseFontSize.isEqual(to: 16.0) {
top = 0.5
bottom = 0.0
} else {
top = 0.0
bottom = 0.0
}
return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: 0.0)
}
private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, UIImage)?
private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackgroundColor: UIColor?, strokeColor: UIColor, diameter: CGFloat) -> UIImage? {
if let backgroundColor = backgroundColor, let current = currentTextInputBackgroundImage {
if current.0.isEqual(backgroundColor) && current.1.isEqual(strokeColor) && current.2.isEqual(to: diameter) {
return current.3
}
}
let image = generateImage(CGSize(width: diameter, height: diameter), rotatedContext: { size, context in
context.clear(CGRect(x: 0.0, y: 0.0, width: diameter, height: diameter))
if let inputBackgroundColor = inputBackgroundColor {
context.setBlendMode(.normal)
context.setFillColor(inputBackgroundColor.cgColor)
} else {
context.setBlendMode(.clear)
context.setFillColor(UIColor.clear.cgColor)
}
context.fillEllipse(in: CGRect(x: 0.0, y: 0.0, width: diameter, height: diameter))
context.setBlendMode(.normal)
context.setStrokeColor(strokeColor.cgColor)
let strokeWidth: CGFloat = 1.0
context.setLineWidth(strokeWidth)
context.strokeEllipse(in: CGRect(x: strokeWidth / 2.0, y: strokeWidth / 2.0, width: diameter - strokeWidth, height: diameter - strokeWidth))
})?.stretchableImage(withLeftCapWidth: Int(diameter) / 2, topCapHeight: Int(diameter) / 2)
if let image = image {
if let backgroundColor = backgroundColor {
currentTextInputBackgroundImage = (backgroundColor, strokeColor, diameter, image)
}
return image
} else {
return nil
}
}
class PeerSelectionTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
var textPlaceholderNode: ImmediateTextNode
let textInputContainerBackgroundNode: ASImageNode
let textInputContainer: ASDisplayNode
var textInputNode: EditableTextNode?
let textInputBackgroundNode: ASImageNode
private var transparentTextInputBackgroundImage: UIImage?
let actionButtons: ChatTextInputActionButtonsNode
private let counterTextNode: ImmediateTextNode
private var validLayout: (CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool)?
var sendMessage: () -> Void = { }
var updateHeight: (Bool) -> Void = { _ in }
private var updatingInputState = false
private var currentPlaceholder: String?
private var presentationInterfaceState: ChatPresentationInterfaceState?
private var initializedPlaceholder = false
private let inputMenu = ChatTextInputMenu()
private var theme: PresentationTheme?
private var strings: PresentationStrings?
private let hapticFeedback = HapticFeedback()
var inputTextState: ChatTextInputState {
if let textInputNode = self.textInputNode {
let selectionRange: Range<Int> = textInputNode.selectedRange.location ..< (textInputNode.selectedRange.location + textInputNode.selectedRange.length)
return ChatTextInputState(inputText: stateAttributedStringForText(textInputNode.attributedText ?? NSAttributedString()), selectionRange: selectionRange)
} else {
return ChatTextInputState()
}
}
var storedInputLanguage: String?
var effectiveInputLanguage: String? {
if let textInputNode = textInputNode, textInputNode.isFirstResponder() {
return textInputNode.textInputMode.primaryLanguage
} else {
return self.storedInputLanguage
}
}
var enablePredictiveInput: Bool = true {
didSet {
if let textInputNode = self.textInputNode {
textInputNode.textView.autocorrectionType = self.enablePredictiveInput ? .default : .no
}
}
}
override var context: AccountContext? {
didSet {
self.actionButtons.micButton.account = self.context?.account
}
}
var micButton: ChatTextInputMediaRecordingButton? {
return self.actionButtons.micButton
}
func updateSendButtonEnabled(_ enabled: Bool, animated: Bool) {
self.actionButtons.isUserInteractionEnabled = enabled
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate
transition.updateAlpha(node: self.actionButtons, alpha: enabled ? 1.0 : 0.3)
}
func updateInputTextState(_ state: ChatTextInputState, animated: Bool) {
if state.inputText.length != 0 && self.textInputNode == nil {
self.loadTextInputNode()
}
if let textInputNode = self.textInputNode, let _ = self.presentationInterfaceState {
self.updatingInputState = true
var textColor: UIColor = .black
var accentTextColor: UIColor = .blue
var baseFontSize: CGFloat = 17.0
if let presentationInterfaceState = self.presentationInterfaceState {
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
accentTextColor = presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
}
textInputNode.attributedText = textAttributedStringForStateText(state.inputText, fontSize: baseFontSize, textColor: textColor, accentTextColor: accentTextColor, writingDirection: nil)
textInputNode.selectedRange = NSMakeRange(state.selectionRange.lowerBound, state.selectionRange.count)
self.updatingInputState = false
self.updateTextNodeText(animated: animated)
}
}
var text: String {
get {
return self.textInputNode?.attributedText?.string ?? ""
} set(value) {
if let textInputNode = self.textInputNode {
var textColor: UIColor = .black
var baseFontSize: CGFloat = 17.0
if let presentationInterfaceState = self.presentationInterfaceState {
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
}
textInputNode.attributedText = NSAttributedString(string: value, font: Font.regular(baseFontSize), textColor: textColor)
self.editableTextNodeDidUpdateText(textInputNode)
}
}
}
private let textInputViewInternalInsets = UIEdgeInsets(top: 1.0, left: 13.0, bottom: 1.0, right: 13.0)
init(presentationInterfaceState: ChatPresentationInterfaceState, presentController: @escaping (ViewController) -> Void) {
self.textInputContainerBackgroundNode = ASImageNode()
self.textInputContainerBackgroundNode.isUserInteractionEnabled = false
self.textInputContainerBackgroundNode.displaysAsynchronously = false
self.textInputContainer = ASDisplayNode()
self.textInputContainer.addSubnode(self.textInputContainerBackgroundNode)
self.textInputContainer.clipsToBounds = true
self.textInputBackgroundNode = ASImageNode()
self.textInputBackgroundNode.displaysAsynchronously = false
self.textInputBackgroundNode.displayWithoutProcessing = true
self.textPlaceholderNode = ImmediateTextNode()
self.textPlaceholderNode.maximumNumberOfLines = 1
self.textPlaceholderNode.isUserInteractionEnabled = false
self.actionButtons = ChatTextInputActionButtonsNode(theme: presentationInterfaceState.theme, strings: presentationInterfaceState.strings, presentController: presentController)
self.counterTextNode = ImmediateTextNode()
self.counterTextNode.textAlignment = .center
super.init()
self.actionButtons.sendButtonLongPressed = { [weak self] node, gesture in
self?.interfaceInteraction?.displaySendMessageOptions(node, gesture)
}
self.actionButtons.sendButton.addTarget(self, action: #selector(self.sendButtonPressed), forControlEvents: .touchUpInside)
self.actionButtons.sendButton.alpha = 1.0
self.actionButtons.micButton.alpha = 0.0
self.actionButtons.expandMediaInputButton.alpha = 0.0
self.actionButtons.updateAccessibility()
self.addSubnode(self.textInputContainer)
self.addSubnode(self.textInputBackgroundNode)
self.addSubnode(self.textPlaceholderNode)
self.addSubnode(self.actionButtons)
self.addSubnode(self.counterTextNode)
self.textInputBackgroundNode.clipsToBounds = true
let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:)))
recognizer.touchDown = { [weak self] in
if let strongSelf = self {
strongSelf.ensureFocused()
}
}
self.textInputBackgroundNode.isUserInteractionEnabled = true
self.textInputBackgroundNode.view.addGestureRecognizer(recognizer)
self.updateSendButtonEnabled(false, animated: false)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func loadTextInputNodeIfNeeded() {
if self.textInputNode == nil {
self.loadTextInputNode()
}
}
private func loadTextInputNode() {
let textInputNode = EditableTextNode()
textInputNode.initialPrimaryLanguage = self.presentationInterfaceState?.interfaceState.inputLanguage
var textColor: UIColor = .black
var tintColor: UIColor = .blue
var baseFontSize: CGFloat = 17.0
var keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default
if let presentationInterfaceState = self.presentationInterfaceState {
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
tintColor = presentationInterfaceState.theme.list.itemAccentColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
keyboardAppearance = presentationInterfaceState.theme.rootController.keyboardColor.keyboardAppearance
}
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 1.0
paragraphStyle.lineHeightMultiple = 1.0
paragraphStyle.paragraphSpacing = 1.0
paragraphStyle.maximumLineHeight = 20.0
paragraphStyle.minimumLineHeight = 20.0
textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(max(minInputFontSize, baseFontSize)), NSAttributedString.Key.foregroundColor.rawValue: textColor, NSAttributedString.Key.paragraphStyle.rawValue: paragraphStyle]
textInputNode.clipsToBounds = false
textInputNode.textView.clipsToBounds = false
textInputNode.delegate = self
textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
textInputNode.keyboardAppearance = keyboardAppearance
textInputNode.tintColor = tintColor
textInputNode.textView.scrollIndicatorInsets = UIEdgeInsets(top: 9.0, left: 0.0, bottom: 9.0, right: -13.0)
self.textInputContainer.addSubnode(textInputNode)
textInputNode.view.disablesInteractiveTransitionGestureRecognizer = true
self.textInputNode = textInputNode
if let presentationInterfaceState = self.presentationInterfaceState {
refreshChatTextInputTypingAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
textInputNode.textContainerInset = calculateTextFieldRealInsets(presentationInterfaceState)
}
if !self.textInputContainer.bounds.size.width.isZero {
let textInputFrame = self.textInputContainer.frame
textInputNode.frame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - self.textInputViewInternalInsets.bottom))
}
self.textInputBackgroundNode.isUserInteractionEnabled = false
self.textInputBackgroundNode.view.removeGestureRecognizer(self.textInputBackgroundNode.view.gestureRecognizers![0])
let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:)))
recognizer.touchDown = { [weak self] in
if let strongSelf = self {
strongSelf.ensureFocused()
}
}
textInputNode.view.addGestureRecognizer(recognizer)
textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string
}
private func textFieldMaxHeight(_ maxHeight: CGFloat, metrics: LayoutMetrics) -> CGFloat {
let textFieldInsets = self.textFieldInsets(metrics: metrics)
return max(33.0, maxHeight - (textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom))
}
private func calculateTextFieldMetrics(width: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat) {
let textFieldInsets = self.textFieldInsets(metrics: metrics)
let fieldMaxHeight = textFieldMaxHeight(maxHeight, metrics: metrics)
var textFieldMinHeight: CGFloat = 35.0
if let presentationInterfaceState = self.presentationInterfaceState {
textFieldMinHeight = calclulateTextFieldMinHeight(presentationInterfaceState, metrics: metrics)
}
let textFieldHeight: CGFloat
if let textInputNode = self.textInputNode {
let maxTextWidth = width - textFieldInsets.left - textFieldInsets.right - self.textInputViewInternalInsets.left - self.textInputViewInternalInsets.right
let measuredHeight = textInputNode.measure(CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude))
let unboundTextFieldHeight = max(textFieldMinHeight, ceil(measuredHeight.height))
let maxNumberOfLines = min(12, (Int(fieldMaxHeight - 11.0) - 33) / 22)
let updatedMaxHeight = (CGFloat(maxNumberOfLines) * (22.0 + 2.0) + 10.0)
textFieldHeight = max(textFieldMinHeight, min(updatedMaxHeight, unboundTextFieldHeight))
} else {
textFieldHeight = textFieldMinHeight
}
return (0.0, textFieldHeight)
}
private func textFieldInsets(metrics: LayoutMetrics) -> UIEdgeInsets {
var insets = UIEdgeInsets(top: 6.0, left: 6.0, bottom: 6.0, right: 42.0)
if case .regular = metrics.widthClass, case .regular = metrics.heightClass {
insets.top += 1.0
insets.bottom += 1.0
}
return insets
}
private func panelHeight(textFieldHeight: CGFloat, metrics: LayoutMetrics) -> CGFloat {
let textFieldInsets = self.textFieldInsets(metrics: metrics)
let result = textFieldHeight + textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom
return result
}
override func minimalHeight(interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics)
var minimalHeight: CGFloat = 14.0 + textFieldMinHeight
if case .regular = metrics.widthClass, case .regular = metrics.heightClass {
minimalHeight += 2.0
}
return minimalHeight
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
let previousAdditionalSideInsets = self.validLayout?.3
self.validLayout = (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary)
var transition = transition
var additionalOffset: CGFloat = 0.0
if let previousAdditionalSideInsets = previousAdditionalSideInsets, previousAdditionalSideInsets.right != additionalSideInsets.right {
additionalOffset = (previousAdditionalSideInsets.right - additionalSideInsets.right) / 3.0
if case .animated = transition {
transition = .animated(duration: 0.2, curve: .easeInOut)
}
}
if self.presentationInterfaceState != interfaceState {
let previousState = self.presentationInterfaceState
self.presentationInterfaceState = interfaceState
let themeUpdated = previousState?.theme !== interfaceState.theme
var updateSendButtonIcon = false
if (previousState?.interfaceState.editMessage != nil) != (interfaceState.interfaceState.editMessage != nil) {
updateSendButtonIcon = true
}
if self.theme !== interfaceState.theme {
updateSendButtonIcon = true
if self.theme == nil || !self.theme!.chat.inputPanel.inputTextColor.isEqual(interfaceState.theme.chat.inputPanel.inputTextColor) {
let textColor = interfaceState.theme.chat.inputPanel.inputTextColor
let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
if let textInputNode = self.textInputNode {
if let text = textInputNode.attributedText?.string {
let range = textInputNode.selectedRange
textInputNode.attributedText = NSAttributedString(string: text, font: Font.regular(baseFontSize), textColor: textColor)
textInputNode.selectedRange = range
}
textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(baseFontSize), NSAttributedString.Key.foregroundColor.rawValue: textColor]
}
}
let keyboardAppearance = interfaceState.theme.rootController.keyboardColor.keyboardAppearance
if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance, textInputNode.isFirstResponder() {
if textInputNode.isCurrentlyEmoji() {
textInputNode.initialPrimaryLanguage = "emoji"
textInputNode.resetInitialPrimaryLanguage()
}
textInputNode.keyboardAppearance = keyboardAppearance
}
self.theme = interfaceState.theme
self.actionButtons.updateTheme(theme: interfaceState.theme)
let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics)
let minimalInputHeight: CGFloat = 2.0 + textFieldMinHeight
let backgroundColor: UIColor
if case let .color(color) = interfaceState.chatWallpaper, UIColor(rgb: color).isEqual(interfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) {
backgroundColor = interfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper
} else {
backgroundColor = interfaceState.theme.chat.inputPanel.panelBackgroundColor
}
self.textInputBackgroundNode.image = textInputBackgroundImage(backgroundColor: backgroundColor, inputBackgroundColor: nil, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
self.transparentTextInputBackgroundImage = textInputBackgroundImage(backgroundColor: nil, inputBackgroundColor: interfaceState.theme.chat.inputPanel.inputBackgroundColor, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
self.textInputContainerBackgroundNode.image = generateStretchableFilledCircleImage(diameter: minimalInputHeight, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor)
} else {
if self.strings !== interfaceState.strings {
self.strings = interfaceState.strings
self.inputMenu.updateStrings(interfaceState.strings)
}
}
if themeUpdated || !self.initializedPlaceholder {
self.initializedPlaceholder = true
let placeholder = interfaceState.strings.Conversation_InputTextPlaceholder
if self.currentPlaceholder != placeholder || themeUpdated {
self.currentPlaceholder = placeholder
let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
self.textPlaceholderNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(baseFontSize), textColor: interfaceState.theme.chat.inputPanel.inputPlaceholderColor)
self.textInputNode?.textView.accessibilityHint = placeholder
let placeholderSize = self.textPlaceholderNode.updateLayout(CGSize(width: 320.0, height: CGFloat.greatestFiniteMagnitude))
if transition.isAnimated, let snapshotLayer = self.textPlaceholderNode.layer.snapshotContentTree() {
self.textPlaceholderNode.supernode?.layer.insertSublayer(snapshotLayer, above: self.textPlaceholderNode.layer)
snapshotLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.22, removeOnCompletion: false, completion: { [weak snapshotLayer] _ in
snapshotLayer?.removeFromSuperlayer()
})
self.textPlaceholderNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
}
self.textPlaceholderNode.frame = CGRect(origin: self.textPlaceholderNode.frame.origin, size: placeholderSize)
}
self.actionButtons.sendButtonLongPressEnabled = true
}
let sendButtonHasApplyIcon = interfaceState.interfaceState.editMessage != nil
if updateSendButtonIcon {
if !self.actionButtons.animatingSendButton {
let imageNode = self.actionButtons.sendButton.imageNode
if transition.isAnimated && !self.actionButtons.sendButton.alpha.isZero && self.actionButtons.sendButton.layer.animation(forKey: "opacity") == nil, let previousImage = imageNode.image {
let tempView = UIImageView(image: previousImage)
self.actionButtons.sendButton.view.addSubview(tempView)
tempView.frame = imageNode.frame
tempView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak tempView] _ in
tempView?.removeFromSuperview()
})
tempView.layer.animateScale(from: 1.0, to: 0.2, duration: 0.2, removeOnCompletion: false)
imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
imageNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2)
}
self.actionButtons.sendButtonHasApplyIcon = sendButtonHasApplyIcon
if self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyButtonImage(interfaceState.theme), for: [])
} else {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(interfaceState.theme), for: [])
}
}
}
}
var textFieldMinHeight: CGFloat = 33.0
if let presentationInterfaceState = self.presentationInterfaceState {
textFieldMinHeight = calclulateTextFieldMinHeight(presentationInterfaceState, metrics: metrics)
}
let minimalHeight: CGFloat = 14.0 + textFieldMinHeight
let minimalInputHeight: CGFloat = 2.0 + textFieldMinHeight
var animatedTransition = true
if case .immediate = transition {
animatedTransition = false
}
let baseWidth = width - leftInset - rightInset
let (accessoryButtonsWidth, textFieldHeight) = self.calculateTextFieldMetrics(width: baseWidth, maxHeight: maxHeight, metrics: metrics)
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
var composeButtonsOffset: CGFloat = 0.0
var textInputBackgroundWidthOffset: CGFloat = 0.0
self.updateCounterTextNode(transition: transition)
let actionButtonsFrame = CGRect(origin: CGPoint(x: width - rightInset - 43.0 - UIScreenPixel + composeButtonsOffset, y: panelHeight - minimalHeight), size: CGSize(width: 44.0, height: minimalHeight))
transition.updateFrame(node: self.actionButtons, frame: actionButtonsFrame)
if let presentationInterfaceState = self.presentationInterfaceState {
self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, interfaceState: presentationInterfaceState)
}
let searchLayoutClearButtonSize = CGSize(width: 44.0, height: minimalHeight)
var textFieldInsets = self.textFieldInsets(metrics: metrics)
if additionalSideInsets.right > 0.0 {
textFieldInsets.right += additionalSideInsets.right / 3.0
}
var textInputViewRealInsets = UIEdgeInsets()
if let presentationInterfaceState = self.presentationInterfaceState {
textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState)
}
let textInputFrame = CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom)
transition.updateFrame(node: self.textInputContainer, frame: textInputFrame)
transition.updateFrame(node: self.textInputContainerBackgroundNode, frame: CGRect(origin: CGPoint(), size: textInputFrame.size))
if let textInputNode = self.textInputNode {
let textFieldFrame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - textInputViewInternalInsets.bottom))
let shouldUpdateLayout = textFieldFrame.size != textInputNode.frame.size
transition.updateFrame(node: textInputNode, frame: textFieldFrame)
if shouldUpdateLayout {
textInputNode.layout()
}
}
var inputHasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
inputHasText = true
}
self.textPlaceholderNode.isHidden = inputHasText
transition.updateFrame(node: self.textPlaceholderNode, frame: CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: self.textPlaceholderNode.frame.size))
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
self.actionButtons.updateAccessibility()
if let prevInputPanelNode = self.prevInputPanelNode {
prevInputPanelNode.frame = CGRect(origin: .zero, size: prevInputPanelNode.frame.size)
}
return panelHeight
}
override func canHandleTransition(from prevInputPanelNode: ChatInputPanelNode?) -> Bool {
return false
}
@objc func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) {
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
refreshChatTextInputAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
refreshChatTextInputTypingAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
let inputTextState = self.inputTextState
self.interfaceInteraction?.updateTextInputStateAndMode({ _, inputMode in return (inputTextState, inputMode) })
self.interfaceInteraction?.updateInputLanguage({ _ in return textInputNode.textInputMode.primaryLanguage })
self.updateTextNodeText(animated: true)
self.updateCounterTextNode(transition: .immediate)
}
}
private func updateCounterTextNode(transition: ContainedViewLayoutTransition) {
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState, let editMessage = presentationInterfaceState.interfaceState.editMessage, let inputTextMaxLength = editMessage.inputTextMaxLength {
let textCount = Int32(textInputNode.textView.text.count)
let counterColor: UIColor = textCount > inputTextMaxLength ? presentationInterfaceState.theme.chat.inputPanel.panelControlDestructiveColor : presentationInterfaceState.theme.chat.inputPanel.panelControlColor
let remainingCount = max(-999, inputTextMaxLength - textCount)
let counterText = remainingCount >= 5 ? "" : "\(remainingCount)"
self.counterTextNode.attributedText = NSAttributedString(string: counterText, font: counterFont, textColor: counterColor)
} else {
self.counterTextNode.attributedText = NSAttributedString(string: "", font: counterFont, textColor: .black)
}
if let (width, leftInset, rightInset, _, maxHeight, metrics, _) = self.validLayout {
var composeButtonsOffset: CGFloat = 0.0
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset, maxHeight: maxHeight, metrics: metrics)
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
var textFieldMinHeight: CGFloat = 33.0
if let presentationInterfaceState = self.presentationInterfaceState {
textFieldMinHeight = calclulateTextFieldMinHeight(presentationInterfaceState, metrics: metrics)
}
let minimalHeight: CGFloat = 14.0 + textFieldMinHeight
let counterSize = self.counterTextNode.updateLayout(CGSize(width: 44.0, height: 44.0))
let actionButtonsOriginX = width - rightInset - 43.0 - UIScreenPixel + composeButtonsOffset
let counterFrame = CGRect(origin: CGPoint(x: actionButtonsOriginX, y: panelHeight - minimalHeight - counterSize.height + 3.0), size: CGSize(width: width - actionButtonsOriginX - rightInset, height: counterSize.height))
transition.updateFrame(node: self.counterTextNode, frame: counterFrame)
}
}
private func updateTextNodeText(animated: Bool) {
var inputHasText = false
if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 {
inputHasText = true
}
if let _ = self.presentationInterfaceState {
self.textPlaceholderNode.isHidden = inputHasText
}
self.updateTextHeight(animated: animated)
}
private func updateTextHeight(animated: Bool) {
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, _) = self.validLayout {
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right, maxHeight: maxHeight, metrics: metrics)
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
if !self.bounds.size.height.isEqual(to: panelHeight) {
self.updateHeight(animated)
}
}
}
@objc func editableTextNodeShouldReturn(_ editableTextNode: ASEditableTextNode) -> Bool {
if self.actionButtons.sendButton.supernode != nil && !self.actionButtons.sendButton.isHidden && !self.actionButtons.sendButton.alpha.isZero {
self.sendButtonPressed()
}
return false
}
private func applyUpdateSendButtonIcon() {
if let interfaceState = self.presentationInterfaceState {
let sendButtonHasApplyIcon = interfaceState.interfaceState.editMessage != nil
if sendButtonHasApplyIcon != self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButtonHasApplyIcon = sendButtonHasApplyIcon
if self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyButtonImage(interfaceState.theme), for: [])
} else {
if case .scheduledMessages = interfaceState.subject {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelScheduleButtonImage(interfaceState.theme), for: [])
} else {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(interfaceState.theme), for: [])
}
}
}
}
}
@objc func editableTextNodeDidChangeSelection(_ editableTextNode: ASEditableTextNode, fromSelectedRange: NSRange, toSelectedRange: NSRange, dueToEditing: Bool) {
if !dueToEditing && !self.updatingInputState {
let inputTextState = self.inputTextState
self.interfaceInteraction?.updateTextInputStateAndMode({ _, inputMode in return (inputTextState, inputMode) })
}
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState {
if case .format = self.inputMenu.state {
self.inputMenu.deactivate()
UIMenuController.shared.update()
}
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
refreshChatTextInputTypingAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
}
}
@objc func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) {
self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in
return (.text, state.keyboardButtonsMessage?.id)
})
self.inputMenu.activate()
}
func editableTextNodeDidFinishEditing(_ editableTextNode: ASEditableTextNode) {
self.storedInputLanguage = editableTextNode.textInputMode.primaryLanguage
self.inputMenu.deactivate()
}
func editableTextNodeTarget(forAction action: Selector) -> ASEditableTextNodeTargetForAction? {
if action == Selector(("_accessibilitySpeak:")) {
if case .format = self.inputMenu.state {
return ASEditableTextNodeTargetForAction(target: nil)
} else if let textInputNode = self.textInputNode, textInputNode.selectedRange.length > 0 {
return ASEditableTextNodeTargetForAction(target: self)
} else {
return ASEditableTextNodeTargetForAction(target: nil)
}
} else if action == Selector(("_accessibilitySpeakSpellOut:")) {
if case .format = self.inputMenu.state {
return ASEditableTextNodeTargetForAction(target: nil)
} else if let textInputNode = self.textInputNode, textInputNode.selectedRange.length > 0 {
return nil
} else {
return ASEditableTextNodeTargetForAction(target: nil)
}
}
else if action == Selector("_accessibilitySpeakLanguageSelection:") || action == Selector("_accessibilityPauseSpeaking:") || action == Selector("_accessibilitySpeakSentence:") {
return ASEditableTextNodeTargetForAction(target: nil)
} else if action == Selector(("_showTextStyleOptions:")) {
if case .general = self.inputMenu.state {
if let textInputNode = self.textInputNode, textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 {
return ASEditableTextNodeTargetForAction(target: nil)
}
return ASEditableTextNodeTargetForAction(target: self)
} else {
return ASEditableTextNodeTargetForAction(target: nil)
}
} else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) {
if case .format = self.inputMenu.state {
return ASEditableTextNodeTargetForAction(target: self)
} else {
return ASEditableTextNodeTargetForAction(target: nil)
}
}
if case .format = self.inputMenu.state {
return ASEditableTextNodeTargetForAction(target: nil)
}
return nil
}
@objc func _accessibilitySpeak(_ sender: Any) {
var text = ""
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
text = current.inputText.attributedSubstring(from: NSMakeRange(current.selectionRange.lowerBound, current.selectionRange.count)).string
return (current, inputMode)
}
speakText(text)
if #available(iOS 13.0, *) {
UIMenuController.shared.hideMenu()
} else {
UIMenuController.shared.isMenuVisible = false
UIMenuController.shared.update()
}
}
@objc func _showTextStyleOptions(_ sender: Any) {
if let textInputNode = self.textInputNode {
self.inputMenu.format(view: textInputNode.view, rect: textInputNode.selectionRect.offsetBy(dx: 0.0, dy: -textInputNode.textView.contentOffset.y).insetBy(dx: 0.0, dy: -1.0))
}
}
@objc func formatAttributesBold(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.bold), inputMode)
}
}
@objc func formatAttributesItalic(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.italic), inputMode)
}
}
@objc func formatAttributesMonospace(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.monospace), inputMode)
}
}
@objc func formatAttributesLink(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.openLinkEditing()
}
@objc func formatAttributesStrikethrough(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.strikethrough), inputMode)
}
}
@objc func formatAttributesUnderline(_ sender: Any) {
self.inputMenu.back()
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.underline), inputMode)
}
}
@objc func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
var cleanText = text
let removeSequences: [String] = ["\u{202d}", "\u{202c}"]
for sequence in removeSequences {
inner: while true {
if let range = cleanText.range(of: sequence) {
cleanText.removeSubrange(range)
} else {
break inner
}
}
}
if cleanText != text {
let string = NSMutableAttributedString(attributedString: editableTextNode.attributedText ?? NSAttributedString())
var textColor: UIColor = .black
var accentTextColor: UIColor = .blue
var baseFontSize: CGFloat = 17.0
if let presentationInterfaceState = self.presentationInterfaceState {
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
accentTextColor = presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
}
let cleanReplacementString = textAttributedStringForStateText(NSAttributedString(string: cleanText), fontSize: baseFontSize, textColor: textColor, accentTextColor: accentTextColor, writingDirection: nil)
string.replaceCharacters(in: range, with: cleanReplacementString)
self.textInputNode?.attributedText = string
self.textInputNode?.selectedRange = NSMakeRange(range.lowerBound + cleanReplacementString.length, 0)
self.updateTextNodeText(animated: true)
return false
}
return true
}
@objc func editableTextNodeShouldCopy(_ editableTextNode: ASEditableTextNode) -> Bool {
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
storeInputTextInPasteboard(current.inputText.attributedSubstring(from: NSMakeRange(current.selectionRange.lowerBound, current.selectionRange.count)))
return (current, inputMode)
}
return false
}
@objc func editableTextNodeShouldPaste(_ editableTextNode: ASEditableTextNode) -> Bool {
let pasteboard = UIPasteboard.general
var attributedString: NSAttributedString?
if let data = pasteboard.data(forPasteboardType: kUTTypeRTF as String) {
attributedString = chatInputStateStringFromRTF(data, type: NSAttributedString.DocumentType.rtf)
} else if let data = pasteboard.data(forPasteboardType: "com.apple.flat-rtfd") {
attributedString = chatInputStateStringFromRTF(data, type: NSAttributedString.DocumentType.rtfd)
}
if let attributedString = attributedString {
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
if let inputText = current.inputText.mutableCopy() as? NSMutableAttributedString {
inputText.replaceCharacters(in: NSMakeRange(current.selectionRange.lowerBound, current.selectionRange.count), with: attributedString)
let updatedRange = current.selectionRange.lowerBound + attributedString.length
return (ChatTextInputState(inputText: inputText, selectionRange: updatedRange ..< updatedRange), inputMode)
} else {
return (ChatTextInputState(inputText: attributedString), inputMode)
}
}
return false
}
return true
}
@objc func sendButtonPressed() {
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState, let editMessage = presentationInterfaceState.interfaceState.editMessage, let inputTextMaxLength = editMessage.inputTextMaxLength {
let textCount = Int32(textInputNode.textView.text.count)
let remainingCount = inputTextMaxLength - textCount
if remainingCount < 0 {
textInputNode.layer.addShakeAnimation()
self.hapticFeedback.error()
return
}
}
self.sendMessage()
}
@objc func textInputBackgroundViewTap(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.ensureFocused()
}
}
var isFocused: Bool {
return self.textInputNode?.isFirstResponder() ?? false
}
func ensureUnfocused() {
self.textInputNode?.resignFirstResponder()
}
func ensureFocused() {
if self.textInputNode == nil {
self.loadTextInputNode()
}
self.textInputNode?.becomeFirstResponder()
}
func frameForInputActionButton() -> CGRect? {
if !self.actionButtons.alpha.isZero {
if self.actionButtons.micButton.alpha.isZero {
return self.actionButtons.frame.insetBy(dx: 0.0, dy: 6.0).offsetBy(dx: 4.0, dy: 0.0)
} else {
return self.actionButtons.frame.insetBy(dx: 0.0, dy: 6.0).offsetBy(dx: 2.0, dy: 0.0)
}
}
return nil
}
}

View File

@ -645,6 +645,10 @@ public final class OngoingGroupCallContext {
}
})
}
func addExternalAudioData(data: Data) {
self.context.addExternalAudioData(data)
}
}
private let queue = Queue()
@ -804,4 +808,10 @@ public final class OngoingGroupCallContext {
impl.makeIncomingVideoView(endpointId: endpointId, requestClone: requestClone, completion: completion)
}
}
public func addExternalAudioData(data: Data) {
self.impl.with { impl in
impl.addExternalAudioData(data: data)
}
}
}

View File

@ -142,7 +142,7 @@ private final class FdWriteConnection {
private let buffer: UnsafeMutableRawPointer
private var currentData: PendingData?
private var nextData: Data?
private var nextDataList: [Data] = []
init(queue: Queue, fd: Int32) {
assert(queue.isCurrent())
@ -182,8 +182,8 @@ private final class FdWriteConnection {
if currentData.offset == currentData.data.count {
strongSelf.currentData = nil
if let nextData = strongSelf.nextData {
strongSelf.nextData = nil
if !strongSelf.nextDataList.isEmpty {
let nextData = strongSelf.nextDataList.removeFirst()
strongSelf.currentData = PendingData(data: nextData)
} else {
strongSelf.channel.suspend()
@ -217,11 +217,17 @@ private final class FdWriteConnection {
free(self.buffer)
}
func replaceData(data: Data) {
func addData(data: Data) {
if self.currentData == nil {
self.currentData = PendingData(data: data)
} else {
self.nextData = data
var totalBytes = 0
for data in self.nextDataList {
totalBytes += data.count
}
if totalBytes < 1 * 1024 * 1024 {
self.nextDataList.append(data)
}
}
if !self.isResumed {
@ -274,11 +280,11 @@ private final class NamedPipeWriterImpl {
}
}
func replaceData(data: Data) {
func addData(data: Data) {
guard let connection = self.connection else {
return
}
connection.replaceData(data: data)
connection.addData(data: data)
}
}
@ -293,9 +299,9 @@ private final class NamedPipeWriter {
})
}
func replaceData(data: Data) {
func addData(data: Data) {
self.impl.with { impl in
impl.replaceData(data: data)
impl.addData(data: data)
}
}
}
@ -363,7 +369,7 @@ private final class MappedFile {
public final class IpcGroupCallBufferAppContext {
private let basePath: String
private let server: NamedPipeReader
private var audioServer: NamedPipeReader?
private let id: UInt32
@ -378,6 +384,11 @@ public final class IpcGroupCallBufferAppContext {
return self.framesPipe.signal()
}
private let audioDataPipe = ValuePipe<Data>()
public var audioData: Signal<Data, NoError> {
return self.audioDataPipe.signal()
}
private var framePollTimer: SwiftSignalKit.Timer?
private var mappedFile: MappedFile?
@ -389,12 +400,8 @@ public final class IpcGroupCallBufferAppContext {
self.id = UInt32.random(in: 0 ..< UInt32.max)
let framesPipe = self.framesPipe
self.server = NamedPipeReader(path: broadcastAppSocketPath(basePath: basePath), didRead: { data in
//framesPipe.putNext(data)
})
let dataPath = broadcastAppSocketPath(basePath: basePath) + "-data-\(self.id)"
let audioDataPath = broadcastAppSocketPath(basePath: basePath) + "-audio-\(self.id)"
if let mappedFile = MappedFile(path: dataPath, createIfNotExists: true) {
self.mappedFile = mappedFile
@ -403,6 +410,11 @@ public final class IpcGroupCallBufferAppContext {
}
}
let audioDataPipe = self.audioDataPipe
self.audioServer = NamedPipeReader(path: audioDataPath, didRead: { data in
audioDataPipe.putNext(data)
})
let framePollTimer = SwiftSignalKit.Timer(timeout: 1.0 / 30.0, repeat: true, completion: { [weak self] in
guard let strongSelf = self, let mappedFile = strongSelf.mappedFile else {
return
@ -515,6 +527,7 @@ public final class IpcGroupCallBufferBroadcastContext {
private var mappedFile: MappedFile?
private var currentId: UInt32?
private var audioClient: NamedPipeWriter?
private var callActiveInfoTimer: SwiftSignalKit.Timer?
private var keepaliveInfoTimer: SwiftSignalKit.Timer?
@ -589,6 +602,7 @@ public final class IpcGroupCallBufferBroadcastContext {
self.currentId = payloadDescription.id
let dataPath = broadcastAppSocketPath(basePath: basePath) + "-data-\(payloadDescription.id)"
let audioDataPath = broadcastAppSocketPath(basePath: basePath) + "-audio-\(payloadDescription.id)"
if let mappedFile = MappedFile(path: dataPath, createIfNotExists: false) {
self.mappedFile = mappedFile
@ -597,6 +611,8 @@ public final class IpcGroupCallBufferBroadcastContext {
}
}
self.audioClient = NamedPipeWriter(path: audioDataPath)
self.writeKeepaliveInfo()
let keepaliveInfoTimer = SwiftSignalKit.Timer(timeout: 1.0, repeat: true, completion: { [weak self] in
@ -608,8 +624,6 @@ public final class IpcGroupCallBufferBroadcastContext {
}
public func setCurrentFrame(data: Data, orientation: CGImagePropertyOrientation) {
//let _ = try? data.write(to: URL(fileURLWithPath: dataPath), options: [])
if let mappedFile = self.mappedFile, mappedFile.size >= data.count {
let _ = data.withUnsafeBytes { bytes in
var orientationValue = Int32(bitPattern: orientation.rawValue)
@ -617,8 +631,10 @@ public final class IpcGroupCallBufferBroadcastContext {
memcpy(mappedFile.memory.advanced(by: 4), bytes.baseAddress!, data.count)
}
}
}
//self.client.replaceData(data: data)
public func writeAudioData(data: Data) {
self.audioClient?.addData(data: data)
}
private func writeKeepaliveInfo() {

View File

@ -290,6 +290,8 @@ typedef NS_ENUM(int32_t, OngoingGroupCallRequestedVideoQuality) {
- (void)switchAudioInput:(NSString * _Nonnull)deviceId;
- (void)makeIncomingVideoViewWithEndpointId:(NSString * _Nonnull)endpointId requestClone:(bool)requestClone completion:(void (^_Nonnull)(UIView<OngoingCallThreadLocalContextWebrtcVideoView> * _Nullable, UIView<OngoingCallThreadLocalContextWebrtcVideoView> * _Nullable))completion;
- (void)addExternalAudioData:(NSData * _Nonnull)data;
@end
#endif

View File

@ -1121,10 +1121,9 @@ private:
}
std::vector<tgcalls::VideoCodecName> videoCodecPreferences;
videoCodecPreferences.push_back(tgcalls::VideoCodecName::VP8);
//videoCodecPreferences.push_back(tgcalls::VideoCodecName::VP9);
int minOutgoingVideoBitrateKbit = 500;
bool disableOutgoingAudioProcessing = false;
tgcalls::GroupConfig config;
config.need_log = false;
@ -1196,6 +1195,7 @@ private:
return std::make_shared<BroadcastPartTaskImpl>(task);
},
.outgoingAudioBitrateKbit = outgoingAudioBitrateKbit,
.disableOutgoingAudioProcessing = disableOutgoingAudioProcessing,
.videoContentType = _videoContentType,
.videoCodecPreferences = videoCodecPreferences,
.initialEnableNoiseSuppression = enableNoiseSuppression,
@ -1477,6 +1477,15 @@ private:
}
}
- (void)addExternalAudioData:(NSData * _Nonnull)data {
if (_instance) {
std::vector<uint8_t> samples;
samples.resize(data.length);
[data getBytes:samples.data() length:data.length];
_instance->addExternalAudioSamples(std::move(samples));
}
}
@end
@implementation OngoingGroupCallMediaChannelDescription

@ -1 +1 @@
Subproject commit 6ec339fd301781a4087ca1710814617e3502eec6
Subproject commit f6251ca48df94296d63272ee9b155eec2d7964b2

View File

@ -192,12 +192,12 @@ genrule(
PATH="$$PATH:$$YASM_DIR" "$$SOURCE_PATH/build-ffmpeg-bazel.sh" "$$VARIANT" "$$BUILD_ARCH" "$$BUILD_DIR" "$$SOURCE_PATH"
""" + "\n" + "\n".join([
"cp \"$$BUILD_DIR/FFmpeg-iOS/include/{header_path}\" \"$(location Public/ffmpeg/{header_path})\"".format(header_path = header_path) for header_path in ffmpeg_header_paths
"cp \"$$BUILD_DIR/FFmpeg-iOS/include/{header_path}\" \"$(location Public/third_party/ffmpeg/{header_path})\"".format(header_path = header_path) for header_path in ffmpeg_header_paths
]) + "\n" + "\n".join([
"cp \"$$BUILD_DIR/FFmpeg-iOS/lib/{lib}\" \"$(location {lib})\"".format(lib = lib) for lib in ffmpeg_libs
]),
outs = [
"Public/ffmpeg/{}".format(header_path) for header_path in ffmpeg_header_paths
"Public/third_party/ffmpeg/{}".format(header_path) for header_path in ffmpeg_header_paths
] + ffmpeg_libs,
tools = [
"//third-party/yasm:yasm.tar",
@ -219,9 +219,10 @@ objc_library(
name = "ffmpeg",
module_name = "ffmpeg",
enable_modules = True,
hdrs = ["Public/ffmpeg/" + x for x in ffmpeg_header_paths],
hdrs = ["Public/third_party/ffmpeg/" + x for x in ffmpeg_header_paths],
includes = [
"Public/ffmpeg",
"Public",
"Public/third_party/ffmpeg",
],
sdk_dylibs = [
"libbz2",

View File

@ -57,6 +57,8 @@ CONFIGURE_FLAGS="--enable-cross-compile --disable-programs \
#--enable-hwaccel=h264_videotoolbox,hevc_videotoolbox \
EXTRA_CFLAGS="-DCONFIG_SAFE_BITSTREAM_READER=1"
if [ "$1" = "debug" ];
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --disable-optimizations --disable-stripping"
@ -121,7 +123,7 @@ then
LIBOPUS_PATH="$SOURCE_DIR/libopus"
CFLAGS="-arch $ARCH"
CFLAGS="$EXTRA_CFLAGS -arch $ARCH"
if [ "$RAW_ARCH" = "i386" -o "$RAW_ARCH" = "x86_64" ]
then
PLATFORM="iPhoneSimulator"

@ -1 +1 @@
Subproject commit 76a4e44563bcf0ec8917d9bf805d28040d371de4
Subproject commit 3a38edea2cd114d53914cab017cab2e43a600031

270
third-party/openh264/BUILD vendored Normal file
View File

@ -0,0 +1,270 @@
arm64_specific_sources = [
"third_party/openh264/src/codec/encoder/core/arm64/intra_pred_aarch64_neon.S",
"third_party/openh264/src/codec/encoder/core/arm64/intra_pred_sad_3_opt_aarch64_neon.S",
"third_party/openh264/src/codec/encoder/core/arm64/memory_aarch64_neon.S",
"third_party/openh264/src/codec/encoder/core/arm64/pixel_aarch64_neon.S",
"third_party/openh264/src/codec/encoder/core/arm64/reconstruct_aarch64_neon.S",
"third_party/openh264/src/codec/encoder/core/arm64/svc_motion_estimation_aarch64_neon.S",
"third_party/openh264/src/codec/common/arm64/copy_mb_aarch64_neon.S",
"third_party/openh264/src/codec/common/arm64/deblocking_aarch64_neon.S",
"third_party/openh264/src/codec/common/arm64/expand_picture_aarch64_neon.S",
"third_party/openh264/src/codec/common/arm64/intra_pred_common_aarch64_neon.S",
"third_party/openh264/src/codec/common/arm64/mc_aarch64_neon.S",
"third_party/openh264/src/codec/processing/src/arm64/adaptive_quantization_aarch64_neon.S",
"third_party/openh264/src/codec/processing/src/arm64/down_sample_aarch64_neon.S",
"third_party/openh264/src/codec/processing/src/arm64/pixel_sad_aarch64_neon.S",
"third_party/openh264/src/codec/processing/src/arm64/vaa_calc_aarch64_neon.S",
]
arm64_specific_textual_hdrs = [
"third_party/openh264/src/codec/common/arm64/arm_arch64_common_macro.S",
]
arm_specific_sources = [
"third_party/openh264/src/codec/encoder/core/arm/intra_pred_neon.S",
"third_party/openh264/src/codec/encoder/core/arm/intra_pred_sad_3_opt_neon.S",
"third_party/openh264/src/codec/encoder/core/arm/memory_neon.S",
"third_party/openh264/src/codec/encoder/core/arm/pixel_neon.S",
"third_party/openh264/src/codec/encoder/core/arm/reconstruct_neon.S",
"third_party/openh264/src/codec/encoder/core/arm/svc_motion_estimation.S",
"third_party/openh264/src/codec/common/arm/copy_mb_neon.S",
"third_party/openh264/src/codec/common/arm/deblocking_neon.S",
"third_party/openh264/src/codec/common/arm/expand_picture_neon.S",
"third_party/openh264/src/codec/common/arm/intra_pred_common_neon.S",
"third_party/openh264/src/codec/common/arm/mc_neon.S",
"third_party/openh264/src/codec/processing/src/arm/adaptive_quantization.S",
"third_party/openh264/src/codec/processing/src/arm/down_sample_neon.S",
"third_party/openh264/src/codec/processing/src/arm/pixel_sad_neon.S",
"third_party/openh264/src/codec/processing/src/arm/vaa_calc_neon.S",
]
arm_specific_textual_hdrs = [
"third_party/openh264/third_party/openh264/src/codec/common/arm/arm_arch_common_macro.S",
]
arm64_specific_copts = [
"-DHAVE_NEON_AARCH64=1",
"-Ithird-party/openh264/third_party/openh264/src/codec/common/arm64",
]
arm_specific_copts = [
"-DHAVE_NEON=1",
"-Ithird-party/openh264/third_party/openh264/src/codec/common/arm",
]
arch_specific_sources = select({
"@build_bazel_rules_apple//apple:ios_armv7": arm_specific_sources,
"@build_bazel_rules_apple//apple:ios_arm64": arm64_specific_sources,
"//build-system:ios_sim_arm64": arm64_specific_sources,
"@build_bazel_rules_apple//apple:ios_x86_64": [],
})
arch_specific_copts = select({
"@build_bazel_rules_apple//apple:ios_armv7": arm_specific_copts,
"@build_bazel_rules_apple//apple:ios_arm64": arm64_specific_copts,
"//build-system:ios_sim_arm64": arm64_specific_copts,
"@build_bazel_rules_apple//apple:ios_x86_64": [],
})
arch_specific_textual_hdrs = select({
"@build_bazel_rules_apple//apple:ios_armv7": arm_specific_textual_hdrs,
"@build_bazel_rules_apple//apple:ios_arm64": arm64_specific_textual_hdrs,
"//build-system:ios_sim_arm64": arm64_specific_textual_hdrs,
"@build_bazel_rules_apple//apple:ios_x86_64": [],
})
all_sources = arch_specific_sources + [
"third_party/openh264/src/codec/encoder/core/inc/as264_common.h",
"third_party/openh264/src/codec/encoder/core/inc/au_set.h",
"third_party/openh264/src/codec/encoder/core/inc/deblocking.h",
"third_party/openh264/src/codec/encoder/core/inc/decode_mb_aux.h",
"third_party/openh264/src/codec/encoder/core/inc/dq_map.h",
"third_party/openh264/src/codec/encoder/core/inc/encode_mb_aux.h",
"third_party/openh264/src/codec/encoder/core/inc/encoder_context.h",
"third_party/openh264/src/codec/encoder/core/inc/encoder.h",
"third_party/openh264/src/codec/encoder/core/inc/extern.h",
"third_party/openh264/src/codec/encoder/core/inc/get_intra_predictor.h",
"third_party/openh264/src/codec/encoder/core/inc/mb_cache.h",
"third_party/openh264/src/codec/encoder/core/inc/md.h",
"third_party/openh264/src/codec/encoder/core/inc/mt_defs.h",
"third_party/openh264/src/codec/encoder/core/inc/mv_pred.h",
"third_party/openh264/src/codec/encoder/core/inc/nal_encap.h",
"third_party/openh264/src/codec/encoder/core/inc/param_svc.h",
"third_party/openh264/src/codec/encoder/core/inc/parameter_sets.h",
"third_party/openh264/src/codec/encoder/core/inc/paraset_strategy.h",
"third_party/openh264/src/codec/encoder/core/inc/picture_handle.h",
"third_party/openh264/src/codec/encoder/core/inc/picture.h",
"third_party/openh264/src/codec/encoder/core/inc/rc.h",
"third_party/openh264/src/codec/encoder/core/inc/ref_list_mgr_svc.h",
"third_party/openh264/src/codec/encoder/core/inc/sample.h",
"third_party/openh264/src/codec/encoder/core/inc/set_mb_syn_cabac.h",
"third_party/openh264/src/codec/encoder/core/inc/set_mb_syn_cavlc.h",
"third_party/openh264/src/codec/encoder/core/inc/slice_multi_threading.h",
"third_party/openh264/src/codec/encoder/core/inc/slice.h",
"third_party/openh264/src/codec/encoder/core/inc/stat.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_base_layer_md.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_enc_frame.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_enc_golomb.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_enc_macroblock.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_enc_slice_segment.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_encode_mb.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_encode_slice.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_mode_decision.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_motion_estimate.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_set_mb_syn_cavlc.h",
"third_party/openh264/src/codec/encoder/core/inc/svc_set_mb_syn.h",
"third_party/openh264/src/codec/encoder/core/inc/vlc_encoder.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_common_basis.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_const.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_func_ptr_def.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_preprocess.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_task_base.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_task_encoder.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_task_management.h",
"third_party/openh264/src/codec/encoder/core/inc/wels_transpose_matrix.h",
"third_party/openh264/src/codec/common/inc/crt_util_safe_x.h",
"third_party/openh264/src/codec/common/inc/typedefs.h",
"third_party/openh264/src/codec/common/inc/utils.h",
"third_party/openh264/src/codec/api/svc/codec_app_def.h",
"third_party/openh264/src/codec/api/svc/codec_def.h",
"third_party/openh264/src/codec/api/svc/codec_api.h",
"third_party/openh264/src/codec/common/inc/WelsTask.h",
"third_party/openh264/src/codec/common/inc/macros.h",
"third_party/openh264/src/codec/common/inc/wels_const_common.h",
"third_party/openh264/src/codec/common/inc/wels_common_defs.h",
"third_party/openh264/src/codec/common/inc/memory_align.h",
"third_party/openh264/src/codec/common/inc/expand_pic.h",
"third_party/openh264/src/codec/common/inc/mc.h",
"third_party/openh264/src/codec/common/inc/cpu_core.h",
"third_party/openh264/src/codec/common/inc/WelsThreadLib.h",
"third_party/openh264/src/codec/common/inc/WelsLock.h",
"third_party/openh264/src/codec/common/inc/WelsThreadPool.h",
"third_party/openh264/src/codec/common/inc/WelsTaskThread.h",
"third_party/openh264/src/codec/common/inc/WelsThread.h",
"third_party/openh264/src/codec/common/inc/WelsList.h",
"third_party/openh264/src/codec/common/inc/copy_mb.h",
"third_party/openh264/src/codec/common/inc/golomb_common.h",
"third_party/openh264/src/codec/common/inc/ls_defines.h",
"third_party/openh264/src/codec/common/inc/measure_time.h",
"third_party/openh264/src/codec/common/inc/deblocking_common.h",
"third_party/openh264/src/codec/common/inc/cpu.h",
"third_party/openh264/src/codec/api/svc/codec_ver.h",
"third_party/openh264/src/codec/common/inc/intra_pred_common.h",
"third_party/openh264/src/codec/common/inc/sad_common.h",
] + [
"third_party/openh264/src/codec/encoder/core/src/au_set.cpp",
"third_party/openh264/src/codec/encoder/core/src/deblocking.cpp",
"third_party/openh264/src/codec/encoder/core/src/decode_mb_aux.cpp",
"third_party/openh264/src/codec/encoder/core/src/encode_mb_aux.cpp",
"third_party/openh264/src/codec/encoder/core/src/encoder_data_tables.cpp",
"third_party/openh264/src/codec/encoder/core/src/encoder_ext.cpp",
"third_party/openh264/src/codec/encoder/core/src/encoder.cpp",
"third_party/openh264/src/codec/encoder/core/src/get_intra_predictor.cpp",
"third_party/openh264/src/codec/encoder/core/src/md.cpp",
"third_party/openh264/src/codec/encoder/core/src/mv_pred.cpp",
"third_party/openh264/src/codec/encoder/core/src/nal_encap.cpp",
"third_party/openh264/src/codec/encoder/core/src/paraset_strategy.cpp",
"third_party/openh264/src/codec/encoder/core/src/picture_handle.cpp",
"third_party/openh264/src/codec/encoder/core/src/ratectl.cpp",
"third_party/openh264/src/codec/encoder/core/src/ref_list_mgr_svc.cpp",
"third_party/openh264/src/codec/encoder/core/src/sample.cpp",
"third_party/openh264/src/codec/encoder/core/src/set_mb_syn_cabac.cpp",
"third_party/openh264/src/codec/encoder/core/src/set_mb_syn_cavlc.cpp",
"third_party/openh264/src/codec/encoder/core/src/slice_multi_threading.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_base_layer_md.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_enc_slice_segment.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_encode_mb.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_encode_slice.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_mode_decision.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_motion_estimate.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_set_mb_syn_cabac.cpp",
"third_party/openh264/src/codec/encoder/core/src/svc_set_mb_syn_cavlc.cpp",
"third_party/openh264/src/codec/encoder/core/src/wels_preprocess.cpp",
"third_party/openh264/src/codec/encoder/core/src/wels_task_base.cpp",
"third_party/openh264/src/codec/encoder/core/src/wels_task_encoder.cpp",
"third_party/openh264/src/codec/encoder/core/src/wels_task_management.cpp",
] + [
"third_party/openh264/src/codec/encoder/plus/inc/welsEncoderExt.h",
"third_party/openh264/src/codec/common/inc/version.h",
"third_party/openh264/src/codec/common/inc/welsCodecTrace.h",
"third_party/openh264/src/codec/common/inc/asmdefs_mmi.h",
] + [
"third_party/openh264/src/codec/encoder/plus/src/welsEncoderExt.cpp",
"third_party/openh264/src/codec/common/src/welsCodecTrace.cpp",
"third_party/openh264/src/codec/common/src/common_tables.cpp",
"third_party/openh264/src/codec/common/src/copy_mb.cpp",
"third_party/openh264/src/codec/common/src/cpu.cpp",
"third_party/openh264/src/codec/common/src/crt_util_safe_x.cpp",
"third_party/openh264/src/codec/common/src/deblocking_common.cpp",
"third_party/openh264/src/codec/common/src/expand_pic.cpp",
"third_party/openh264/src/codec/common/src/intra_pred_common.cpp",
"third_party/openh264/src/codec/common/src/mc.cpp",
"third_party/openh264/src/codec/common/src/memory_align.cpp",
"third_party/openh264/src/codec/common/src/sad_common.cpp",
"third_party/openh264/src/codec/common/src/WelsTaskThread.cpp",
"third_party/openh264/src/codec/common/src/WelsThread.cpp",
"third_party/openh264/src/codec/common/src/WelsThreadLib.cpp",
"third_party/openh264/src/codec/common/src/WelsThreadPool.cpp",
"third_party/openh264/src/codec/common/src/utils.cpp",
] + [
"third_party/openh264/src/codec/processing/interface/IWelsVP.h",
"third_party/openh264/src/codec/processing/src/adaptivequantization/AdaptiveQuantization.cpp",
"third_party/openh264/src/codec/processing/src/adaptivequantization/AdaptiveQuantization.h",
"third_party/openh264/src/codec/processing/src/backgrounddetection/BackgroundDetection.cpp",
"third_party/openh264/src/codec/processing/src/backgrounddetection/BackgroundDetection.h",
"third_party/openh264/src/codec/processing/src/common/common.h",
"third_party/openh264/src/codec/processing/src/common/memory.cpp",
"third_party/openh264/src/codec/processing/src/common/memory.h",
"third_party/openh264/src/codec/processing/src/common/resource.h",
"third_party/openh264/src/codec/processing/src/common/typedef.h",
"third_party/openh264/src/codec/processing/src/common/util.h",
"third_party/openh264/src/codec/processing/src/common/WelsFrameWork.cpp",
"third_party/openh264/src/codec/processing/src/common/WelsFrameWork.h",
"third_party/openh264/src/codec/processing/src/common/WelsFrameWorkEx.cpp",
"third_party/openh264/src/codec/processing/src/complexityanalysis/ComplexityAnalysis.cpp",
"third_party/openh264/src/codec/processing/src/complexityanalysis/ComplexityAnalysis.h",
"third_party/openh264/src/codec/processing/src/denoise/denoise.cpp",
"third_party/openh264/src/codec/processing/src/denoise/denoise_filter.cpp",
"third_party/openh264/src/codec/processing/src/denoise/denoise.h",
"third_party/openh264/src/codec/processing/src/downsample/downsample.cpp",
"third_party/openh264/src/codec/processing/src/downsample/downsample.h",
"third_party/openh264/src/codec/processing/src/downsample/downsamplefuncs.cpp",
"third_party/openh264/src/codec/processing/src/imagerotate/imagerotate.cpp",
"third_party/openh264/src/codec/processing/src/imagerotate/imagerotate.h",
"third_party/openh264/src/codec/processing/src/imagerotate/imagerotatefuncs.cpp",
"third_party/openh264/src/codec/processing/src/scenechangedetection/SceneChangeDetection.cpp",
"third_party/openh264/src/codec/processing/src/scenechangedetection/SceneChangeDetection.h",
"third_party/openh264/src/codec/processing/src/scrolldetection/ScrollDetection.cpp",
"third_party/openh264/src/codec/processing/src/scrolldetection/ScrollDetection.h",
"third_party/openh264/src/codec/processing/src/scrolldetection/ScrollDetectionFuncs.cpp",
"third_party/openh264/src/codec/processing/src/scrolldetection/ScrollDetectionFuncs.h",
"third_party/openh264/src/codec/processing/src/vaacalc/vaacalcfuncs.cpp",
"third_party/openh264/src/codec/processing/src/vaacalc/vaacalculation.cpp",
"third_party/openh264/src/codec/processing/src/vaacalc/vaacalculation.h",
]
cc_library(
name = "openh264",
srcs = all_sources,
hdrs = glob([
]),
textual_hdrs = arch_specific_textual_hdrs,
includes = [
],
copts = arch_specific_copts + [
"-Ithird-party/openh264/third_party/openh264/src/codec/encoder/core/inc",
"-Ithird-party/openh264/third_party/openh264/src/codec/encoder/plus/inc",
"-Ithird-party/openh264/third_party/openh264/src/codec/decoder/plus/inc",
"-Ithird-party/openh264/third_party/openh264/src/codec/common/inc",
"-Ithird-party/openh264/third_party/openh264/src/codec/api/svc",
"-Ithird-party/openh264/third_party/openh264/src/codec/processing/interface",
"-Ithird-party/openh264/third_party/openh264/src/codec/processing/src/common",
"-Os",
],
deps = [
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1 @@
subdir ('svc')

View File

@ -0,0 +1,592 @@
/*!
*@page License
*
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WELS_VIDEO_CODEC_SVC_API_H__
#define WELS_VIDEO_CODEC_SVC_API_H__
#ifndef __cplusplus
#if defined(_MSC_VER) && (_MSC_VER < 1800)
typedef unsigned char bool;
#else
#include <stdbool.h>
#endif
#endif
#include "codec_app_def.h"
#include "codec_def.h"
#if defined(_WIN32) || defined(__cdecl)
#define EXTAPI __cdecl
#else
#define EXTAPI
#endif
/**
* @file codec_api.h
*/
/**
* @page Overview
* * This page is for openh264 codec API usage.
* * For how to use the encoder,please refer to page UsageExampleForEncoder
* * For how to use the decoder,please refer to page UsageExampleForDecoder
* * For more detail about ISVEncoder,please refer to page ISVCEncoder
* * For more detail about ISVDecoder,please refer to page ISVCDecoder
*/
/**
* @page DecoderUsageExample
*
* @brief
* * An example for using the decoder for Decoding only or Parsing only
*
* Step 1:decoder declaration
* @code
*
* //decoder declaration
* ISVCDecoder *pSvcDecoder;
* //input: encoded bitstream start position; should include start code prefix
* unsigned char *pBuf =...;
* //input: encoded bit stream length; should include the size of start code prefix
* int iSize =...;
* //output: [0~2] for Y,U,V buffer for Decoding only
* unsigned char *pData[3] =...;
* //in-out: for Decoding only: declare and initialize the output buffer info, this should never co-exist with Parsing only
* SBufferInfo sDstBufInfo;
* memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
* //in-out: for Parsing only: declare and initialize the output bitstream buffer info for parse only, this should never co-exist with Decoding only
* SParserBsInfo sDstParseInfo;
* memset(&sDstParseInfo, 0, sizeof(SParserBsInfo));
* sDstParseInfo.pDstBuff = new unsigned char[PARSE_SIZE]; //In Parsing only, allocate enough buffer to save transcoded bitstream for a frame
*
* @endcode
*
* Step 2:decoder creation
* @code
* WelsCreateDecoder(&pSvcDecoder);
* @endcode
*
* Step 3:declare required parameter, used to differentiate Decoding only and Parsing only
* @code
* SDecodingParam sDecParam = {0};
* sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
* //for Parsing only, the assignment is mandatory
* sDecParam.bParseOnly = true;
* @endcode
*
* Step 4:initialize the parameter and decoder context, allocate memory
* @code
* pSvcDecoder->Initialize(&sDecParam);
* @endcode
*
* Step 5:do actual decoding process in slice level;
* this can be done in a loop until data ends
* @code
* //for Decoding only
* iRet = pSvcDecoder->DecodeFrameNoDelay(pBuf, iSize, pData, &sDstBufInfo);
* //or
* iRet = pSvcDecoder->DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
* //for Parsing only
* iRet = pSvcDecoder->DecodeParser(pBuf, iSize, &sDstParseInfo);
* //decode failed
* If (iRet != 0){
* //error handling (RequestIDR or something like that)
* }
* //for Decoding only, pData can be used for render.
* if (sDstBufInfo.iBufferStatus==1){
* //output handling (pData[0], pData[1], pData[2])
* }
* //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
* if (sDstBufInfo.iNalNum > 0){
* //Hardware decoding sDstParseInfo;
* }
* //no-delay decoding can be realized by directly calling DecodeFrameNoDelay(), which is the recommended usage.
* //no-delay decoding can also be realized by directly calling DecodeFrame2() again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
* iRet = pSvcDecoder->DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
* //judge iRet, sDstBufInfo.iBufferStatus ...
* @endcode
*
* Step 6:uninitialize the decoder and memory free
* @code
* pSvcDecoder->Uninitialize();
* @endcode
*
* Step 7:destroy the decoder
* @code
* DestroyDecoder(pSvcDecoder);
* @endcode
*
*/
/**
* @page EncoderUsageExample1
*
* @brief
* * An example for using encoder with basic parameter
*
* Step1:setup encoder
* @code
* ISVCEncoder* encoder_;
* int rv = WelsCreateSVCEncoder (&encoder_);
* assert (rv == 0);
* assert (encoder_ != NULL);
* @endcode
*
* Step2:initilize with basic parameter
* @code
* SEncParamBase param;
* memset (&param, 0, sizeof (SEncParamBase));
* param.iUsageType = usageType; //from EUsageType enum
* param.fMaxFrameRate = frameRate;
* param.iPicWidth = width;
* param.iPicHeight = height;
* param.iTargetBitrate = 5000000;
* encoder_->Initialize (&param);
* @endcode
*
* Step3:set option, set option during encoding process
* @code
* encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
* int videoFormat = videoFormatI420;
* encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
* @endcode
*
* Step4: encode and store ouput bistream
* @code
* int frameSize = width * height * 3 / 2;
* BufferedData buf;
* buf.SetLength (frameSize);
* assert (buf.Length() == (size_t)frameSize);
* SFrameBSInfo info;
* memset (&info, 0, sizeof (SFrameBSInfo));
* SSourcePicture pic;
* memset (&pic, 0, sizeof (SsourcePicture));
* pic.iPicWidth = width;
* pic.iPicHeight = height;
* pic.iColorFormat = videoFormatI420;
* pic.iStride[0] = pic.iPicWidth;
* pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
* pic.pData[0] = buf.data();
* pic.pData[1] = pic.pData[0] + width * height;
* pic.pData[2] = pic.pData[1] + (width * height >> 2);
* for(int num = 0;num<total_num;num++) {
* //prepare input data
* rv = encoder_->EncodeFrame (&pic, &info);
* assert (rv == cmResultSuccess);
* if (info.eFrameType != videoFrameTypeSkip) {
* //output bitstream handling
* }
* }
* @endcode
*
* Step5:teardown encoder
* @code
* if (encoder_) {
* encoder_->Uninitialize();
* WelsDestroySVCEncoder (encoder_);
* }
* @endcode
*
*/
/**
* @page EncoderUsageExample2
*
* @brief
* * An example for using the encoder with extension parameter.
* * The same operation on Step 1,3,4,5 with Example-1
*
* Step 2:initialize with extension parameter
* @code
* SEncParamExt param;
* encoder_->GetDefaultParams (&param);
* param.iUsageType = usageType;
* param.fMaxFrameRate = frameRate;
* param.iPicWidth = width;
* param.iPicHeight = height;
* param.iTargetBitrate = 5000000;
* param.bEnableDenoise = denoise;
* param.iSpatialLayerNum = layers;
* //SM_DYN_SLICE don't support multi-thread now
* if (sliceMode != SM_SINGLE_SLICE && sliceMode != SM_DYN_SLICE)
* param.iMultipleThreadIdc = 2;
*
* for (int i = 0; i < param.iSpatialLayerNum; i++) {
* param.sSpatialLayers[i].iVideoWidth = width >> (param.iSpatialLayerNum - 1 - i);
* param.sSpatialLayers[i].iVideoHeight = height >> (param.iSpatialLayerNum - 1 - i);
* param.sSpatialLayers[i].fFrameRate = frameRate;
* param.sSpatialLayers[i].iSpatialBitrate = param.iTargetBitrate;
*
* param.sSpatialLayers[i].sSliceCfg.uiSliceMode = sliceMode;
* if (sliceMode == SM_DYN_SLICE) {
* param.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 600;
* param.uiMaxNalSize = 1500;
* }
* }
* param.iTargetBitrate *= param.iSpatialLayerNum;
* encoder_->InitializeExt (&param);
* int videoFormat = videoFormatI420;
* encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
*
* @endcode
*/
#ifdef __cplusplus
/**
* @brief Endocder definition
*/
class ISVCEncoder {
public:
/**
* @brief Initialize the encoder
* @param pParam basic encoder parameter
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI Initialize (const SEncParamBase* pParam) = 0;
/**
* @brief Initilaize encoder by using extension parameters.
* @param pParam extension parameter for encoder
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) = 0;
/**
* @brief Get the default extension parameters.
* If you want to change some parameters of encoder, firstly you need to get the default encoding parameters,
* after that you can change part of parameters you want to.
* @param pParam extension parameter for encoder
* @return CM_RETURN: 0 - success; otherwise - failed;
* */
virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) = 0;
/// uninitialize the encoder
virtual int EXTAPI Uninitialize() = 0;
/**
* @brief Encode one frame
* @param kpSrcPic the pointer to the source luminance plane
* chrominance data:
* CbData = kpSrc + m_iMaxPicWidth * m_iMaxPicHeight;
* CrData = CbData + (m_iMaxPicWidth * m_iMaxPicHeight)/4;
* the application calling this interface needs to ensure the data validation between the location
* @param pBsInfo output bit stream
* @return 0 - success; otherwise -failed;
*/
virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) = 0;
/**
* @brief Encode the parameters from output bit stream
* @param pBsInfo output bit stream
* @return 0 - success; otherwise - failed;
*/
virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) = 0;
/**
* @brief Force encoder to encoder frame as IDR if bIDR set as true
* @param bIDR true: force encoder to encode frame as IDR frame;false, return 1 and nothing to do
* @return 0 - success; otherwise - failed;
*/
virtual int EXTAPI ForceIntraFrame (bool bIDR, int iLayerId = -1) = 0;
/**
* @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
* @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
/**
* @brief Get option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
* @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
virtual ~ISVCEncoder() {}
};
/**
* @brief Decoder definition
*/
class ISVCDecoder {
public:
/**
* @brief Initilaize decoder
* @param pParam parameter for decoder
* @return 0 - success; otherwise - failed;
*/
virtual long EXTAPI Initialize (const SDecodingParam* pParam) = 0;
/// Uninitialize the decoder
virtual long EXTAPI Uninitialize() = 0;
/**
* @brief Decode one frame
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param ppDst buffer pointer of decoded data (YUV)
* @param pStride output stride
* @param iWidth output width
* @param iHeight output height
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
int* pStride,
int& iWidth,
int& iHeight) = 0;
/**
* @brief For slice level DecodeFrameNoDelay() (4 parameters input),
* whatever the function return value is, the output data
* of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
* This function will parse and reconstruct the input frame immediately if it is complete
* It is recommended as the main decoding function for H.264/AVC format input
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param ppDst buffer pointer of decoded data (YUV)
* @param pDstInfo information provided to API(width, height, etc.)
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
SBufferInfo* pDstInfo) = 0;
/**
* @brief For slice level DecodeFrame2() (4 parameters input),
* whatever the function return value is, the output data
* of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
* (e.g., in multi-slice cases, only when the whole picture
* is completely reconstructed, this variable would be set equal to 1.)
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param ppDst buffer pointer of decoded data (YUV)
* @param pDstInfo information provided to API(width, height, etc.)
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
SBufferInfo* pDstInfo) = 0;
/**
* @brief This function gets a decoded ready frame remaining in buffers after the last frame has been decoded.
* Use GetOption with option DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER to get the number of frames remaining in buffers.
* Note that it is only applicable for profile_idc != 66
* @param ppDst buffer pointer of decoded data (YUV)
* @param pDstInfo information provided to API(width, height, etc.)
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst,
SBufferInfo* pDstInfo) = 0;
/**
* @brief This function parse input bitstream only, and rewrite possible SVC syntax to AVC syntax
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param pDstInfo bit stream info
* @return 0 - success; otherwise -failed;
*/
virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
const int iSrcLen,
SParserBsInfo* pDstInfo) = 0;
/**
* @brief This API does not work for now!! This is for future use to support non-I420 color format output.
* @param pSrc the h264 stream to be decoded
* @param iSrcLen the length of h264 stream
* @param pDst buffer pointer of decoded data (YUV)
* @param iDstStride output stride
* @param iDstLen bit stream info
* @param iWidth output width
* @param iHeight output height
* @param iColorFormat output color format
* @return to do ...
*/
virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
const int iSrcLen,
unsigned char* pDst,
int iDstStride,
int& iDstLen,
int& iWidth,
int& iHeight,
int& iColorFormat) = 0;
/**
* @brief Set option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
* @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
/**
* @brief Get option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
* @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
* @return CM_RETURN: 0 - success; otherwise - failed;
*/
virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
virtual ~ISVCDecoder() {}
};
extern "C"
{
#else
typedef struct ISVCEncoderVtbl ISVCEncoderVtbl;
typedef const ISVCEncoderVtbl* ISVCEncoder;
struct ISVCEncoderVtbl {
int (*Initialize) (ISVCEncoder*, const SEncParamBase* pParam);
int (*InitializeExt) (ISVCEncoder*, const SEncParamExt* pParam);
int (*GetDefaultParams) (ISVCEncoder*, SEncParamExt* pParam);
int (*Uninitialize) (ISVCEncoder*);
int (*EncodeFrame) (ISVCEncoder*, const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo);
int (*EncodeParameterSets) (ISVCEncoder*, SFrameBSInfo* pBsInfo);
int (*ForceIntraFrame) (ISVCEncoder*, bool bIDR);
int (*SetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
int (*GetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
};
typedef struct ISVCDecoderVtbl ISVCDecoderVtbl;
typedef const ISVCDecoderVtbl* ISVCDecoder;
struct ISVCDecoderVtbl {
long (*Initialize) (ISVCDecoder*, const SDecodingParam* pParam);
long (*Uninitialize) (ISVCDecoder*);
DECODING_STATE (*DecodeFrame) (ISVCDecoder*, const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
int* pStride,
int* iWidth,
int* iHeight);
DECODING_STATE (*DecodeFrameNoDelay) (ISVCDecoder*, const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
SBufferInfo* pDstInfo);
DECODING_STATE (*DecodeFrame2) (ISVCDecoder*, const unsigned char* pSrc,
const int iSrcLen,
unsigned char** ppDst,
SBufferInfo* pDstInfo);
DECODING_STATE (*FlushFrame) (ISVCDecoder*, unsigned char** ppDst,
SBufferInfo* pDstInfo);
DECODING_STATE (*DecodeParser) (ISVCDecoder*, const unsigned char* pSrc,
const int iSrcLen,
SParserBsInfo* pDstInfo);
DECODING_STATE (*DecodeFrameEx) (ISVCDecoder*, const unsigned char* pSrc,
const int iSrcLen,
unsigned char* pDst,
int iDstStride,
int* iDstLen,
int* iWidth,
int* iHeight,
int* iColorFormat);
long (*SetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
long (*GetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
};
#endif
typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
/** @brief Create encoder
* @param ppEncoder encoder
* @return 0 - success; otherwise - failed;
*/
int WelsCreateSVCEncoder (ISVCEncoder** ppEncoder);
/** @brief Destroy encoder
* @param pEncoder encoder
* @return void
*/
void WelsDestroySVCEncoder (ISVCEncoder* pEncoder);
/** @brief Get the capability of decoder
* @param pDecCapability decoder capability
* @return 0 - success; otherwise - failed;
*/
int WelsGetDecoderCapability (SDecoderCapability* pDecCapability);
/** @brief Create decoder
* @param ppDecoder decoder
* @return 0 - success; otherwise - failed;
*/
long WelsCreateDecoder (ISVCDecoder** ppDecoder);
/** @brief Destroy decoder
* @param pDecoder decoder
* @return void
*/
void WelsDestroyDecoder (ISVCDecoder* pDecoder);
/** @brief Get codec version
* Note, old versions of Mingw (GCC < 4.7) are buggy and use an
* incorrect/different ABI for calling this function, making it
* incompatible with MSVC builds.
* @return The linked codec version
*/
OpenH264Version WelsGetCodecVersion (void);
/** @brief Get codec version
* @param pVersion struct to fill in with the version
*/
void WelsGetCodecVersionEx (OpenH264Version* pVersion);
#ifdef __cplusplus
}
#endif
#endif//WELS_VIDEO_CODEC_SVC_API_H__

View File

@ -0,0 +1,810 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
#define WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
/**
* @file codec_app_def.h
* @brief Data and /or structures introduced in Cisco OpenH264 application
*/
#include "codec_def.h"
/* Constants */
#define MAX_TEMPORAL_LAYER_NUM 4
#define MAX_SPATIAL_LAYER_NUM 4
#define MAX_QUALITY_LAYER_NUM 4
#define MAX_LAYER_NUM_OF_FRAME 128
#define MAX_NAL_UNITS_IN_LAYER 128 ///< predetermined here, adjust it later if need
#define MAX_RTP_PAYLOAD_LEN 1000
#define AVERAGE_RTP_PAYLOAD_LEN 800
#define SAVED_NALUNIT_NUM_TMP ( (MAX_SPATIAL_LAYER_NUM*MAX_QUALITY_LAYER_NUM) + 1 + MAX_SPATIAL_LAYER_NUM ) ///< SPS/PPS + SEI/SSEI + PADDING_NAL
#define MAX_SLICES_NUM_TMP ( ( MAX_NAL_UNITS_IN_LAYER - SAVED_NALUNIT_NUM_TMP ) / 3 )
#define AUTO_REF_PIC_COUNT -1 ///< encoder selects the number of reference frame automatically
#define UNSPECIFIED_BIT_RATE 0 ///< to do: add detail comment
/**
* @brief Struct of OpenH264 version
*/
///
/// E.g. SDK version is 1.2.0.0, major version number is 1, minor version number is 2, and revision number is 0.
typedef struct _tagVersion {
unsigned int uMajor; ///< The major version number
unsigned int uMinor; ///< The minor version number
unsigned int uRevision; ///< The revision number
unsigned int uReserved; ///< The reserved number, it should be 0.
} OpenH264Version;
/**
* @brief Decoding status
*/
typedef enum {
/**
* Errors derived from bitstream parsing
*/
dsErrorFree = 0x00, ///< bit stream error-free
dsFramePending = 0x01, ///< need more throughput to generate a frame output,
dsRefLost = 0x02, ///< layer lost at reference frame with temporal id 0
dsBitstreamError = 0x04, ///< error bitstreams(maybe broken internal frame) the decoder cared
dsDepLayerLost = 0x08, ///< dependented layer is ever lost
dsNoParamSets = 0x10, ///< no parameter set NALs involved
dsDataErrorConcealed = 0x20, ///< current data error concealed specified
dsRefListNullPtrs = 0x40, ///<ref picure list contains null ptrs within uiRefCount range
/**
* Errors derived from logic level
*/
dsInvalidArgument = 0x1000, ///< invalid argument specified
dsInitialOptExpected = 0x2000, ///< initializing operation is expected
dsOutOfMemory = 0x4000, ///< out of memory due to new request
/**
* ANY OTHERS?
*/
dsDstBufNeedExpan = 0x8000 ///< actual picture size exceeds size of dst pBuffer feed in decoder, so need expand its size
} DECODING_STATE;
/**
* @brief Option types introduced in SVC encoder application
*/
typedef enum {
ENCODER_OPTION_DATAFORMAT = 0,
ENCODER_OPTION_IDR_INTERVAL, ///< IDR period,0/-1 means no Intra period (only the first frame); lager than 0 means the desired IDR period, must be multiple of (2^temporal_layer)
ENCODER_OPTION_SVC_ENCODE_PARAM_BASE, ///< structure of Base Param
ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ///< structure of Extension Param
ENCODER_OPTION_FRAME_RATE, ///< maximal input frame rate, current supported range: MAX_FRAME_RATE = 30,MIN_FRAME_RATE = 1
ENCODER_OPTION_BITRATE,
ENCODER_OPTION_MAX_BITRATE,
ENCODER_OPTION_INTER_SPATIAL_PRED,
ENCODER_OPTION_RC_MODE,
ENCODER_OPTION_RC_FRAME_SKIP,
ENCODER_PADDING_PADDING, ///< 0:disable padding;1:padding
ENCODER_OPTION_PROFILE, ///< assgin the profile for each layer
ENCODER_OPTION_LEVEL, ///< assgin the level for each layer
ENCODER_OPTION_NUMBER_REF, ///< the number of refererence frame
ENCODER_OPTION_DELIVERY_STATUS, ///< the delivery info which is a feedback from app level
ENCODER_LTR_RECOVERY_REQUEST,
ENCODER_LTR_MARKING_FEEDBACK,
ENCODER_LTR_MARKING_PERIOD,
ENCODER_OPTION_LTR, ///< 0:disable LTR;larger than 0 enable LTR; LTR number is fixed to be 2 in current encoder
ENCODER_OPTION_COMPLEXITY,
ENCODER_OPTION_ENABLE_SSEI, ///< enable SSEI: true--enable ssei; false--disable ssei
ENCODER_OPTION_ENABLE_PREFIX_NAL_ADDING, ///< enable prefix: true--enable prefix; false--disable prefix
ENCODER_OPTION_SPS_PPS_ID_STRATEGY, ///< different stategy in adjust ID in SPS/PPS: 0- constant ID, 1-additional ID, 6-mapping and additional
ENCODER_OPTION_CURRENT_PATH,
ENCODER_OPTION_DUMP_FILE, ///< dump layer reconstruct frame to a specified file
ENCODER_OPTION_TRACE_LEVEL, ///< trace info based on the trace level
ENCODER_OPTION_TRACE_CALLBACK, ///< a void (*)(void* context, int level, const char* message) function which receives log messages
ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, ///< context info of trace callback
ENCODER_OPTION_GET_STATISTICS, ///< read only
ENCODER_OPTION_STATISTICS_LOG_INTERVAL, ///< log interval in millisecond
ENCODER_OPTION_IS_LOSSLESS_LINK, ///< advanced algorithmetic settings
ENCODER_OPTION_BITS_VARY_PERCENTAGE ///< bit vary percentage
} ENCODER_OPTION;
/**
* @brief Option types introduced in decoder application
*/
typedef enum {
DECODER_OPTION_END_OF_STREAM = 1, ///< end of stream flag
DECODER_OPTION_VCL_NAL, ///< feedback whether or not have VCL NAL in current AU for application layer
DECODER_OPTION_TEMPORAL_ID, ///< feedback temporal id for application layer
DECODER_OPTION_FRAME_NUM, ///< feedback current decoded frame number
DECODER_OPTION_IDR_PIC_ID, ///< feedback current frame belong to which IDR period
DECODER_OPTION_LTR_MARKING_FLAG, ///< feedback wether current frame mark a LTR
DECODER_OPTION_LTR_MARKED_FRAME_NUM, ///< feedback frame num marked by current Frame
DECODER_OPTION_ERROR_CON_IDC, ///< indicate decoder error concealment method
DECODER_OPTION_TRACE_LEVEL,
DECODER_OPTION_TRACE_CALLBACK, ///< a void (*)(void* context, int level, const char* message) function which receives log messages
DECODER_OPTION_TRACE_CALLBACK_CONTEXT,///< context info of trace callbac
DECODER_OPTION_GET_STATISTICS, ///< feedback decoder statistics
DECODER_OPTION_GET_SAR_INFO, ///< feedback decoder Sample Aspect Ratio info in Vui
DECODER_OPTION_PROFILE, ///< get current AU profile info, only is used in GetOption
DECODER_OPTION_LEVEL, ///< get current AU level info,only is used in GetOption
DECODER_OPTION_STATISTICS_LOG_INTERVAL,///< set log output interval
DECODER_OPTION_IS_REF_PIC, ///< feedback current frame is ref pic or not
DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, ///< number of frames remaining in decoder buffer when pictures are required to re-ordered into display-order.
DECODER_OPTION_NUM_OF_THREADS, ///< number of decoding threads. The maximum thread count is equal or less than lesser of (cpu core counts and 16).
} DECODER_OPTION;
/**
* @brief Enumerate the type of error concealment methods
*/
typedef enum {
ERROR_CON_DISABLE = 0,
ERROR_CON_FRAME_COPY,
ERROR_CON_SLICE_COPY,
ERROR_CON_FRAME_COPY_CROSS_IDR,
ERROR_CON_SLICE_COPY_CROSS_IDR,
ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE,
ERROR_CON_SLICE_MV_COPY_CROSS_IDR,
ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE
} ERROR_CON_IDC;
/**
* @brief Feedback that whether or not have VCL NAL in current AU
*/
typedef enum {
FEEDBACK_NON_VCL_NAL = 0,
FEEDBACK_VCL_NAL,
FEEDBACK_UNKNOWN_NAL
} FEEDBACK_VCL_NAL_IN_AU;
/**
* @brief Type of layer being encoded
*/
typedef enum {
NON_VIDEO_CODING_LAYER = 0,
VIDEO_CODING_LAYER = 1
} LAYER_TYPE;
/**
* @brief Spatial layer num
*/
typedef enum {
SPATIAL_LAYER_0 = 0,
SPATIAL_LAYER_1 = 1,
SPATIAL_LAYER_2 = 2,
SPATIAL_LAYER_3 = 3,
SPATIAL_LAYER_ALL = 4
} LAYER_NUM;
/**
* @brief Enumerate the type of video bitstream which is provided to decoder
*/
typedef enum {
VIDEO_BITSTREAM_AVC = 0,
VIDEO_BITSTREAM_SVC = 1,
VIDEO_BITSTREAM_DEFAULT = VIDEO_BITSTREAM_SVC
} VIDEO_BITSTREAM_TYPE;
/**
* @brief Enumerate the type of key frame request
*/
typedef enum {
NO_RECOVERY_REQUSET = 0,
LTR_RECOVERY_REQUEST = 1,
IDR_RECOVERY_REQUEST = 2,
NO_LTR_MARKING_FEEDBACK = 3,
LTR_MARKING_SUCCESS = 4,
LTR_MARKING_FAILED = 5
} KEY_FRAME_REQUEST_TYPE;
/**
* @brief Structure for LTR recover request
*/
typedef struct {
unsigned int uiFeedbackType; ///< IDR request or LTR recovery request
unsigned int uiIDRPicId; ///< distinguish request from different IDR
int iLastCorrectFrameNum;
int iCurrentFrameNum; ///< specify current decoder frame_num.
int iLayerId; //specify the layer for recovery request
} SLTRRecoverRequest;
/**
* @brief Structure for LTR marking feedback
*/
typedef struct {
unsigned int uiFeedbackType; ///< mark failed or successful
unsigned int uiIDRPicId; ///< distinguish request from different IDR
int iLTRFrameNum; ///< specify current decoder frame_num
int iLayerId; //specify the layer for LTR marking feedback
} SLTRMarkingFeedback;
/**
* @brief Structure for LTR configuration
*/
typedef struct {
bool bEnableLongTermReference; ///< 1: on, 0: off
int iLTRRefNum; ///< TODO: not supported to set it arbitrary yet
} SLTRConfig;
/**
* @brief Enumerate the type of rate control mode
*/
typedef enum {
RC_QUALITY_MODE = 0, ///< quality mode
RC_BITRATE_MODE = 1, ///< bitrate mode
RC_BUFFERBASED_MODE = 2, ///< no bitrate control,only using buffer status,adjust the video quality
RC_TIMESTAMP_MODE = 3, //rate control based timestamp
RC_BITRATE_MODE_POST_SKIP = 4, ///< this is in-building RC MODE, WILL BE DELETED after algorithm tuning!
RC_OFF_MODE = -1, ///< rate control off mode
} RC_MODES;
/**
* @brief Enumerate the type of profile id
*/
typedef enum {
PRO_UNKNOWN = 0,
PRO_BASELINE = 66,
PRO_MAIN = 77,
PRO_EXTENDED = 88,
PRO_HIGH = 100,
PRO_HIGH10 = 110,
PRO_HIGH422 = 122,
PRO_HIGH444 = 144,
PRO_CAVLC444 = 244,
PRO_SCALABLE_BASELINE = 83,
PRO_SCALABLE_HIGH = 86
} EProfileIdc;
/**
* @brief Enumerate the type of level id
*/
typedef enum {
LEVEL_UNKNOWN = 0,
LEVEL_1_0 = 10,
LEVEL_1_B = 9,
LEVEL_1_1 = 11,
LEVEL_1_2 = 12,
LEVEL_1_3 = 13,
LEVEL_2_0 = 20,
LEVEL_2_1 = 21,
LEVEL_2_2 = 22,
LEVEL_3_0 = 30,
LEVEL_3_1 = 31,
LEVEL_3_2 = 32,
LEVEL_4_0 = 40,
LEVEL_4_1 = 41,
LEVEL_4_2 = 42,
LEVEL_5_0 = 50,
LEVEL_5_1 = 51,
LEVEL_5_2 = 52
} ELevelIdc;
/**
* @brief Enumerate the type of wels log
*/
enum {
WELS_LOG_QUIET = 0x00, ///< quiet mode
WELS_LOG_ERROR = 1 << 0, ///< error log iLevel
WELS_LOG_WARNING = 1 << 1, ///< Warning log iLevel
WELS_LOG_INFO = 1 << 2, ///< information log iLevel
WELS_LOG_DEBUG = 1 << 3, ///< debug log, critical algo log
WELS_LOG_DETAIL = 1 << 4, ///< per packet/frame log
WELS_LOG_RESV = 1 << 5, ///< resversed log iLevel
WELS_LOG_LEVEL_COUNT = 6,
WELS_LOG_DEFAULT = WELS_LOG_WARNING ///< default log iLevel in Wels codec
};
/**
* @brief Enumerate the type of slice mode
*/
typedef enum {
SM_SINGLE_SLICE = 0, ///< | SliceNum==1
SM_FIXEDSLCNUM_SLICE = 1, ///< | according to SliceNum | enabled dynamic slicing for multi-thread
SM_RASTER_SLICE = 2, ///< | according to SlicesAssign | need input of MB numbers each slice. In addition, if other constraint in SSliceArgument is presented, need to follow the constraints. Typically if MB num and slice size are both constrained, re-encoding may be involved.
SM_SIZELIMITED_SLICE = 3, ///< | according to SliceSize | slicing according to size, the slicing will be dynamic(have no idea about slice_nums until encoding current frame)
SM_RESERVED = 4
} SliceModeEnum;
/**
* @brief Structure for slice argument
*/
typedef struct {
SliceModeEnum uiSliceMode; ///< by default, uiSliceMode will be SM_SINGLE_SLICE
unsigned int
uiSliceNum; ///< only used when uiSliceMode=1, when uiSliceNum=0 means auto design it with cpu core number
unsigned int
uiSliceMbNum[MAX_SLICES_NUM_TMP]; ///< only used when uiSliceMode=2; when =0 means setting one MB row a slice
unsigned int uiSliceSizeConstraint; ///< now only used when uiSliceMode=4
} SSliceArgument;
/**
* @brief Enumerate the type of video format
*/
typedef enum {
VF_COMPONENT,
VF_PAL,
VF_NTSC,
VF_SECAM,
VF_MAC,
VF_UNDEF,
VF_NUM_ENUM
} EVideoFormatSPS; // EVideoFormat is already defined/used elsewhere!
/**
* @brief Enumerate the type of color primaries
*/
typedef enum {
CP_RESERVED0,
CP_BT709,
CP_UNDEF,
CP_RESERVED3,
CP_BT470M,
CP_BT470BG,
CP_SMPTE170M,
CP_SMPTE240M,
CP_FILM,
CP_BT2020,
CP_NUM_ENUM
} EColorPrimaries;
/**
* @brief Enumerate the type of transfer characteristics
*/
typedef enum {
TRC_RESERVED0,
TRC_BT709,
TRC_UNDEF,
TRC_RESERVED3,
TRC_BT470M,
TRC_BT470BG,
TRC_SMPTE170M,
TRC_SMPTE240M,
TRC_LINEAR,
TRC_LOG100,
TRC_LOG316,
TRC_IEC61966_2_4,
TRC_BT1361E,
TRC_IEC61966_2_1,
TRC_BT2020_10,
TRC_BT2020_12,
TRC_NUM_ENUM
} ETransferCharacteristics;
/**
* @brief Enumerate the type of color matrix
*/
typedef enum {
CM_GBR,
CM_BT709,
CM_UNDEF,
CM_RESERVED3,
CM_FCC,
CM_BT470BG,
CM_SMPTE170M,
CM_SMPTE240M,
CM_YCGCO,
CM_BT2020NC,
CM_BT2020C,
CM_NUM_ENUM
} EColorMatrix;
/**
* @brief Enumerate the type of sample aspect ratio
*/
typedef enum {
ASP_UNSPECIFIED = 0,
ASP_1x1 = 1,
ASP_12x11 = 2,
ASP_10x11 = 3,
ASP_16x11 = 4,
ASP_40x33 = 5,
ASP_24x11 = 6,
ASP_20x11 = 7,
ASP_32x11 = 8,
ASP_80x33 = 9,
ASP_18x11 = 10,
ASP_15x11 = 11,
ASP_64x33 = 12,
ASP_160x99 = 13,
ASP_EXT_SAR = 255
} ESampleAspectRatio;
/**
* @brief Structure for spatial layer configuration
*/
typedef struct {
int iVideoWidth; ///< width of picture in luminance samples of a layer
int iVideoHeight; ///< height of picture in luminance samples of a layer
float fFrameRate; ///< frame rate specified for a layer
int iSpatialBitrate; ///< target bitrate for a spatial layer, in unit of bps
int iMaxSpatialBitrate; ///< maximum bitrate for a spatial layer, in unit of bps
EProfileIdc uiProfileIdc; ///< value of profile IDC (PRO_UNKNOWN for auto-detection)
ELevelIdc uiLevelIdc; ///< value of profile IDC (0 for auto-detection)
int iDLayerQp; ///< value of level IDC (0 for auto-detection)
SSliceArgument sSliceArgument;
// Note: members bVideoSignalTypePresent through uiColorMatrix below are also defined in SWelsSPS in parameter_sets.h.
bool bVideoSignalTypePresent; // false => do not write any of the following information to the header
unsigned char
uiVideoFormat; // EVideoFormatSPS; 3 bits in header; 0-5 => component, kpal, ntsc, secam, mac, undef
bool bFullRange; // false => analog video data range [16, 235]; true => full data range [0,255]
bool bColorDescriptionPresent; // false => do not write any of the following three items to the header
unsigned char
uiColorPrimaries; // EColorPrimaries; 8 bits in header; 0 - 9 => ???, bt709, undef, ???, bt470m, bt470bg,
// smpte170m, smpte240m, film, bt2020
unsigned char
uiTransferCharacteristics; // ETransferCharacteristics; 8 bits in header; 0 - 15 => ???, bt709, undef, ???, bt470m, bt470bg, smpte170m,
// smpte240m, linear, log100, log316, iec61966-2-4, bt1361e, iec61966-2-1, bt2020-10, bt2020-12
unsigned char
uiColorMatrix; // EColorMatrix; 8 bits in header (corresponds to FFmpeg "colorspace"); 0 - 10 => GBR, bt709,
// undef, ???, fcc, bt470bg, smpte170m, smpte240m, YCgCo, bt2020nc, bt2020c
bool bAspectRatioPresent; ///< aspect ratio present in VUI
ESampleAspectRatio eAspectRatio; ///< aspect ratio idc
unsigned short sAspectRatioExtWidth; ///< use if aspect ratio idc == 255
unsigned short sAspectRatioExtHeight; ///< use if aspect ratio idc == 255
} SSpatialLayerConfig;
/**
* @brief Encoder usage type
*/
typedef enum {
CAMERA_VIDEO_REAL_TIME, ///< camera video for real-time communication
SCREEN_CONTENT_REAL_TIME, ///< screen content signal
CAMERA_VIDEO_NON_REAL_TIME,
SCREEN_CONTENT_NON_REAL_TIME,
INPUT_CONTENT_TYPE_ALL,
} EUsageType;
/**
* @brief Enumulate the complexity mode
*/
typedef enum {
LOW_COMPLEXITY = 0, ///< the lowest compleixty,the fastest speed,
MEDIUM_COMPLEXITY, ///< medium complexity, medium speed,medium quality
HIGH_COMPLEXITY ///< high complexity, lowest speed, high quality
} ECOMPLEXITY_MODE;
/**
* @brief Enumulate for the stategy of SPS/PPS strategy
*/
typedef enum {
CONSTANT_ID = 0, ///< constant id in SPS/PPS
INCREASING_ID = 0x01, ///< SPS/PPS id increases at each IDR
SPS_LISTING = 0x02, ///< using SPS in the existing list if possible
SPS_LISTING_AND_PPS_INCREASING = 0x03,
SPS_PPS_LISTING = 0x06,
} EParameterSetStrategy;
// TODO: Refine the parameters definition.
/**
* @brief SVC Encoding Parameters
*/
typedef struct TagEncParamBase {
EUsageType
iUsageType; ///< application type; please refer to the definition of EUsageType
int iPicWidth; ///< width of picture in luminance samples (the maximum of all layers if multiple spatial layers presents)
int iPicHeight; ///< height of picture in luminance samples((the maximum of all layers if multiple spatial layers presents)
int iTargetBitrate; ///< target bitrate desired, in unit of bps
RC_MODES iRCMode; ///< rate control mode
float fMaxFrameRate; ///< maximal input frame rate
} SEncParamBase, *PEncParamBase;
/**
* @brief SVC Encoding Parameters extention
*/
typedef struct TagEncParamExt {
EUsageType
iUsageType; ///< same as in TagEncParamBase
int iPicWidth; ///< same as in TagEncParamBase
int iPicHeight; ///< same as in TagEncParamBase
int iTargetBitrate; ///< same as in TagEncParamBase
RC_MODES iRCMode; ///< same as in TagEncParamBase
float fMaxFrameRate; ///< same as in TagEncParamBase
int iTemporalLayerNum; ///< temporal layer number, max temporal layer = 4
int iSpatialLayerNum; ///< spatial layer number,1<= iSpatialLayerNum <= MAX_SPATIAL_LAYER_NUM, MAX_SPATIAL_LAYER_NUM = 4
SSpatialLayerConfig sSpatialLayers[MAX_SPATIAL_LAYER_NUM];
ECOMPLEXITY_MODE iComplexityMode;
unsigned int uiIntraPeriod; ///< period of Intra frame
int iNumRefFrame; ///< number of reference frame used
EParameterSetStrategy
eSpsPpsIdStrategy; ///< different stategy in adjust ID in SPS/PPS: 0- constant ID, 1-additional ID, 6-mapping and additional
bool bPrefixNalAddingCtrl; ///< false:not use Prefix NAL; true: use Prefix NAL
bool bEnableSSEI; ///< false:not use SSEI; true: use SSEI -- TODO: planning to remove the interface of SSEI
bool bSimulcastAVC; ///< (when encoding more than 1 spatial layer) false: use SVC syntax for higher layers; true: use Simulcast AVC
int iPaddingFlag; ///< 0:disable padding;1:padding
int iEntropyCodingModeFlag; ///< 0:CAVLC 1:CABAC.
/* rc control */
bool bEnableFrameSkip; ///< False: don't skip frame even if VBV buffer overflow.True: allow skipping frames to keep the bitrate within limits
int iMaxBitrate; ///< the maximum bitrate, in unit of bps, set it to UNSPECIFIED_BIT_RATE if not needed
int iMaxQp; ///< the maximum QP encoder supports
int iMinQp; ///< the minmum QP encoder supports
unsigned int uiMaxNalSize; ///< the maximum NAL size. This value should be not 0 for dynamic slice mode
/*LTR settings*/
bool bEnableLongTermReference; ///< 1: on, 0: off
int iLTRRefNum; ///< the number of LTR(long term reference),TODO: not supported to set it arbitrary yet
unsigned int iLtrMarkPeriod; ///< the LTR marked period that is used in feedback.
/* multi-thread settings*/
unsigned short
iMultipleThreadIdc; ///< 1 # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; lager than 1: count number of threads;
bool bUseLoadBalancing; ///< only used when uiSliceMode=1 or 3, will change slicing of a picture during the run-time of multi-thread encoding, so the result of each run may be different
/* Deblocking loop filter */
int iLoopFilterDisableIdc; ///< 0: on, 1: off, 2: on except for slice boundaries
int iLoopFilterAlphaC0Offset; ///< AlphaOffset: valid range [-6, 6], default 0
int iLoopFilterBetaOffset; ///< BetaOffset: valid range [-6, 6], default 0
/*pre-processing feature*/
bool bEnableDenoise; ///< denoise control
bool bEnableBackgroundDetection; ///< background detection control //VAA_BACKGROUND_DETECTION //BGD cmd
bool bEnableAdaptiveQuant; ///< adaptive quantization control
bool bEnableFrameCroppingFlag; ///< enable frame cropping flag: TRUE always in application
bool bEnableSceneChangeDetect;
bool bIsLosslessLink; ///< LTR advanced setting
} SEncParamExt;
/**
* @brief Define a new struct to show the property of video bitstream.
*/
typedef struct {
unsigned int size; ///< size of the struct
VIDEO_BITSTREAM_TYPE eVideoBsType; ///< video stream type (AVC/SVC)
} SVideoProperty;
/**
* @brief SVC Decoding Parameters, reserved here and potential applicable in the future
*/
typedef struct TagSVCDecodingParam {
char* pFileNameRestructed; ///< file name of reconstructed frame used for PSNR calculation based debug
unsigned int uiCpuLoad; ///< CPU load
unsigned char uiTargetDqLayer; ///< setting target dq layer id
ERROR_CON_IDC eEcActiveIdc; ///< whether active error concealment feature in decoder
bool bParseOnly; ///< decoder for parse only, no reconstruction. When it is true, SPS/PPS size should not exceed SPS_PPS_BS_SIZE (128). Otherwise, it will return error info
SVideoProperty sVideoProperty; ///< video stream property
} SDecodingParam, *PDecodingParam;
/**
* @brief Bitstream inforamtion of a layer being encoded
*/
typedef struct {
unsigned char uiTemporalId;
unsigned char uiSpatialId;
unsigned char uiQualityId;
EVideoFrameType eFrameType;
unsigned char uiLayerType;
/**
* The sub sequence layers are ordered hierarchically based on their dependency on each other so that any picture in a layer shall not be
* predicted from any picture on any higher layer.
*/
int iSubSeqId; ///< refer to D.2.11 Sub-sequence information SEI message semantics
int iNalCount; ///< count number of NAL coded already
int* pNalLengthInByte; ///< length of NAL size in byte from 0 to iNalCount-1
unsigned char* pBsBuf; ///< buffer of bitstream contained
} SLayerBSInfo, *PLayerBSInfo;
/**
* @brief Frame bit stream info
*/
typedef struct {
int iLayerNum;
SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
EVideoFrameType eFrameType;
int iFrameSizeInBytes;
long long uiTimeStamp;
} SFrameBSInfo, *PFrameBSInfo;
/**
* @brief Structure for source picture
*/
typedef struct Source_Picture_s {
int iColorFormat; ///< color space type
int iStride[4]; ///< stride for each plane pData
unsigned char* pData[4]; ///< plane pData
int iPicWidth; ///< luma picture width in x coordinate
int iPicHeight; ///< luma picture height in y coordinate
long long uiTimeStamp; ///< timestamp of the source picture, unit: millisecond
} SSourcePicture;
/**
* @brief Structure for bit rate info
*/
typedef struct TagBitrateInfo {
LAYER_NUM iLayer;
int iBitrate; ///< the maximum bitrate
} SBitrateInfo;
/**
* @brief Structure for dump layer info
*/
typedef struct TagDumpLayer {
int iLayer;
char* pFileName;
} SDumpLayer;
/**
* @brief Structure for profile info in layer
*
*/
typedef struct TagProfileInfo {
int iLayer;
EProfileIdc uiProfileIdc; ///< the profile info
} SProfileInfo;
/**
* @brief Structure for level info in layer
*
*/
typedef struct TagLevelInfo {
int iLayer;
ELevelIdc uiLevelIdc; ///< the level info
} SLevelInfo;
/**
* @brief Structure for dilivery status
*
*/
typedef struct TagDeliveryStatus {
bool bDeliveryFlag; ///< 0: the previous frame isn't delivered,1: the previous frame is delivered
int iDropFrameType; ///< the frame type that is dropped; reserved
int iDropFrameSize; ///< the frame size that is dropped; reserved
} SDeliveryStatus;
/**
* @brief The capability of decoder, for SDP negotiation
*/
typedef struct TagDecoderCapability {
int iProfileIdc; ///< profile_idc
int iProfileIop; ///< profile-iop
int iLevelIdc; ///< level_idc
int iMaxMbps; ///< max-mbps
int iMaxFs; ///< max-fs
int iMaxCpb; ///< max-cpb
int iMaxDpb; ///< max-dpb
int iMaxBr; ///< max-br
bool bRedPicCap; ///< redundant-pic-cap
} SDecoderCapability;
/**
* @brief Structure for parse only output
*/
typedef struct TagParserBsInfo {
int iNalNum; ///< total NAL number in current AU
int* pNalLenInByte; ///< each nal length
unsigned char* pDstBuff; ///< outputted dst buffer for parsed bitstream
int iSpsWidthInPixel; ///< required SPS width info
int iSpsHeightInPixel; ///< required SPS height info
unsigned long long uiInBsTimeStamp; ///< input BS timestamp
unsigned long long uiOutBsTimeStamp; ///< output BS timestamp
} SParserBsInfo, *PParserBsInfo;
/**
* @brief Structure for encoder statistics
*/
typedef struct TagVideoEncoderStatistics {
unsigned int uiWidth; ///< the width of encoded frame
unsigned int uiHeight; ///< the height of encoded frame
//following standard, will be 16x aligned, if there are multiple spatial, this is of the highest
float fAverageFrameSpeedInMs; ///< average_Encoding_Time
// rate control related
float fAverageFrameRate; ///< the average frame rate in, calculate since encoding starts, supposed that the input timestamp is in unit of ms
float fLatestFrameRate; ///< the frame rate in, in the last second, supposed that the input timestamp is in unit of ms (? useful for checking BR, but is it easy to calculate?
unsigned int uiBitRate; ///< sendrate in Bits per second, calculated within the set time-window
unsigned int uiAverageFrameQP; ///< the average QP of last encoded frame
unsigned int uiInputFrameCount; ///< number of frames
unsigned int uiSkippedFrameCount; ///< number of frames
unsigned int uiResolutionChangeTimes; ///< uiResolutionChangeTimes
unsigned int uiIDRReqNum; ///< number of IDR requests
unsigned int uiIDRSentNum; ///< number of actual IDRs sent
unsigned int uiLTRSentNum; ///< number of LTR sent/marked
long long iStatisticsTs; ///< Timestamp of updating the statistics
unsigned long iTotalEncodedBytes;
unsigned long iLastStatisticsBytes;
unsigned long iLastStatisticsFrameCount;
} SEncoderStatistics;
/**
* @brief Structure for decoder statistics
*/
typedef struct TagVideoDecoderStatistics {
unsigned int uiWidth; ///< the width of encode/decode frame
unsigned int uiHeight; ///< the height of encode/decode frame
float fAverageFrameSpeedInMs; ///< average_Decoding_Time
float fActualAverageFrameSpeedInMs; ///< actual average_Decoding_Time, including freezing pictures
unsigned int uiDecodedFrameCount; ///< number of frames
unsigned int uiResolutionChangeTimes; ///< uiResolutionChangeTimes
unsigned int uiIDRCorrectNum; ///< number of correct IDR received
//EC on related
unsigned int
uiAvgEcRatio; ///< when EC is on, the average ratio of total EC areas, can be an indicator of reconstruction quality
unsigned int
uiAvgEcPropRatio; ///< when EC is on, the rough average ratio of propogate EC areas, can be an indicator of reconstruction quality
unsigned int uiEcIDRNum; ///< number of actual unintegrity IDR or not received but eced
unsigned int uiEcFrameNum; ///<
unsigned int uiIDRLostNum; ///< number of whole lost IDR
unsigned int
uiFreezingIDRNum; ///< number of freezing IDR with error (partly received), under resolution change
unsigned int uiFreezingNonIDRNum; ///< number of freezing non-IDR with error
int iAvgLumaQp; ///< average luma QP. default: -1, no correct frame outputted
int iSpsReportErrorNum; ///< number of Sps Invalid report
int iSubSpsReportErrorNum; ///< number of SubSps Invalid report
int iPpsReportErrorNum; ///< number of Pps Invalid report
int iSpsNoExistNalNum; ///< number of Sps NoExist Nal
int iSubSpsNoExistNalNum; ///< number of SubSps NoExist Nal
int iPpsNoExistNalNum; ///< number of Pps NoExist Nal
unsigned int uiProfile; ///< Profile idc in syntax
unsigned int uiLevel; ///< level idc according to Annex A-1
int iCurrentActiveSpsId; ///< current active SPS id
int iCurrentActivePpsId; ///< current active PPS id
unsigned int iStatisticsLogInterval; ///< frame interval of statistics log
} SDecoderStatistics; // in building, coming soon
/**
* @brief Structure for sample aspect ratio (SAR) info in VUI
*/
typedef struct TagVuiSarInfo {
unsigned int uiSarWidth; ///< SAR width
unsigned int uiSarHeight; ///< SAR height
bool bOverscanAppropriateFlag; ///< SAR overscan flag
} SVuiSarInfo, *PVuiSarInfo;
#endif//WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__

View File

@ -0,0 +1,216 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WELS_VIDEO_CODEC_DEFINITION_H__
#define WELS_VIDEO_CODEC_DEFINITION_H__
/**
* @file codec_def.h
*/
/**
* @brief Enumerate the type of video format
*/
typedef enum {
videoFormatRGB = 1, ///< rgb color formats
videoFormatRGBA = 2,
videoFormatRGB555 = 3,
videoFormatRGB565 = 4,
videoFormatBGR = 5,
videoFormatBGRA = 6,
videoFormatABGR = 7,
videoFormatARGB = 8,
videoFormatYUY2 = 20, ///< yuv color formats
videoFormatYVYU = 21,
videoFormatUYVY = 22,
videoFormatI420 = 23, ///< the same as IYUV
videoFormatYV12 = 24,
videoFormatInternal = 25, ///< only used in SVC decoder testbed
videoFormatNV12 = 26, ///< new format for output by DXVA decoding
videoFormatVFlip = 0x80000000
} EVideoFormatType;
/**
* @brief Enumerate video frame type
*/
typedef enum {
videoFrameTypeInvalid, ///< encoder not ready or parameters are invalidate
videoFrameTypeIDR, ///< IDR frame in H.264
videoFrameTypeI, ///< I frame type
videoFrameTypeP, ///< P frame type
videoFrameTypeSkip, ///< skip the frame based encoder kernel
videoFrameTypeIPMixed ///< a frame where I and P slices are mixing, not supported yet
} EVideoFrameType;
/**
* @brief Enumerate return type
*/
typedef enum {
cmResultSuccess, ///< successful
cmInitParaError, ///< parameters are invalid
cmUnknownReason,
cmMallocMemeError, ///< malloc a memory error
cmInitExpected, ///< initial action is expected
cmUnsupportedData
} CM_RETURN;
/**
* @brief Enumulate the nal unit type
*/
enum ENalUnitType {
NAL_UNKNOWN = 0,
NAL_SLICE = 1,
NAL_SLICE_DPA = 2,
NAL_SLICE_DPB = 3,
NAL_SLICE_DPC = 4,
NAL_SLICE_IDR = 5, ///< ref_idc != 0
NAL_SEI = 6, ///< ref_idc == 0
NAL_SPS = 7,
NAL_PPS = 8
///< ref_idc == 0 for 6,9,10,11,12
};
/**
* @brief NRI: eNalRefIdc
*/
enum ENalPriority {
NAL_PRIORITY_DISPOSABLE = 0,
NAL_PRIORITY_LOW = 1,
NAL_PRIORITY_HIGH = 2,
NAL_PRIORITY_HIGHEST = 3
};
#define IS_PARAMETER_SET_NAL(eNalRefIdc, eNalType) \
( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == (NAL_SPS|NAL_PPS) || eNalType == NAL_SPS) )
#define IS_IDR_NAL(eNalRefIdc, eNalType) \
( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == NAL_SLICE_IDR) )
#define FRAME_NUM_PARAM_SET (-1)
#define FRAME_NUM_IDR 0
/**
* @brief eDeblockingIdc
*/
enum {
DEBLOCKING_IDC_0 = 0,
DEBLOCKING_IDC_1 = 1,
DEBLOCKING_IDC_2 = 2
};
#define DEBLOCKING_OFFSET (6)
#define DEBLOCKING_OFFSET_MINUS (-6)
/* Error Tools definition */
typedef unsigned short ERR_TOOL;
/**
@brief to do
*/
enum {
ET_NONE = 0x00, ///< NONE Error Tools
ET_IP_SCALE = 0x01, ///< IP Scalable
ET_FMO = 0x02, ///< Flexible Macroblock Ordering
ET_IR_R1 = 0x04, ///< Intra Refresh in predifined 2% MB
ET_IR_R2 = 0x08, ///< Intra Refresh in predifined 5% MB
ET_IR_R3 = 0x10, ///< Intra Refresh in predifined 10% MB
ET_FEC_HALF = 0x20, ///< Forward Error Correction in 50% redundency mode
ET_FEC_FULL = 0x40, ///< Forward Error Correction in 100% redundency mode
ET_RFS = 0x80 ///< Reference Frame Selection
};
/**
* @brief Information of coded Slice(=NAL)(s)
*/
typedef struct SliceInformation {
unsigned char* pBufferOfSlices; ///< base buffer of coded slice(s)
int iCodedSliceCount; ///< number of coded slices
unsigned int* pLengthOfSlices; ///< array of slices length accordingly by number of slice
int iFecType; ///< FEC type[0, 50%FEC, 100%FEC]
unsigned char uiSliceIdx; ///< index of slice in frame [FMO: 0,..,uiSliceCount-1; No FMO: 0]
unsigned char uiSliceCount; ///< count number of slice in frame [FMO: 2-8; No FMO: 1]
char iFrameIndex; ///< index of frame[-1, .., idr_interval-1]
unsigned char uiNalRefIdc; ///< NRI, priority level of slice(NAL)
unsigned char uiNalType; ///< NAL type
unsigned char
uiContainingFinalNal; ///< whether final NAL is involved in buffer of coded slices, flag used in Pause feature in T27
} SliceInfo, *PSliceInfo;
/**
* @brief thresholds of the initial, maximal and minimal rate
*/
typedef struct {
int iWidth; ///< frame width
int iHeight; ///< frame height
int iThresholdOfInitRate; ///< threshold of initial rate
int iThresholdOfMaxRate; ///< threshold of maximal rate
int iThresholdOfMinRate; ///< threshold of minimal rate
int iMinThresholdFrameRate; ///< min frame rate min
int iSkipFrameRate; ///< skip to frame rate min
int iSkipFrameStep; ///< how many frames to skip
} SRateThresholds, *PRateThresholds;
/**
* @brief Structure for decoder memery
*/
typedef struct TagSysMemBuffer {
int iWidth; ///< width of decoded pic for display
int iHeight; ///< height of decoded pic for display
int iFormat; ///< type is "EVideoFormatType"
int iStride[2]; ///< stride of 2 component
} SSysMEMBuffer;
/**
* @brief Buffer info
*/
typedef struct TagBufferInfo {
int iBufferStatus; ///< 0: one frame data is not ready; 1: one frame data is ready
unsigned long long uiInBsTimeStamp; ///< input BS timestamp
unsigned long long uiOutYuvTimeStamp; ///< output YUV timestamp, when bufferstatus is 1
union {
SSysMEMBuffer sSystemBuffer; ///< memory info for one picture
} UsrData; ///< output buffer info
unsigned char* pDst[3]; //point to picture YUV data
} SBufferInfo;
/**
* @brief In a GOP, multiple of the key frame number, derived from
* the number of layers(index or array below)
*/
static const char kiKeyNumMultiple[] = {
1, 1, 2, 4, 8, 16,
};
#endif//WELS_VIDEO_CODEC_DEFINITION_H__

View File

@ -0,0 +1,15 @@
//The current file is auto-generated by script: generate_codec_ver.sh
#ifndef CODEC_VER_H
#define CODEC_VER_H
#include "codec_app_def.h"
static const OpenH264Version g_stCodecVersion = {2, 1, 0, 2002};
static const char* const g_strCodecVer = "OpenH264 version:2.1.0.2002";
#define OPENH264_MAJOR (2)
#define OPENH264_MINOR (1)
#define OPENH264_REVISION (0)
#define OPENH264_RESERVED (2002)
#endif // CODEC_VER_H

View File

@ -0,0 +1,13 @@
headers = [
'codec_api.h',
'codec_app_def.h',
'codec_def.h',
'codec_ver.h',
]
foreach header : headers
api_headers += [[header, files(header)]]
endforeach
install_headers(headers,
subdir: 'wels')

View File

@ -0,0 +1,6 @@
build.xml
local.properties
proguard-project.txt
gen
bin
project.properties

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wels.dec"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application android:label="@string/app_name">
<activity android:name=".WelsDecTest"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,9 @@
LOCAL_PATH := $(call my-dir)
MY_LOCAL_PATH := $(LOCAL_PATH)
# Step3
#Generate the libwelsdecdemo.so file
include $(LOCAL_PATH)/welsdecdemo.mk
LOCAL_PATH := $(MY_LOCAL_PATH)

View File

@ -0,0 +1,6 @@
ifeq ($(NDK_TOOLCHAIN_VERSION), clang)
APP_STL := c++_shared
else
APP_STL := stlport_shared
endif
APP_PLATFORM := android-12

View File

@ -0,0 +1,24 @@
#include <string.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "welsdec"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern int DecMain (int argc, char* argv[]);
extern "C"
JNIEXPORT void JNICALL Java_com_wels_dec_WelsDecTest_DoDecoderTest
(JNIEnv* env, jobject thiz, jstring jsFileNameIn, jstring jsFileNameOut) {
/**************** Add the native codes/API *****************/
char* argv[3];
int argc = 3;
argv[0] = (char*) ("decConsole.exe");
argv[1] = (char*) ((*env).GetStringUTFChars (jsFileNameIn, NULL));
argv[2] = (char*) ((*env).GetStringUTFChars (jsFileNameOut, NULL));
LOGI ("Start to run JNI module!+++");
DecMain (argc, argv);
LOGI ("End to run JNI module!+++");
}

View File

@ -0,0 +1,47 @@
# Generate the libwelsdecdemo.so file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := wels
LOCAL_SRC_FILES := ../../../../../libopenh264.so
ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_SRC_FILES)))
include $(PREBUILT_SHARED_LIBRARY)
endif
include $(CLEAR_VARS)
#
# Module Settings
#
LOCAL_MODULE := welsdecdemo
#
# Source Files
#
CODEC_PATH := ../../../../
CONSOLE_DEC_PATH := ../../../../console/dec
CONSOLE_COMMON_PATH := ../../../../console/common
LOCAL_SRC_FILES := \
$(CONSOLE_DEC_PATH)/src/h264dec.cpp \
$(CONSOLE_COMMON_PATH)/src/read_config.cpp \
$(CONSOLE_DEC_PATH)/src/d3d9_utils.cpp \
myjni.cpp
#
# Header Includes
#
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../../../api/svc \
$(LOCAL_PATH)/../../../../console/dec/inc \
$(LOCAL_PATH)/../../../../console/common/inc \
$(LOCAL_PATH)/../../../../common/inc
#
# Compile Flags and Link Libraries
#
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := wels
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/cfg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load bitstreams" />
<Button
android:id="@+id/buttonSW"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WelsDecoderTest</string>
</resources>

View File

@ -0,0 +1,151 @@
package com.wels.dec;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import java.io.*;
import java.util.Vector;
public class WelsDecTest extends Activity {
/** Called when the activity is first created. */
private OnClickListener OnClickEvent;
private Button mBtnLoad, mBtnStartSW;
final String mStreamPath = "/sdcard/welsdec/";
Vector<String> mStreamFiles = new Vector<String>();
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
final TextView tv = new TextView (this);
System.out.println ("Here we go ...");
Log.i (TAG, "sdcard path:" + Environment.getExternalStorageDirectory().getAbsolutePath());
setContentView (R.layout.main);
mBtnLoad = (Button)findViewById (R.id.cfg);
mBtnStartSW = (Button)findViewById (R.id.buttonSW);
OnClickEvent = new OnClickListener() {
public void onClick (View v) {
switch (v.getId()) {
case R.id.cfg: {
String cfgFile = mStreamPath + "BitStreams.txt";
try {
BufferedReader bufferedReader = new BufferedReader (new FileReader (cfgFile));
String text;
while ((text = bufferedReader.readLine()) != null) {
mStreamFiles.add (mStreamPath + text);
Log.i (TAG, mStreamPath + text);
}
bufferedReader.close();
} catch (IOException e) {
Log.e ("WELS_DEC", e.getMessage());
}
}
break;
case R.id.buttonSW: {
System.out.println ("decode sequence number = " + mStreamFiles.size());
Log.i ("WSE_DEC", "after click");
try {
for (int k = 0; k < mStreamFiles.size(); k++) {
String inFile = mStreamFiles.get (k);
String outFile = mStreamFiles.get (k) + ".yuv";
Log.i (TAG, "input file:" + inFile + " output file:" + outFile);
DoDecoderTest (inFile, outFile);
}
} catch (Exception e) {
Log.e (TAG, e.getMessage());
}
mStreamFiles.clear();
tv.setText ("Decoder is completed!");
}
break;
}
}
};
mBtnLoad.setOnClickListener (OnClickEvent);
mBtnStartSW.setOnClickListener (OnClickEvent);
System.out.println ("Done!");
//if you want to run the demo manually, just comment following 2 lines
runAutoDec();
}
public void runAutoDec() {
Thread thread = new Thread() {
public void run() {
Log.i (TAG, "decoder performance test begin");
File bitstreams = new File (mStreamPath);
String[] list = bitstreams.list();
if (list == null || list.length == 0) {
Log.i (TAG, "have not find any coder resourse");
finish();
}
for (int i = 0; i < list.length; i++) {
String inFile = list[i];
inFile = mStreamPath + inFile;
String outFile = inFile + ".yuv";
DoDecoderTest (inFile, outFile);
}
Log.i (TAG, "decoder performance test finish");
finish();
}
};
thread.start();
}
@Override
public void onStart() {
Log.i ("WSE_DEC", "welsdecdemo onStart");
super.onStart();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i (TAG, "OnDestroy");
Process.killProcess (Process.myPid());
}
@Override
public boolean onKeyDown (int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
default:
return super.onKeyDown (keyCode, event);
}
}
public native void DoDecoderTest (String infilename, String outfilename);
private static final String TAG = "welsdec";
static {
try {
System.loadLibrary ("openh264");
System.loadLibrary ("stlport_shared");
System.loadLibrary ("welsdecdemo");
Log.v (TAG, "Load libwelsdec successful");
} catch (Exception e) {
Log.e (TAG, "Failed to load welsdec" + e.getMessage());
}
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wels.enc"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application android:label="@string/app_name">
<activity android:name=".WelsEncTest"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,9 @@
LOCAL_PATH := $(call my-dir)
MY_LOCAL_PATH := $(LOCAL_PATH)
# Step3
#Generate the libwelsdecdemo.so file
include $(LOCAL_PATH)/welsencdemo.mk
LOCAL_PATH := $(MY_LOCAL_PATH)

View File

@ -0,0 +1,6 @@
ifeq ($(NDK_TOOLCHAIN_VERSION), clang)
APP_STL := c++_shared
else
APP_STL := stlport_shared
endif
APP_PLATFORM := android-12

View File

@ -0,0 +1,45 @@
#include <string.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "welsdec"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C" int EncMain (int argc, char* argv[]);
extern "C"
JNIEXPORT void JNICALL Java_com_wels_enc_WelsEncTest_DoEncoderAutoTest
(JNIEnv* env, jobject thiz, jstring jsIncfgName, jstring jsInlayerName, jstring jsInyuvName, jstring jsOutbitName) {
/**************** Add the native codes/API *****************/
const char* argv[] = {
(char*) ("encConsole.exe"),
(char*) ((*env).GetStringUTFChars (jsIncfgName, NULL)),
(char*) ("-org"),
(char*) ((*env).GetStringUTFChars (jsInyuvName, NULL)),
(char*) ("-bf"),
(char*) ((*env).GetStringUTFChars (jsOutbitName, NULL)),
(char*) ("-numl"),
(char*) ("1"),
(char*) ("-lconfig"),
(char*) ("0"),
(char*) ((*env).GetStringUTFChars (jsInlayerName, NULL))
};
LOGI ("Start to run JNI module!+++");
EncMain (sizeof (argv) / sizeof (argv[0]), (char**)&argv[0]);
LOGI ("End to run JNI module!+++");
}
JNIEXPORT void JNICALL Java_com_wels_enc_WelsEncTest_DoEncoderTest
(JNIEnv* env, jobject thiz, jstring jsFileNameIn) {
/**************** Add the native codes/API *****************/
char* argv[2];
int argc = 2;
argv[0] = (char*) ("encConsole.exe");
argv[1] = (char*) ((*env).GetStringUTFChars (jsFileNameIn, NULL));
LOGI ("Start to run JNI module!+++");
EncMain (argc, argv);
LOGI ("End to run JNI module!+++");
}

View File

@ -0,0 +1,51 @@
# Generate the libwelsencdemo.so file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := wels
LOCAL_SRC_FILES := ../../../../../libopenh264.so
ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_SRC_FILES)))
include $(PREBUILT_SHARED_LIBRARY)
endif
include $(CLEAR_VARS)
#
# Module Settings
#
LOCAL_MODULE := welsencdemo
#
# Source Files
#
CODEC_PATH := ../../../../
CONSOLE_ENC_PATH := ../../../../console/enc
CONSOLE_COMMON_PATH := ../../../../console/common
LOCAL_SRC_FILES := \
$(CONSOLE_ENC_PATH)/src/welsenc.cpp \
$(CONSOLE_COMMON_PATH)/src/read_config.cpp \
myjni.cpp
#
# Header Includes
#
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../../../api/svc \
$(LOCAL_PATH)/../../../../console/enc/inc \
$(LOCAL_PATH)/../../../../console/common/inc \
$(LOCAL_PATH)/../../../../encoder/core/inc \
$(LOCAL_PATH)/../../../../processing/interface \
$(LOCAL_PATH)/../../../../common/inc
#
# Compile Flags and Link Libraries
#
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := wels
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/cfg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load bitstreams" />
<Button
android:id="@+id/buttonSW"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WelsEncoderTest</string>
</resources>

View File

@ -0,0 +1,173 @@
package com.wels.enc;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import java.io.*;
import java.util.Vector;
public class WelsEncTest extends Activity {
/** Called when the activity is first created. */
private OnClickListener OnClickEvent;
private Button mBtnLoad, mBtnStartSW;
final String mStreamPath = "/sdcard/welsenc/";
Vector<String> mCfgFiles = new Vector<String>();
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
final TextView tv = new TextView (this);
System.out.println ("Here we go ...");
Log.i (TAG, "sdcard path:" + Environment.getExternalStorageDirectory().getAbsolutePath());
setContentView (R.layout.main);
mBtnLoad = (Button)findViewById (R.id.cfg);
mBtnStartSW = (Button)findViewById (R.id.buttonSW);
OnClickEvent = new OnClickListener() {
public void onClick (View v) {
switch (v.getId()) {
case R.id.cfg: {
String cfgFile = mStreamPath + "cfgs.txt";
try {
BufferedReader bufferedReader = new BufferedReader (new FileReader (cfgFile));
String text;
while ((text = bufferedReader.readLine()) != null) {
mCfgFiles.add (mStreamPath + text);
Log.i (TAG, mStreamPath + text);
}
bufferedReader.close();
} catch (IOException e) {
Log.e (TAG, e.getMessage());
}
}
break;
case R.id.buttonSW: {
System.out.println ("encode sequence number = " + mCfgFiles.size());
Log.i (TAG, "after click");
try {
for (int k = 0; k < mCfgFiles.size(); k++) {
String cfgFile = mCfgFiles.get (k);
DoEncoderTest (cfgFile);
}
} catch (Exception e) {
Log.e (TAG, e.getMessage());
}
mCfgFiles.clear();
tv.setText ("Encoder is completed!");
}
break;
}
}
};
mBtnLoad.setOnClickListener (OnClickEvent);
mBtnStartSW.setOnClickListener (OnClickEvent);
System.out.println ("Done!");
//run the test automatically,if you not want to autotest, just comment this line
runAutoEnc();
}
public void runAutoEnc() {
Thread thread = new Thread() {
public void run() {
Log.i (TAG, "encoder performance test begin");
String inYuvfile = null, outBitfile = null, inOrgfile = null, inLayerfile = null;
File encCase = new File (mStreamPath);
String[] caseNum = encCase.list();
if (caseNum == null || caseNum.length == 0) {
Log.i (TAG, "have not find any encoder resourse");
finish();
}
for (int i = 0; i < caseNum.length; i++) {
String[] yuvName = null;
File yuvPath = null;
File encCaseNo = new File (mStreamPath + caseNum[i]);
String[] encFile = encCaseNo.list();
for (int k = 0; k < encFile.length; k++) {
if (encFile[k].compareToIgnoreCase ("welsenc.cfg") == 0)
inOrgfile = encCaseNo + File.separator + encFile[k];
else if (encFile[k].compareToIgnoreCase ("layer2.cfg") == 0)
inLayerfile = encCaseNo + File.separator + encFile[k];
else if (encFile[k].compareToIgnoreCase ("yuv") == 0) {
yuvPath = new File (encCaseNo + File.separator + encFile[k]);
yuvName = yuvPath.list();
}
}
for (int m = 0; m < yuvName.length; m++) {
inYuvfile = yuvPath + File.separator + yuvName[m];
outBitfile = inYuvfile + ".264";
Log.i (TAG, "enc yuv file:" + yuvName[m]);
DoEncoderAutoTest (inOrgfile, inLayerfile, inYuvfile, outBitfile);
}
}
Log.i (TAG, "encoder performance test finish");
finish();
}
};
thread.start();
}
@Override
public void onStart() {
Log.i (TAG, "welsencdemo onStart");
super.onStart();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i (TAG, "OnDestroy");
Process.killProcess (Process.myPid());
}
@Override
public boolean onKeyDown (int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
default:
return super.onKeyDown (keyCode, event);
}
}
public native void DoEncoderTest (String cfgFileName);
public native void DoEncoderAutoTest (String cfgFileName, String layerFileName, String yuvFileName,
String outBitsName);
private static final String TAG = "welsenc";
static {
try {
System.loadLibrary ("openh264");
System.loadLibrary ("stlport_shared");
System.loadLibrary ("welsencdemo");
Log.v (TAG, "Load libwelsencdemo.so successful");
} catch (Exception e) {
Log.e (TAG, "Failed to load welsenc" + e.getMessage());
}
}
}

View File

@ -0,0 +1,62 @@
# Run this to update the codec_ver.h at changes of api
#!/bin/sh
#
if [ "$1"x = ""x ]; then
echo "Please input the version number as: major_ver.minor_ver.patch.reserve"
exit 127
fi
codec_ver=`echo "$1" | egrep "^([0-9]+[.]){3}[0-9]+$"`
if [ $? -ne 0 ]; then
echo "Please input the version number as: major_ver.minor_ver.patch.reserve"
exit 127
fi
revision=`git show | head -n 1`
revision=`echo $revision|cut -d' ' -f2|sed -e 's#[ ]*\(.*\)[ ]*#\1#'`
revision=${revision:0:7}
echo "//The current file is auto-generated by script: generate_codec_ver.sh" >>codec_ver.h
echo "#ifndef CODEC_VER_H" >>codec_ver.h
echo "#define CODEC_VER_H" >>codec_ver.h
echo "" >>codec_ver.h
echo "#include \"codec_app_def.h\"" >>codec_ver.h
echo "" >>codec_ver.h
fullver="$1"
major="${1%%.*}"
tmp=${1#*.}
minor="${tmp%%.*}"
tmp=${tmp#*.}
revnr="${tmp%%.*}"
tmp=${tmp#*.}
resnr="${tmp%%.*}"
echo "static const OpenH264Version g_stCodecVersion = {$major, $minor, $revnr, $resnr};" >>codec_ver.h
echo "static const char* const g_strCodecVer = \"OpenH264 version:$fullver\";" >>codec_ver.h
#if [ "$2"x = ""x ]; then
#echo "static const char* const g_strCodecBuildNum = \"OpenH264 revision:$revision\";" >> codec_ver.h
#else
#echo "static const char* const g_strCodecBuildNum = \"OpenH264 build:$2, OpenH264 revision:$revision\";" >> codec_ver.h
#fi
echo "" >>codec_ver.h
#define OPENH264_MAJOR 1, #define OPENH264_MINOR 2 #define OPENH264_REVISION 3 #define OPENH264_RESERVED 0
echo "#define OPENH264_MAJOR ($major)" >>codec_ver.h
echo "#define OPENH264_MINOR ($minor)" >>codec_ver.h
echo "#define OPENH264_REVISION ($revnr)" >>codec_ver.h
echo "#define OPENH264_RESERVED ($resnr)" >>codec_ver.h
echo "" >>codec_ver.h
echo "#endif // CODEC_VER_H" >>codec_ver.h
mv -f codec_ver.h ../api/svc/codec_ver.h
# Ignore non-utf8 chars in the input
export LC_ALL=C
cat ../../openh264.rc.template | sed "s/\$MAJOR/$major/g" | sed "s/\$MINOR/$minor/g" | sed "s/\$REVISION/$revnr/g" | sed "s/\$RESERVED/$resnr/g" > openh264.rc.tmp
mv openh264.rc.tmp ../../openh264.rc

View File

@ -0,0 +1,3 @@
project.xcworkspace
xcuserdata
.DS_Store

View File

@ -0,0 +1,39 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
@interface DEMOAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow* window;
@end

View File

@ -0,0 +1,68 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "DEMOAppDelegate.h"
@implementation DEMOAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
//Sent when the application is about to move from active to inactive state.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
//Used to store application state information.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
//Called as part of the transition from the background to the inactive state.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
//Restart any tasks that were paused while the application was inactive.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
//Called when the application is about to terminate.
}
@end

View File

@ -0,0 +1,48 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
@interface DEMOViewController : UIViewController {
BOOL bEnableFlag;
}
@property (strong, nonatomic) NSMutableArray* resFileArray;
@property (retain, nonatomic)UIAlertView* statusIndication;
@property (assign, nonatomic) NSUInteger selectedRow;
- (IBAction)startDecoderAll: (id)sender;
- (IBAction)startDecoderOne: (id)sender;
@property (weak, nonatomic) IBOutlet UITextField* currentSelectedFileTF;
//unwind segue
- (IBAction)unwindSegueForShowResourceViewController: (UIStoryboardSegue*)segue;
@end

View File

@ -0,0 +1,187 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#define ENDLESS_LOOP //define to do the performance testing
#define NO_OUTPUT_MODE //define to disable the output yuv file
extern int DecMain(int argc, char * argv[]);
#import "DEMOViewController.h"
#import "DEMOViewControllerShowResource.h"
@interface DEMOViewController ()
@end
@implementation DEMOViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Add the testing codes
self.resFileArray = [[NSMutableArray alloc] init];
self.selectedRow = 0;
[self updateResourceArray];
//Init the status indication window
_statusIndication = [[UIAlertView alloc] initWithTitle: @"Decoding" message: @"Waiting the decoding" delegate: self cancelButtonTitle: @"Cancel" otherButtonTitles: nil];
if ([self.resFileArray count] > self.selectedRow)
self.currentSelectedFileTF.text = [[self.resFileArray objectAtIndex:self.selectedRow] lastPathComponent];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)startDecoderAll:(id)sender {
bEnableFlag = YES;
[_statusIndication show];
[NSThread detachNewThreadSelector:@selector(processDecoderAll) toTarget:self withObject:nil];
}
- (IBAction)startDecoderOne:(id)sender {
bEnableFlag = YES;
[_statusIndication show];
[NSThread detachNewThreadSelector:@selector(processDecoderOne) toTarget:self withObject:nil];
}
- (void)processDecoderAll
{
[self updateResourceArray];
if (YES == [self DoDecoderAll]) {
[self performSelectorOnMainThread:@selector(showAlertWnd) withObject:nil waitUntilDone:NO];
}
}
- (void)processDecoderOne
{
if (YES == [self DoDecoderOne:self.selectedRow]) {
[self performSelectorOnMainThread:@selector(showAlertWnd) withObject:nil waitUntilDone:NO];
}
}
- (void)showAlertWnd
{
[_statusIndication dismissWithClickedButtonIndex:0 animated:(BOOL)YES];
[self showAlertWindowTitle:@"Successful" message: @"Decode is successful!"];
}
-(void)showAlertWindowTitle:(NSString*)title message:(NSString*)message
{
UIAlertView *someError = [[UIAlertView alloc] initWithTitle: title message: message delegate: self cancelButtonTitle: @"Ok" otherButtonTitles: nil];
[someError show];
}
//Delegate for alertView
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (_statusIndication == alertView) {
bEnableFlag = NO;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"segueShowResource"]) {
[self updateResourceArray];
UINavigationController *navigationController = [segue destinationViewController];
DEMOViewControllerShowResource *ViewControllerShowResource = (DEMOViewControllerShowResource *)[navigationController topViewController];
ViewControllerShowResource.resFileArray = self.resFileArray;
}
}
//unwind segue
- (void)unwindSegueForShowResourceViewController:(UIStoryboardSegue *)segue
{
DEMOViewControllerShowResource *ViewControllerShowResource = [segue sourceViewController];
self.selectedRow = ViewControllerShowResource.selectedRow;
if ([self.resFileArray count] > self.selectedRow)
self.currentSelectedFileTF.text = [[self.resFileArray objectAtIndex:self.selectedRow] lastPathComponent];
}
//**************************************************************************/
// Following codes is for demo testing input
//**************************************************************************/
- (BOOL) DoDecoderAll
{
BOOL bResult;
for (NSUInteger index=0; index<[self.resFileArray count]; index++) {
if ((bResult = [self DoDecoderOne:index]) == NO) {
return NO;
}
}
return YES;
}
- (BOOL) DoDecoderOne:(NSUInteger)index
{
char *argv[3];//0 for exe name, 1 for resource input, 2 for output yuvfile
int argc = 3;
NSString *fileName = [[self.resFileArray objectAtIndex:index] lastPathComponent];
NSString *outputFileName = [[fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"yuv"];
NSString *outputFilePath = [[[self.resFileArray objectAtIndex:index] stringByDeletingLastPathComponent] stringByAppendingPathComponent:outputFileName];
argv[0] = (char *)("decConsole.exe");
argv[1] = (char *)[[self.resFileArray objectAtIndex:index] UTF8String]; //input resouce file path
argv[2] = (char *)[outputFilePath UTF8String]; //output file path
if (bEnableFlag == NO) {
return NO;
}
DecMain(argc, argv);
return YES;
}
- (void) updateResourceArray
{
//Clear the resource array
if ([self.resFileArray count] > 0) {
[self.resFileArray removeAllObjects];
}
//get the sharing folder path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sharingFolderPath = [paths objectAtIndex:0];
//enumerate the h.264 files at sharing folder
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray * directoryContents = [fileManager contentsOfDirectoryAtPath:sharingFolderPath error:&error];
for (NSUInteger index=0; index < [directoryContents count]; index++) {
NSString *fileName = [directoryContents objectAtIndex:index];
if (([fileName hasSuffix:@"264"] == YES) ||
([fileName hasSuffix:@"h264"] == YES)||
([fileName hasSuffix:@"H264"] == YES))
{
[self.resFileArray addObject:[sharingFolderPath stringByAppendingPathComponent:fileName]];
}
}
}
@end

View File

@ -0,0 +1,38 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
@interface DEMOViewControllerShowResource : UITableViewController
@property (strong, nonatomic) NSMutableArray* resFileArray;
@property (assign, nonatomic) NSUInteger selectedRow;
@end

View File

@ -0,0 +1,93 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "DEMOViewControllerShowResource.h"
@interface DEMOViewControllerShowResource ()
@end
@implementation DEMOViewControllerShowResource
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.resFileArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"resourcesListCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = [[self.resFileArray objectAtIndex:indexPath.row] lastPathComponent];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
self.selectedRow = indexPath.row;
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>hf.cisco.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>UIFileSharingEnabled</key>
<true/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>MainStoryboard_iPhone</string>
<key>UIMainStoryboardFile~ipad</key>
<string>MainStoryboard_iPad</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="4510" systemVersion="13A524d" targetRuntime="iOS.CocoaTouch.iPad" variant="6xAndEarlier" propertyAccessControl="none" useAutolayout="YES" initialViewController="yXx-eU-91T">
<dependencies>
<deployment defaultVersion="1552" identifier="iOS"/>
<development version="4600" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="jPS-ri-o6p">
<objects>
<viewController id="yXx-eU-91T" customClass="DEMOViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="hbu-fP-oM5">
<rect key="frame" x="0.0" y="20" width="768" height="1004"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hYB-j2-40C">
<rect key="frame" x="183" y="420" width="108" height="33"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Decoder All">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="startDecoderAll:" destination="yXx-eU-91T" eventType="touchUpInside" id="3MS-Cf-Adc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2wb-SI-4H1">
<rect key="frame" x="183" y="345" width="108" height="33"/>
<constraints>
<constraint firstAttribute="width" constant="108" id="2v6-gF-smR"/>
<constraint firstAttribute="height" constant="32" id="eJ4-hy-WrG"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Select File">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="8C7-cK-gmI" kind="modal" identifier="segueShowResource" id="hQX-Cl-38d"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TYm-NZ-PYc">
<rect key="frame" x="299" y="345" width="108" height="33"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Decoder">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="startDecoderOne:" destination="yXx-eU-91T" eventType="touchUpInside" id="QTx-lm-dBt"/>
</connections>
</button>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="File:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MKn-UR-WQ1">
<rect key="frame" x="183" y="283" width="32" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="6we-jx-Qq3">
<rect key="frame" x="223" y="274" width="323" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="323" id="4v5-6h-G72"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="2wb-SI-4H1" firstAttribute="width" secondItem="hYB-j2-40C" secondAttribute="width" type="user" id="6XQ-FA-Gxw"/>
<constraint firstItem="6we-jx-Qq3" firstAttribute="leading" secondItem="MKn-UR-WQ1" secondAttribute="trailing" constant="8" symbolic="YES" type="default" id="A8k-85-yfT"/>
<constraint firstItem="TYm-NZ-PYc" firstAttribute="baseline" secondItem="2wb-SI-4H1" secondAttribute="baseline" type="default" id="By0-sg-TgF"/>
<constraint firstItem="2wb-SI-4H1" firstAttribute="leading" secondItem="MKn-UR-WQ1" secondAttribute="leading" type="default" id="EOt-Ub-ktw"/>
<constraint firstItem="2wb-SI-4H1" firstAttribute="height" secondItem="TYm-NZ-PYc" secondAttribute="height" type="user" id="FEa-hl-Nkb"/>
<constraint firstItem="6we-jx-Qq3" firstAttribute="centerX" secondItem="hbu-fP-oM5" secondAttribute="centerX" type="default" id="Kiw-Sc-FdU"/>
<constraint firstItem="MKn-UR-WQ1" firstAttribute="bottom" secondItem="6we-jx-Qq3" secondAttribute="bottom" type="default" id="Lcn-Qu-3kM"/>
<constraint firstItem="TYm-NZ-PYc" firstAttribute="leading" secondItem="2wb-SI-4H1" secondAttribute="trailing" constant="8" symbolic="YES" type="default" id="QIU-v5-1LW"/>
<constraint firstItem="2wb-SI-4H1" firstAttribute="height" secondItem="hYB-j2-40C" secondAttribute="height" type="user" id="QKo-Ly-odJ"/>
<constraint firstItem="2wb-SI-4H1" firstAttribute="width" secondItem="TYm-NZ-PYc" secondAttribute="width" type="user" id="ZsI-jv-vxw"/>
<constraint firstItem="hYB-j2-40C" firstAttribute="leading" secondItem="2wb-SI-4H1" secondAttribute="leading" type="default" id="paU-W4-QEQ"/>
<constraint firstItem="6we-jx-Qq3" firstAttribute="top" secondItem="hbu-fP-oM5" secondAttribute="top" constant="274" id="swb-OF-reU"/>
<constraint firstItem="2wb-SI-4H1" firstAttribute="top" secondItem="hbu-fP-oM5" secondAttribute="top" constant="345" id="ty2-u6-bWv"/>
<constraint firstItem="hYB-j2-40C" firstAttribute="top" secondItem="hbu-fP-oM5" secondAttribute="top" constant="420" id="zeL-FT-4Zf"/>
</constraints>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics"/>
<connections>
<outlet property="currentSelectedFileTF" destination="6we-jx-Qq3" id="kXv-Fm-gM8"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ev2-Bg-nkw" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-885" y="74"/>
</scene>
<!--View Controller Show Resource - Resource List-->
<scene sceneID="0YF-PF-BUj">
<objects>
<tableViewController id="aiM-V0-4K8" customClass="DEMOViewControllerShowResource" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="wwS-SO-V2c">
<rect key="frame" x="0.0" y="64" width="768" height="960"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="resourcesListCell" id="tKV-R7-KlD">
<rect key="frame" x="0.0" y="22" width="768" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="768" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</tableViewCell>
</prototypes>
</tableView>
<navigationItem key="navigationItem" title="Resource List" id="nUp-VX-3WO">
<barButtonItem key="leftBarButtonItem" title="Back" id="vnO-PI-39R">
<connections>
<segue destination="igZ-GB-DHn" kind="unwind" unwindAction="unwindSegueForShowResourceViewController:" id="PBk-bM-n1O"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ikd-br-I9X" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="igZ-GB-DHn" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="783" y="79"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="n0I-kW-S3k">
<objects>
<navigationController definesPresentationContext="YES" id="8C7-cK-gmI" sceneMemberID="viewController">
<navigationItem key="navigationItem" id="dzH-BV-b40"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="40d-Zw-OWZ">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="aiM-V0-4K8" kind="relationship" relationship="rootViewController" id="W69-zP-VcW"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ZxZ-cF-kpk" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-51" y="74"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar" statusBarStyle="blackTranslucent"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination"/>
</simulatedMetricsContainer>
</document>

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="4510" systemVersion="13A524d" targetRuntime="iOS.CocoaTouch" variant="6xAndEarlier" propertyAccessControl="none" useAutolayout="YES" initialViewController="2">
<dependencies>
<deployment defaultVersion="1552" identifier="iOS"/>
<development version="4600" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="5">
<objects>
<viewController id="2" customClass="DEMOViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="3">
<rect key="frame" x="0.0" y="20" width="568" height="300"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="O8J-C0-MbI">
<rect key="frame" x="32" y="134" width="108" height="33"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Decoder All">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="startDecoderAll:" destination="2" eventType="touchUpInside" id="Hll-tC-Hss"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="abQ-CA-DAK">
<rect key="frame" x="32" y="94" width="108" height="33"/>
<constraints>
<constraint firstAttribute="width" constant="108" id="IqM-pe-lBv"/>
<constraint firstAttribute="height" constant="32" id="cem-8H-DBq"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Select File">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="mcO-AN-z7a" kind="modal" identifier="segueShowResource" id="WLe-Im-zJ0"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ykW-2E-vCm">
<rect key="frame" x="148" y="94" width="108" height="33"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Decoder">
<color key="titleColor" red="0.19607843137254902" green="0.30980392156862746" blue="0.52156862745098043" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="startDecoderOne:" destination="2" eventType="touchUpInside" id="q2K-s3-RgD"/>
</connections>
</button>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="File:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rsq-r5-ON5">
<rect key="frame" x="32" y="65" width="32" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Qve-7L-UkU">
<rect key="frame" x="72" y="56" width="26" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="rsq-r5-ON5" firstAttribute="leading" secondItem="O8J-C0-MbI" secondAttribute="leading" type="user" id="29I-Xb-0ag"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="height" secondItem="O8J-C0-MbI" secondAttribute="height" type="user" id="OR0-zx-XNf"/>
<constraint firstItem="rsq-r5-ON5" firstAttribute="leading" secondItem="abQ-CA-DAK" secondAttribute="leading" type="user" id="W38-q7-4nd"/>
<constraint firstItem="ykW-2E-vCm" firstAttribute="baseline" secondItem="abQ-CA-DAK" secondAttribute="baseline" type="default" id="WZe-oK-YSo"/>
<constraint firstItem="Qve-7L-UkU" firstAttribute="leading" secondItem="rsq-r5-ON5" secondAttribute="trailing" constant="8" symbolic="YES" type="default" id="b9u-gT-BF9"/>
<constraint firstItem="O8J-C0-MbI" firstAttribute="centerY" secondItem="3" secondAttribute="centerY" type="default" id="cPq-Zs-v04"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="top" secondItem="Qve-7L-UkU" secondAttribute="bottom" constant="8" symbolic="YES" type="default" id="cgB-TX-pla"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="top" secondItem="rsq-r5-ON5" secondAttribute="bottom" constant="8" symbolic="YES" type="default" id="de6-nY-107"/>
<constraint firstItem="O8J-C0-MbI" firstAttribute="top" secondItem="abQ-CA-DAK" secondAttribute="bottom" constant="8" symbolic="YES" type="default" id="fos-tl-P2o"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="width" secondItem="O8J-C0-MbI" secondAttribute="width" type="user" id="fxT-PS-wQq"/>
<constraint firstItem="ykW-2E-vCm" firstAttribute="leading" secondItem="abQ-CA-DAK" secondAttribute="trailing" constant="8" symbolic="YES" type="default" id="hxv-KP-JUV"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="height" secondItem="ykW-2E-vCm" secondAttribute="height" type="user" id="jFb-R4-no1"/>
<constraint firstItem="rsq-r5-ON5" firstAttribute="leading" secondItem="3" secondAttribute="leading" constant="32" id="nbA-ra-IBI"/>
<constraint firstItem="abQ-CA-DAK" firstAttribute="width" secondItem="ykW-2E-vCm" secondAttribute="width" type="user" id="rEp-US-RsU"/>
</constraints>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
<connections>
<outlet property="currentSelectedFileTF" destination="Qve-7L-UkU" id="Aua-id-o2H"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-383" y="79"/>
</scene>
<!--View Controller Show Resource - Resource List-->
<scene sceneID="3sV-NI-ybj">
<objects>
<tableViewController id="MBG-12-1iR" customClass="DEMOViewControllerShowResource" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="fij-4E-cXa">
<rect key="frame" x="0.0" y="64" width="568" height="256"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="resourcesListCell" id="uxm-wK-Brx">
<rect key="frame" x="0.0" y="22" width="568" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="568" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</tableViewCell>
</prototypes>
</tableView>
<navigationItem key="navigationItem" title="Resource List" id="MFQ-Qp-f4f">
<barButtonItem key="leftBarButtonItem" title="Back" id="eU8-kD-m0U">
<connections>
<segue destination="iD0-QE-VCb" kind="unwind" unwindAction="unwindSegueForShowResourceViewController:" id="ikx-lg-mCQ"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="fdb-Ea-RUm" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="iD0-QE-VCb" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="556" y="79"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="GZm-Tn-RdS">
<objects>
<navigationController definesPresentationContext="YES" id="mcO-AN-z7a" sceneMemberID="viewController">
<navigationItem key="navigationItem" id="jLO-A7-sdU"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="Nee-ii-B3U">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="MBG-12-1iR" kind="relationship" relationship="rootViewController" id="pLU-XE-NvG"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="hNx-Nt-9ig" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="22" y="79"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View File

@ -0,0 +1,124 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
#import "DEMOAppDelegate.h"
extern int DecMain (int argc, char* argv[]);
//redirect NSLog and stdout to logfile
void redirectLogToDocumentFile() {
NSArray* path = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString* document = [path objectAtIndex:0];
NSString* fileName = [NSString stringWithFormat:@"decPerf.log"];
NSString* logPath = [document stringByAppendingPathComponent:fileName];
NSFileManager* defaultManager = [NSFileManager defaultManager];
[defaultManager removeItemAtPath:logPath error:nil];
freopen ([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen ([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}
//run auto test to get encoder performance
int AutoTestDec() {
NSString* document = [[NSString alloc] init];
NSArray* paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] == 0) {
NSLog (@"could not find document path");
return 2;
}
document = [paths objectAtIndex:0];
NSString* decFilePath = [document stringByAppendingString:@"/DecoderPerfTestRes"];
NSFileManager* manage = [NSFileManager defaultManager];
NSString* outYuvPath = [decFilePath stringByAppendingString:@"/yuv"];
[manage removeItemAtPath:outYuvPath error:nil];
[manage createDirectoryAtPath:outYuvPath withIntermediateDirectories:YES attributes:nil error: nil];
NSArray* bitstreams = [manage subpathsAtPath:decFilePath];
if (bitstreams == nil) {
NSLog (@"could not find any bitstream under decoderperfpath");
return 1;
}
redirectLogToDocumentFile(); //output to console, just comment this line
for (int caseNO = 0; caseNO < [bitstreams count]; caseNO++) {
NSString* caseName = [bitstreams objectAtIndex:caseNO];
if ([caseName isEqual: @"yuv"]) {
break;
}
NSString* bitstream = [decFilePath stringByAppendingString:@"/"];
bitstream = [bitstream stringByAppendingString:caseName];
NSString* yuvFileName = [caseName stringByAppendingString:@".yuv"];
NSString* tmpyuvFileName = [outYuvPath stringByAppendingString:@"/"];
yuvFileName = [tmpyuvFileName stringByAppendingString:yuvFileName];
[manage createFileAtPath:yuvFileName contents:nil attributes:nil];
const char* argvv[] = {
"decConsole.exe",
[bitstream UTF8String],
[yuvFileName UTF8String]
};
DecMain (sizeof (argvv) / sizeof (argvv[0]), (char**)&argvv[0]);
[manage removeItemAtPath:yuvFileName error:nil];//FOR limited devices spaces
fflush (stdout); // flush the content of stdout instantly
}
return 0;
}
int main (int argc, char* argv[]) {
//***For auto testing of decoder performance, call auto test here, if you not want to do auto test, you can comment it manualy
if (AutoTestDec() == 0)
NSLog (@"Auto testing running sucessfully");
else
NSLog (@"Auto testing running failed");
abort();
//********
@autoreleasepool {
return UIApplicationMain (argc, argv, nil, NSStringFromClass ([DEMOAppDelegate class]));
}
}

View File

@ -0,0 +1,39 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow* window;
@end

View File

@ -0,0 +1,63 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
@end

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4510" systemVersion="12F45" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="AP8-8w-0De"/>
<viewControllerLayoutGuide type="bottom" id="c8g-3k-wFn"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zxO-df-3Nm">
<rect key="frame" x="205" y="483" width="142" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Simple Encoder Test">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="buttonPressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="pzf-mY-PCn"/>
</connections>
</button>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Status:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mpw-Vf-v58">
<rect key="frame" x="205" y="401" width="221" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<connections>
<outlet property="statusText" destination="Mpw-Vf-v58" id="BbS-da-1lz"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar" statusBarStyle="blackOpaque"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination"/>
</simulatedMetricsContainer>
</document>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4510" systemVersion="12F45" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="DZT-bO-vZS"/>
<viewControllerLayoutGuide type="bottom" id="mJc-f0-9sv"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Status:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HvX-56-M19">
<rect key="frame" x="93" y="336" width="55" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SXI-db-Dpk">
<rect key="frame" x="93" y="379" width="136" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Simple Encode Test">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="buttonPressed:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="1uY-7J-edO"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<connections>
<outlet property="statusText" destination="HvX-56-M19" id="KxK-QZ-DTo"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View File

@ -0,0 +1,53 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,51 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,44 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController {
UILabel* statusText_;
}
@property (retain, nonatomic) IBOutlet UILabel* statusText;
- (IBAction) buttonPressed: (id)sender;
@end

View File

@ -0,0 +1,89 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
extern int EncMain(int argc, char **argv);
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize statusText=statusText_;
- (void)viewDidLoad
{
[super viewDidLoad];
statusText_.text = @"Status: Ready for Go";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction) buttonPressed:(id)sender
{
NSBundle * bundle = [NSBundle mainBundle];
NSString * encCfg = [bundle pathForResource:@"welsenc_ios" ofType:@"cfg"];
NSString * dlayerCfg = [bundle pathForResource:@"layer2" ofType:@"cfg"];
NSString * yuvFile = [bundle pathForResource:@"CiscoVT2people_320x192_12fps" ofType:@"yuv"];
NSString * bsfile = [NSString stringWithFormat:@"%@/%@", [self getPathForWrite], @"test.264"];
NSLog(@"WELS_INFO: enc config file: %@, yuv file %@", encCfg, yuvFile);
const char * argv[] = {
"dummy",
[encCfg UTF8String],
"-org",
[yuvFile UTF8String],
"-bf",
[bsfile UTF8String],
"-numl",
"1",
"-lconfig",
"0",
[dlayerCfg UTF8String],
};
NSLog(@"WELS_INFO: enc config file: %@", encCfg);
EncMain(sizeof(argv)/sizeof(argv[0]), (char**)&argv[0]);
statusText_.text = @"Status: Test Over";
}
- (NSString*) getPathForWrite {
NSArray * pathes = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentDirectory = [pathes objectAtIndex:0];
return documentDirectory;
}
@end

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>cisco.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main_iPhone</string>
<key>UIMainStoryboardFile~ipad</key>
<string>Main_iPad</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,175 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
extern int EncMain (int argc, char** argv);
//redirect NSLog and stdout to logfile
void redirectLogToDocumentFile() {
NSArray* path = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString* document = [path objectAtIndex:0];
NSString* fileName = [NSString stringWithFormat:@"encPerf.log"];
NSString* logPath = [document stringByAppendingPathComponent:fileName];
NSFileManager* defaultManager = [NSFileManager defaultManager];
[defaultManager removeItemAtPath:logPath error:nil];
freopen ([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen ([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}
//to judge whether the path is needed case path
bool IsOneDeptDir (NSString* path) {
BOOL isDir = NO;
BOOL isOneDeptDir = NO;
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray* dirPathArray = [fileManager subpathsAtPath:path];
if ([dirPathArray count] == 0 || dirPathArray == nil)
isOneDeptDir = NO;
else {
for (NSString * dirPath in dirPathArray) {
NSString* tmpPath = [path stringByAppendingString:@"/"];
tmpPath = [tmpPath stringByAppendingString:dirPath];
[fileManager fileExistsAtPath:tmpPath isDirectory:&isDir];
if (isDir) {
isOneDeptDir = YES;
break;
}
}
}
return isOneDeptDir;
}
//run auto test to get encoder performance
int AutoTestEnc() {
NSString* document = [[NSString alloc] init];
NSArray* paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] == 0) {
NSLog (@"could not find document path");
return 2;
}
document = [paths objectAtIndex:0];
NSString* encFilePath = [document stringByAppendingString:@"/EncoderPerfTestRes"];
NSFileManager* manage = [NSFileManager defaultManager];
NSArray* cases = [manage subpathsAtPath:encFilePath];
if (cases == nil) {
NSLog (@"could not find any test case under encoderperftest");
return 1;
}
redirectLogToDocumentFile();
NSMutableArray* dirArray = [[NSMutableArray alloc] init];
for (NSString * casePath in cases) {
NSString* path = [encFilePath stringByAppendingPathComponent:casePath];
if (IsOneDeptDir (path)) {
[dirArray addObject:casePath];
}
}
for (int caseNO = 0; caseNO < [dirArray count]; caseNO++) {
NSString* caseName = [dirArray objectAtIndex:caseNO];
NSString* caseFilePath = [encFilePath stringByAppendingString:@"/"];
caseFilePath = [caseFilePath stringByAppendingString:caseName];
[manage changeCurrentDirectoryPath:[caseFilePath stringByExpandingTildeInPath]];
NSString* welscfg = [caseFilePath stringByAppendingString:@"/welsenc.cfg"];
NSString* layercfg = [caseFilePath stringByAppendingString:@"/layer2.cfg"];
NSString* yuvFilePath = [caseFilePath stringByAppendingString:@"/yuv"];
NSString* bitFilePath = [caseFilePath stringByAppendingString:@"/bit"];
[manage removeItemAtPath:bitFilePath error:nil];
[manage createDirectoryAtPath:bitFilePath withIntermediateDirectories:YES attributes:nil error:nil];
NSArray* files = [manage subpathsAtPath:yuvFilePath];
[manage changeCurrentDirectoryPath:[bitFilePath stringByExpandingTildeInPath]];
for (int i = 0; i < [files count]; i++) {
NSString* yuvFileName = [files objectAtIndex:i];
NSString* bitFileName = [yuvFileName stringByAppendingString:@".264"];
NSString* bitFileNamePath = [bitFilePath stringByAppendingString:@"/"];
bitFileName = [bitFileNamePath stringByAppendingString:bitFileName];
[manage createFileAtPath:bitFileName contents:nil attributes:nil];
[manage changeCurrentDirectoryPath:[yuvFilePath stringByExpandingTildeInPath]];
const char* argvv[] = {
"dummy",
[welscfg UTF8String],
"-org",
[yuvFileName UTF8String],
"-bf",
[bitFileName UTF8String],
"-numl",
"1",
"-lconfig",
"0",
[layercfg UTF8String]
};
NSLog (@"WELS_INFO: enc config file: %@", welscfg);
NSLog (@"WELS_INFO: enc yuv file: %@", yuvFileName);
EncMain (sizeof (argvv) / sizeof (argvv[0]), (char**)&argvv[0]);
fflush (stdout); // flush the content of stdout instantly
}
}
return 0;
}
int main (int argc, char* argv[]) {
//***For auto testing of encoder performance, call auto test here, if you not want to do auto test, you can comment it manualy
if (AutoTestEnc() == 0)
NSLog (@"Auto testing running sucessfully");
else
NSLog (@"Auto testing running failed");
abort();
//************************
@autoreleasepool {
return UIApplicationMain (argc, argv, nil, NSStringFromClass ([AppDelegate class]));
}
}

View File

@ -0,0 +1,15 @@
# Files generated by Visual Studio 2008
*.user
*.ncb
*.suo
Win32
x64
# Files generated by upgrading the project files
*.vcxproj*
Backup
UpgradeLog.htm
# Files generated by Visual Studio 2012
*.sdf

View File

@ -0,0 +1,996 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="WelsDecCore"
ProjectGUID="{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}"
RootNamespace="WelsDecCore"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
<DefaultToolFile
FileName="masm.rules"
/>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\decoder\core\inc;..\..\..\common\inc;..\..\..\api\svc"
PreprocessorDefinitions="NDEBUG;_LIB;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\welsdcore.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\decoder\core\inc;..\..\..\common\inc;..\..\..\api\svc"
PreprocessorDefinitions="NDEBUG;_LIB;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\welsdcore.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\decoder\core\inc;..\..\..\common\inc;..\..\..\api\svc"
PreprocessorDefinitions="_DEBUG;_LIB;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\welsdcore.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\decoder\core\inc;..\..\..\common\inc;..\..\..\api\svc"
PreprocessorDefinitions="_DEBUG;_LIB;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\welsdcore.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="asm"
Filter="*.asm;*.inc"
>
<File
RelativePath="..\..\..\common\x86\cpuid.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\dct.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName)_common.obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName)_common.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName)_common.obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName)_common.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName)_common.obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName)_common.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName)_common.obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName)_common.obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\decoder\core\x86\dct.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\deblock.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\expand_picture.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\decoder\core\x86\intra_pred.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\mb_copy.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\mc_chroma.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\..\common\x86\mc_luma.asm"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win32 -DPREFIX -DX86_32 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="nasm -I$(InputDir) -I$(InputDir)/../../../common/x86/ -f win64 -DWIN64 -o $(IntDir)\$(InputName).obj $(InputPath)&#x0D;&#x0A;"
Outputs="$(IntDir)\$(InputName).obj"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\..\decoder\core\inc\au_parser.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\bit_stream.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\cabac_decoder.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\copy_mb.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\cpu.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\cpu_core.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\deblocking.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\deblocking_common.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\dec_frame.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\dec_golomb.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\decode_mb_aux.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\decode_slice.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\decoder.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\decoder_context.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\decoder_core.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\error_code.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\error_concealment.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\expand_pic.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\fmo.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\get_intra_predictor.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\ls_defines.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\macros.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\manage_dec_ref.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\mb_cache.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\mc.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\measure_time.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\memmgr_nal_unit.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\memory_align.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\mv_pred.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\nal_prefix.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\nalu.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parameter_sets.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cabac.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cavlc.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\pic_queue.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\picture.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\rec_mb.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\slice.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\typedefs.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\utils.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\vlc_decoder.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\wels_common_basis.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\wels_common_defs.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\wels_const.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\wels_const_common.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\wels_decoder_thread.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\..\..\decoder\core\src\au_parser.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\bit_stream.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\cabac_decoder.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\common_tables.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\copy_mb.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\cpu.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\crt_util_safe_x.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\deblocking.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\deblocking_common.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\decode_mb_aux.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\decode_slice.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\decoder.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\decoder_core.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\decoder_data_tables.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\error_concealment.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\expand_pic.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\fmo.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\get_intra_predictor.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\manage_dec_ref.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\mc.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\memmgr_nal_unit.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\memory_align.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\mv_pred.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cabac.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cavlc.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\pic_queue.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\rec_mb.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\utils.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\WelsThreadLib.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\wels_decoder_thread.cpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,395 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="WelsDecPlus"
ProjectGUID="{1131558A-9986-4F4B-A13F-8B7F4C8438BF}"
RootNamespace="WelsDecPlus"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\decoder\plus\inc;..\..\..\decoder\core\inc;..\..\..\api\svc;..\..\..\common\inc"
PreprocessorDefinitions="NDEBUG;_USRDLL;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdcore.lib"
OutputFile="$(OutDir)\welsdec.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\..\..\decoder\plus\src\wels_dec_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsdec.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\decoder\plus\inc;..\..\..\decoder\core\inc;..\..\..\api\svc;..\..\..\common\inc"
PreprocessorDefinitions="NDEBUG;_USRDLL;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdcore.lib"
OutputFile="$(OutDir)\welsdec.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\..\..\decoder\plus\src\wels_dec_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsdec.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\decoder\plus\inc;..\..\..\decoder\core\inc;..\..\..\api\svc;..\..\..\common\inc"
PreprocessorDefinitions="_DEBUG;_USRDLL;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdcore.lib"
OutputFile="$(OutDir)\welsdec.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\..\..\decoder\plus\src\wels_dec_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsdec.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\decoder\plus\inc;..\..\..\decoder\core\inc;..\..\..\api\svc;..\..\..\common\inc"
PreprocessorDefinitions="_DEBUG;_USRDLL;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdcore.lib"
OutputFile="$(OutDir)\welsdec.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\..\..\decoder\plus\src\wels_dec_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsdec.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\..\common\inc\welsCodecTrace.h"
>
</File>
<File
RelativePath="..\..\..\decoder\plus\inc\welsDecoderExt.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
<File
RelativePath="..\..\..\..\openh264.rc"
>
</File>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\..\..\decoder\plus\src\wels_dec_export.def"
>
</File>
<File
RelativePath="..\..\..\common\src\welsCodecTrace.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\plus\src\welsDecoderExt.cpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,52 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WelsDecCore", "WelsDecCore.vcproj", "{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WelsDecPlus", "WelsDecPlus.vcproj", "{1131558A-9986-4F4B-A13F-8B7F4C8438BF}"
ProjectSection(ProjectDependencies) = postProject
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5} = {01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decConsole", "decConsole.vcproj", "{71973A8E-103D-4FB7-951F-55E35E7F60FA}"
ProjectSection(ProjectDependencies) = postProject
{1131558A-9986-4F4B-A13F-8B7F4C8438BF} = {1131558A-9986-4F4B-A13F-8B7F4C8438BF}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Debug|Win32.ActiveCfg = Debug|Win32
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Debug|Win32.Build.0 = Debug|Win32
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Debug|x64.ActiveCfg = Debug|x64
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Debug|x64.Build.0 = Debug|x64
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Release|Win32.ActiveCfg = Release|Win32
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Release|Win32.Build.0 = Release|Win32
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Release|x64.ActiveCfg = Release|x64
{01B4AE41-6AD6-4CAF-AEB3-C42F7F9121D5}.Release|x64.Build.0 = Release|x64
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Debug|Win32.ActiveCfg = Debug|Win32
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Debug|Win32.Build.0 = Debug|Win32
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Debug|x64.ActiveCfg = Debug|x64
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Debug|x64.Build.0 = Debug|x64
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Release|Win32.ActiveCfg = Release|Win32
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Release|Win32.Build.0 = Release|Win32
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Release|x64.ActiveCfg = Release|x64
{1131558A-9986-4F4B-A13F-8B7F4C8438BF}.Release|x64.Build.0 = Release|x64
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Debug|Win32.ActiveCfg = Debug|Win32
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Debug|Win32.Build.0 = Debug|Win32
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Debug|x64.ActiveCfg = Debug|x64
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Debug|x64.Build.0 = Debug|x64
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Release|Win32.ActiveCfg = Release|Win32
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Release|Win32.Build.0 = Release|Win32
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Release|x64.ActiveCfg = Release|x64
{71973A8E-103D-4FB7-951F-55E35E7F60FA}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,389 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="decConsole"
ProjectGUID="{71973A8E-103D-4FB7-951F-55E35E7F60FA}"
RootNamespace="decConsole"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\console\dec\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\common\inc"
PreprocessorDefinitions="NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2052"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdec.lib"
OutputFile="$(OutDir)\decConsole.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\decConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\console\dec\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\common\inc"
PreprocessorDefinitions="NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2052"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdec.lib"
OutputFile="$(OutDir)\decConsole.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\decConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\console\dec\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\common\inc"
PreprocessorDefinitions="_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2052"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdec.lib"
OutputFile="$(OutDir)\decConsoled.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\decConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\console\dec\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\common\inc"
PreprocessorDefinitions="_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2052"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsdec.lib"
OutputFile="$(OutDir)\decConsoled.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\decConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\..\..\console\dec\src\d3d9_utils.cpp"
>
</File>
<File
RelativePath="..\..\..\console\dec\src\h264dec.cpp"
>
</File>
<File
RelativePath="..\..\..\console\common\src\read_config.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\..\console\dec\inc\d3d9_utils.h"
>
</File>
<File
RelativePath="..\..\..\console\common\inc\read_config.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,405 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="WelsEncPlus"
ProjectGUID="{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}"
RootNamespace="WelsEncPlus"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\encoder\plus\inc;..\..\..\encoder\core\inc;..\..\..\api\svc;..\..\..\common\inc;..\..\..\processing\interface"
PreprocessorDefinitions="_DEBUG;_USRDLL;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsecore.lib $(OutDir)\welsvp.lib"
OutputFile="$(OutDir)\welsenc.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\..\..\encoder\plus\src\wels_enc_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsenc.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)/WelsEncPlus.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\encoder\plus\inc;..\..\..\encoder\core\inc;..\..\..\api\svc;..\..\..\common\inc;..\..\..\processing\interface"
PreprocessorDefinitions="_DEBUG;_USRDLL;X86_ASM"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsecore.lib $(OutDir)\welsvp.lib"
OutputFile="$(OutDir)\welsenc.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\..\..\encoder\plus\src\wels_enc_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsenc.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)/WelsEncPlus.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..\..\..\encoder\plus\inc;..\..\..\encoder\core\inc;..\..\..\api\svc;..\..\..\common\inc;..\..\..\processing\interface"
PreprocessorDefinitions="NDEBUG;_USRDLL;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsecore.lib $(OutDir)\welsvp.lib"
OutputFile="$(OutDir)\welsenc.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\..\..\encoder\plus\src\wels_enc_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsenc.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)/WelsEncPlus.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..\..\..\encoder\plus\inc;..\..\..\encoder\core\inc;..\..\..\api\svc;..\..\..\common\inc;..\..\..\processing\interface"
PreprocessorDefinitions="NDEBUG;_USRDLL;X86_ASM"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsecore.lib $(OutDir)\welsvp.lib"
OutputFile="$(OutDir)\welsenc.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\..\..\encoder\plus\src\wels_enc_export.def"
GenerateDebugInformation="true"
RandomizedBaseAddress="2"
DataExecutionPrevention="2"
ImportLibrary="$(OutDir)\welsenc.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)/WelsEncPlus.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\..\..\encoder\plus\src\DllEntry.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\plus\src\wels_enc_export.def"
>
</File>
<File
RelativePath="..\..\..\common\src\welsCodecTrace.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\plus\src\welsEncoderExt.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\..\common\inc\welsCodecTrace.h"
>
</File>
<File
RelativePath="..\..\..\encoder\plus\inc\welsEncoderExt.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
<File
RelativePath="..\..\..\..\openh264.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,66 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WelsEncCore", "WelsEncCore.vcproj", "{59208004-1774-4816-AC24-31FF44C324B4}"
ProjectSection(ProjectDependencies) = postProject
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562} = {E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WelsEncPlus", "WelsEncPlus.vcproj", "{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}"
ProjectSection(ProjectDependencies) = postProject
{59208004-1774-4816-AC24-31FF44C324B4} = {59208004-1774-4816-AC24-31FF44C324B4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encConsole", "encConsole.vcproj", "{8509E2A8-2CBD-49E2-B564-3EFF1E927459}"
ProjectSection(ProjectDependencies) = postProject
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F} = {1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562} = {E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WelsVP", "..\..\..\processing\build\win32\WelsVP.vcproj", "{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{59208004-1774-4816-AC24-31FF44C324B4}.Debug|Win32.ActiveCfg = Debug|Win32
{59208004-1774-4816-AC24-31FF44C324B4}.Debug|Win32.Build.0 = Debug|Win32
{59208004-1774-4816-AC24-31FF44C324B4}.Debug|x64.ActiveCfg = Debug|x64
{59208004-1774-4816-AC24-31FF44C324B4}.Debug|x64.Build.0 = Debug|x64
{59208004-1774-4816-AC24-31FF44C324B4}.Release|Win32.ActiveCfg = Release|Win32
{59208004-1774-4816-AC24-31FF44C324B4}.Release|Win32.Build.0 = Release|Win32
{59208004-1774-4816-AC24-31FF44C324B4}.Release|x64.ActiveCfg = Release|x64
{59208004-1774-4816-AC24-31FF44C324B4}.Release|x64.Build.0 = Release|x64
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Debug|Win32.ActiveCfg = Debug|Win32
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Debug|Win32.Build.0 = Debug|Win32
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Debug|x64.ActiveCfg = Debug|x64
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Debug|x64.Build.0 = Debug|x64
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Release|Win32.ActiveCfg = Release|Win32
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Release|Win32.Build.0 = Release|Win32
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Release|x64.ActiveCfg = Release|x64
{1E7B4E9A-986E-4167-8C70-6E4F60EAEE7F}.Release|x64.Build.0 = Release|x64
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Debug|Win32.ActiveCfg = Debug|Win32
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Debug|Win32.Build.0 = Debug|Win32
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Debug|x64.ActiveCfg = Debug|x64
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Debug|x64.Build.0 = Debug|x64
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Release|Win32.ActiveCfg = Release|Win32
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Release|Win32.Build.0 = Release|Win32
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Release|x64.ActiveCfg = Release|x64
{8509E2A8-2CBD-49E2-B564-3EFF1E927459}.Release|x64.Build.0 = Release|x64
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Debug|Win32.ActiveCfg = Debug|Win32
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Debug|Win32.Build.0 = Debug|Win32
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Debug|x64.ActiveCfg = Debug|x64
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Debug|x64.Build.0 = Debug|x64
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Release|Win32.ActiveCfg = Release|Win32
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Release|Win32.Build.0 = Release|Win32
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Release|x64.ActiveCfg = Release|x64
{E8DFAFA1-8DAC-4127-8D27-FBD5819EE562}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,381 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="encConsole"
ProjectGUID="{8509E2A8-2CBD-49E2-B564-3EFF1E927459}"
RootNamespace="encConsole"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\console\enc\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\encoder\core\inc,..\..\..\common\inc,..\..\..\processing\interface"
PreprocessorDefinitions="_DEBUG;_CONSOLE;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsenc.lib"
OutputFile="$(OutDir)\encConsole.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\encConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\console\enc\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\encoder\core\inc,..\..\..\common\inc,..\..\..\processing\interface"
PreprocessorDefinitions="_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsenc.lib"
OutputFile="$(OutDir)\encConsole.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\encConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\console\enc\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\encoder\core\inc,..\..\..\common\inc,..\..\..\processing\interface"
PreprocessorDefinitions="NDEBUG;_CONSOLE;X86_ASM;"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsenc.lib"
OutputFile="$(OutDir)\encConsole.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\encConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\console\enc\inc,..\..\..\console\common\inc,..\..\..\api\svc,..\..\..\encoder\core\inc,..\..\..\common\inc,..\..\..\processing\interface"
PreprocessorDefinitions="NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\welsenc.lib"
OutputFile="$(OutDir)\encConsole.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
OutputFile="$(OutDir)\encConsole.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\..\..\console\common\src\read_config.cpp"
>
</File>
<File
RelativePath="..\..\..\console\enc\src\welsenc.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\..\console\common\inc\read_config.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,29 @@
# Files generated by Visual Studio 2008
*.user
*.ncb
*.suo
*.opensdf
Win32
x64
ARM
Debug
Release
# Files generated by upgrading the project files
Backup
Generated Files
UpgradeLog.htm
# Files generated by Visual Studio 2013
*.sdf
ipch
Draft
# Files used in App
Bin
obj
res
*.dll
*.yuv
*.264

View File

@ -0,0 +1,76 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodecApp", "CodecApp\CodecApp.csproj", "{5424CF29-908E-417E-93F3-F1CD81E5372C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodecRTComponent", "CodecRTComponent.vcxproj", "{FE5BF241-F4EA-4B94-B36A-23511E5908EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|ARM.ActiveCfg = Debug|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|ARM.Build.0 = Debug|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|ARM.Deploy.0 = Debug|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Mixed Platforms.Build.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Mixed Platforms.Deploy.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Win32.ActiveCfg = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Win32.Build.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|Win32.Deploy.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|x86.ActiveCfg = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|x86.Build.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Debug|x86.Deploy.0 = Debug|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Any CPU.Build.0 = Release|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Any CPU.Deploy.0 = Release|Any CPU
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|ARM.ActiveCfg = Release|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|ARM.Build.0 = Release|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|ARM.Deploy.0 = Release|ARM
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Mixed Platforms.ActiveCfg = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Mixed Platforms.Build.0 = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Mixed Platforms.Deploy.0 = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Win32.ActiveCfg = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Win32.Build.0 = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|Win32.Deploy.0 = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|x86.ActiveCfg = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|x86.Build.0 = Release|x86
{5424CF29-908E-417E-93F3-F1CD81E5372C}.Release|x86.Deploy.0 = Release|x86
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|Any CPU.ActiveCfg = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|ARM.ActiveCfg = Debug|ARM
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|ARM.Build.0 = Debug|ARM
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|Win32.ActiveCfg = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|Win32.Build.0 = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|x86.ActiveCfg = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Debug|x86.Build.0 = Debug|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|Any CPU.ActiveCfg = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|ARM.ActiveCfg = Release|ARM
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|ARM.Build.0 = Release|ARM
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|Mixed Platforms.Build.0 = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|Win32.ActiveCfg = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|Win32.Build.0 = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|x86.ActiveCfg = Release|Win32
{FE5BF241-F4EA-4B94-B36A-23511E5908EC}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,20 @@
<Application
x:Class="CodecApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
<!--Application Resources-->
<Application.Resources>
<local:LocalizedStrings xmlns:local="clr-namespace:CodecApp" x:Key="LocalizedStrings"/>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>

View File

@ -0,0 +1,223 @@
using System;
using System.Diagnostics;
using System.Resources;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using CodecApp.Resources;
namespace CodecApp
{
public partial class App : Application
{
/// <summary>
/// Provides easy access to the root frame of the Phone Application.
/// </summary>
/// <returns>The root frame of the Phone Application.</returns>
public static PhoneApplicationFrame RootFrame { get; private set; }
/// <summary>
/// Constructor for the Application object.
/// </summary>
public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
// Standard XAML initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
// Language display initialization
InitializeLanguage();
// Show graphics profiling information while debugging.
if (Debugger.IsAttached)
{
// Display the current frame rate counters.
Application.Current.Host.Settings.EnableFrameRateCounter = true;
// Show the areas of the app that are being redrawn in each frame.
//Application.Current.Host.Settings.EnableRedrawRegions = true;
// Enable non-production analysis visualization mode,
// which shows areas of a page that are handed off to GPU with a colored overlay.
//Application.Current.Host.Settings.EnableCacheVisualization = true;
// Prevent the screen from turning off while under the debugger by disabling
// the application's idle detection.
// Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
// and consume battery power when the user is not using the phone.
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
}
// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
}
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
}
// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
}
// Code to execute if a navigation fails
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (Debugger.IsAttached)
{
// A navigation has failed; break into the debugger
Debugger.Break();
}
}
// Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (Debugger.IsAttached)
{
// An unhandled exception has occurred; break into the debugger
Debugger.Break();
}
}
#region Phone application initialization
// Avoid double-initialization
private bool phoneApplicationInitialized = false;
// Do not add any additional code to this method
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
// Handle reset requests for clearing the backstack
RootFrame.Navigated += CheckForResetNavigation;
// Ensure we don't initialize again
phoneApplicationInitialized = true;
}
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
{
// If the app has received a 'reset' navigation, then we need to check
// on the next navigation to see if the page stack should be reset
if (e.NavigationMode == NavigationMode.Reset)
RootFrame.Navigated += ClearBackStackAfterReset;
}
private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
{
// Unregister the event so it doesn't get called again
RootFrame.Navigated -= ClearBackStackAfterReset;
// Only clear the stack for 'new' (forward) and 'refresh' navigations
if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
return;
// For UI consistency, clear the entire page stack
while (RootFrame.RemoveBackEntry() != null)
{
; // do nothing
}
}
#endregion
// Initialize the app's font and flow direction as defined in its localized resource strings.
//
// To ensure that the font of your application is aligned with its supported languages and that the
// FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
// and ResourceFlowDirection should be initialized in each resx file to match these values with that
// file's culture. For example:
//
// AppResources.es-ES.resx
// ResourceLanguage's value should be "es-ES"
// ResourceFlowDirection's value should be "LeftToRight"
//
// AppResources.ar-SA.resx
// ResourceLanguage's value should be "ar-SA"
// ResourceFlowDirection's value should be "RightToLeft"
//
// For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
//
private void InitializeLanguage()
{
try
{
// Set the font to match the display language defined by the
// ResourceLanguage resource string for each supported language.
//
// Fall back to the font of the neutral language if the Display
// language of the phone is not supported.
//
// If a compiler error is hit then ResourceLanguage is missing from
// the resource file.
RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
// Set the FlowDirection of all elements under the root frame based
// on the ResourceFlowDirection resource string for each
// supported language.
//
// If a compiler error is hit then ResourceFlowDirection is missing from
// the resource file.
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
RootFrame.FlowDirection = flow;
}
catch
{
// If an exception is caught here it is most likely due to either
// ResourceLangauge not being correctly set to a supported language
// code or ResourceFlowDirection is set to a value other than LeftToRight
// or RightToLeft.
if (Debugger.IsAttached)
{
Debugger.Break();
}
throw;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Some files were not shown because too many files have changed in this diff Show More