1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if PLATFORM(WIN) && ENABLE(VIDEO) && HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) 29 30#include "InbandTextTrackPrivateAVCF.h" 31 32#include "FloatConversion.h" 33#include "InbandTextTrackPrivate.h" 34#include "InbandTextTrackPrivateAVF.h" 35#include "Logging.h" 36#include "SoftLinking.h" 37 38#include <AVFoundationCF/AVCFPlayerItemLegibleOutput.h> 39#include <AVFoundationCF/AVFoundationCF.h> 40 41#include <d3d9.h> 42 43// The softlink header files must be included after the AVCF and CoreMedia header files. 44#include "AVFoundationCFSoftLinking.h" 45 46namespace WebCore { 47 48InbandTextTrackPrivateAVCF::InbandTextTrackPrivateAVCF(AVFInbandTrackParent* player, AVCFMediaSelectionOptionRef selection, InbandTextTrackPrivate::CueFormat format) 49 : InbandTextTrackPrivateAVF(player, format) 50 , m_mediaSelectionOption(selection) 51{ 52} 53 54void InbandTextTrackPrivateAVCF::disconnect() 55{ 56 m_mediaSelectionOption = 0; 57 InbandTextTrackPrivateAVF::disconnect(); 58} 59 60InbandTextTrackPrivate::Kind InbandTextTrackPrivateAVCF::kind() const 61{ 62 if (!m_mediaSelectionOption) 63 return InbandTextTrackPrivate::None; 64 65 CFStringRef mediaType = AVCFMediaSelectionOptionGetMediaType(mediaSelectionOption()); 66 67 if (CFStringCompare(mediaType, AVCFMediaTypeClosedCaption, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 68 return InbandTextTrackPrivate::Captions; 69 if (CFStringCompare(mediaType, AVCFMediaTypeSubtitle, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 70 if (AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicContainsOnlyForcedSubtitles)) 71 return InbandTextTrackPrivate::Forced; 72 73 // An "SDH" track is a subtitle track created for the deaf or hard-of-hearing. "captions" in WebVTT are 74 // "labeled as appropriate for the hard-of-hearing", so tag SDH sutitles as "captions". 75 if (AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicTranscribesSpokenDialogForAccessibility)) 76 return InbandTextTrackPrivate::Captions; 77 if (AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicDescribesMusicAndSoundForAccessibility)) 78 return InbandTextTrackPrivate::Captions; 79 80 return InbandTextTrackPrivate::Subtitles; 81 } 82 83 return InbandTextTrackPrivate::Captions; 84} 85 86bool InbandTextTrackPrivateAVCF::isClosedCaptions() const 87{ 88 if (!m_mediaSelectionOption) 89 return false; 90 91 CFStringRef mediaType = AVCFMediaSelectionOptionGetMediaType(mediaSelectionOption()); 92 93 return (CFStringCompare(mediaType, AVCFMediaTypeClosedCaption, kCFCompareCaseInsensitive) == kCFCompareEqualTo); 94} 95 96bool InbandTextTrackPrivateAVCF::isSDH() const 97{ 98 if (!m_mediaSelectionOption) 99 return false; 100 101 CFStringRef mediaType = AVCFMediaSelectionOptionGetMediaType(mediaSelectionOption()); 102 103 if (CFStringCompare(mediaType, AVCFMediaTypeSubtitle, kCFCompareCaseInsensitive) != kCFCompareEqualTo) 104 return false; 105 106 if (AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicTranscribesSpokenDialogForAccessibility) 107 && AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicDescribesMusicAndSoundForAccessibility)) 108 return true; 109 110 return false; 111} 112 113bool InbandTextTrackPrivateAVCF::containsOnlyForcedSubtitles() const 114{ 115 if (!m_mediaSelectionOption) 116 return false; 117 118 return AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicContainsOnlyForcedSubtitles); 119} 120 121bool InbandTextTrackPrivateAVCF::isMainProgramContent() const 122{ 123 if (!m_mediaSelectionOption) 124 return false; 125 126 return AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicIsMainProgramContent); 127} 128 129bool InbandTextTrackPrivateAVCF::isEasyToRead() const 130{ 131 if (!m_mediaSelectionOption) 132 return false; 133 134 return AVCFMediaSelectionOptionHasMediaCharacteristic(mediaSelectionOption(), AVCFMediaCharacteristicEasyToRead); 135} 136 137AtomicString InbandTextTrackPrivateAVCF::label() const 138{ 139 if (!m_mediaSelectionOption) 140 return emptyAtom; 141 142 RetainPtr<CFStringRef> title; 143 144 RetainPtr<CFArrayRef> commonMetaData = adoptCF(AVCFMediaSelectionOptionCopyCommonMetadata(mediaSelectionOption())); 145 RetainPtr<CFArrayRef> titles = adoptCF(AVCFMetadataItemCopyItemsWithKeyAndKeySpace(commonMetaData.get(), AVCFMetadataCommonKeyTitle, AVCFMetadataKeySpaceCommon)); 146 CFIndex titlesCount = CFArrayGetCount(titles.get()); 147 if (!titlesCount) 148 return emptyAtom; 149 150 // If possible, return a title in one of the user's preferred languages. 151 RetainPtr<CFArrayRef> preferredLanguages = adoptCF(CFLocaleCopyPreferredLanguages()); 152 RetainPtr<CFArrayRef> titlesForPreferredLanguages = adoptCF(AVCFMediaSelectionCopyOptionsFromArrayFilteredAndSortedAccordingToPreferredLanguages(titles.get(), preferredLanguages.get())); 153 CFIndex preferredTitlesCount = CFArrayGetCount(titlesForPreferredLanguages.get()); 154 if (preferredTitlesCount) { 155 AVCFMetadataItemRef titleMetadata = static_cast<AVCFMetadataItemRef>(CFArrayGetValueAtIndex(titlesForPreferredLanguages.get(), 0)); 156 title = adoptCF(AVCFMetadataItemCopyStringValue(titleMetadata)); 157 } 158 159 if (!title) { 160 AVCFMetadataItemRef titleMetadata = static_cast<AVCFMetadataItemRef>(CFArrayGetValueAtIndex(titles.get(), 0)); 161 title = adoptCF(AVCFMetadataItemCopyStringValue(titleMetadata)); 162 } 163 164 return title ? AtomicString(title.get()) : emptyAtom; 165} 166 167AtomicString InbandTextTrackPrivateAVCF::language() const 168{ 169 if (!m_mediaSelectionOption) 170 return emptyAtom; 171 172 RetainPtr<CFLocaleRef> locale = adoptCF(AVCFMediaSelectionOptionCopyLocale(mediaSelectionOption())); 173 return CFLocaleGetIdentifier(locale.get()); 174} 175 176bool InbandTextTrackPrivateAVCF::isDefault() const 177{ 178 return false; 179} 180 181} // namespace WebCore 182 183#endif 184