DecoderFactory.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "DecoderFactory.h"
  6. #include "gfxPrefs.h"
  7. #include "nsMimeTypes.h"
  8. #include "mozilla/RefPtr.h"
  9. #include "AnimationSurfaceProvider.h"
  10. #include "Decoder.h"
  11. #include "IDecodingTask.h"
  12. #include "nsPNGDecoder.h"
  13. #include "nsGIFDecoder2.h"
  14. #include "nsJPEGDecoder.h"
  15. #include "nsBMPDecoder.h"
  16. #include "nsICODecoder.h"
  17. #include "nsIconDecoder.h"
  18. #include "nsWebPDecoder.h"
  19. namespace mozilla {
  20. using namespace gfx;
  21. namespace image {
  22. /* static */ DecoderType
  23. DecoderFactory::GetDecoderType(const char* aMimeType)
  24. {
  25. // By default we don't know.
  26. DecoderType type = DecoderType::UNKNOWN;
  27. // PNG
  28. if (!strcmp(aMimeType, IMAGE_PNG)) {
  29. type = DecoderType::PNG;
  30. } else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
  31. type = DecoderType::PNG;
  32. } else if (!strcmp(aMimeType, IMAGE_APNG)) {
  33. type = DecoderType::PNG;
  34. // GIF
  35. } else if (!strcmp(aMimeType, IMAGE_GIF)) {
  36. type = DecoderType::GIF;
  37. // JPEG
  38. } else if (!strcmp(aMimeType, IMAGE_JPEG)) {
  39. type = DecoderType::JPEG;
  40. } else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
  41. type = DecoderType::JPEG;
  42. } else if (!strcmp(aMimeType, IMAGE_JPG)) {
  43. type = DecoderType::JPEG;
  44. // BMP
  45. } else if (!strcmp(aMimeType, IMAGE_BMP)) {
  46. type = DecoderType::BMP;
  47. } else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
  48. type = DecoderType::BMP;
  49. // BMP_CLIPBOARD
  50. } else if (!strcmp(aMimeType, IMAGE_BMP_MS_CLIPBOARD)) {
  51. type = DecoderType::BMP_CLIPBOARD;
  52. // ICO
  53. } else if (!strcmp(aMimeType, IMAGE_ICO)) {
  54. type = DecoderType::ICO;
  55. } else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
  56. type = DecoderType::ICO;
  57. // Icon
  58. } else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
  59. type = DecoderType::ICON;
  60. // WebP
  61. } else if (!strcmp(aMimeType, IMAGE_WEBP) &&
  62. gfxPrefs::ImageWebPEnabled()) {
  63. type = DecoderType::WEBP;
  64. }
  65. return type;
  66. }
  67. /* static */ already_AddRefed<Decoder>
  68. DecoderFactory::GetDecoder(DecoderType aType,
  69. RasterImage* aImage,
  70. bool aIsRedecode)
  71. {
  72. RefPtr<Decoder> decoder;
  73. switch (aType) {
  74. case DecoderType::PNG:
  75. decoder = new nsPNGDecoder(aImage);
  76. break;
  77. case DecoderType::GIF:
  78. decoder = new nsGIFDecoder2(aImage);
  79. break;
  80. case DecoderType::JPEG:
  81. // If we have all the data we don't want to waste cpu time doing
  82. // a progressive decode.
  83. decoder = new nsJPEGDecoder(aImage,
  84. aIsRedecode ? Decoder::SEQUENTIAL
  85. : Decoder::PROGRESSIVE);
  86. break;
  87. case DecoderType::BMP:
  88. decoder = new nsBMPDecoder(aImage);
  89. break;
  90. case DecoderType::BMP_CLIPBOARD:
  91. decoder = new nsBMPDecoder(aImage, /* aForClipboard */ true);
  92. break;
  93. case DecoderType::ICO:
  94. decoder = new nsICODecoder(aImage);
  95. break;
  96. case DecoderType::ICON:
  97. decoder = new nsIconDecoder(aImage);
  98. break;
  99. case DecoderType::WEBP:
  100. decoder = new nsWebPDecoder(aImage);
  101. break;
  102. default:
  103. MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
  104. }
  105. return decoder.forget();
  106. }
  107. /* static */ already_AddRefed<IDecodingTask>
  108. DecoderFactory::CreateDecoder(DecoderType aType,
  109. NotNull<RasterImage*> aImage,
  110. NotNull<SourceBuffer*> aSourceBuffer,
  111. const IntSize& aIntrinsicSize,
  112. const IntSize& aOutputSize,
  113. DecoderFlags aDecoderFlags,
  114. SurfaceFlags aSurfaceFlags,
  115. int aSampleSize)
  116. {
  117. if (aType == DecoderType::UNKNOWN) {
  118. return nullptr;
  119. }
  120. // Create an anonymous decoder. Interaction with the SurfaceCache and the
  121. // owning RasterImage will be mediated by DecodedSurfaceProvider.
  122. RefPtr<Decoder> decoder =
  123. GetDecoder(aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
  124. MOZ_ASSERT(decoder, "Should have a decoder now");
  125. // Initialize the decoder.
  126. decoder->SetMetadataDecode(false);
  127. decoder->SetIterator(aSourceBuffer->Iterator());
  128. decoder->SetOutputSize(aOutputSize);
  129. decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
  130. decoder->SetSurfaceFlags(aSurfaceFlags);
  131. decoder->SetSampleSize(aSampleSize);
  132. if (NS_FAILED(decoder->Init())) {
  133. return nullptr;
  134. }
  135. // Create a DecodedSurfaceProvider which will manage the decoding process and
  136. // make this decoder's output available in the surface cache.
  137. SurfaceKey surfaceKey =
  138. RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
  139. NotNull<RefPtr<DecodedSurfaceProvider>> provider =
  140. WrapNotNull(new DecodedSurfaceProvider(aImage,
  141. surfaceKey,
  142. WrapNotNull(decoder)));
  143. // Attempt to insert the surface provider into the surface cache right away so
  144. // we won't trigger any more decoders with the same parameters.
  145. if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
  146. return nullptr;
  147. }
  148. // Return the surface provider in its IDecodingTask guise.
  149. RefPtr<IDecodingTask> task = provider.get();
  150. return task.forget();
  151. }
  152. /* static */ already_AddRefed<IDecodingTask>
  153. DecoderFactory::CreateAnimationDecoder(DecoderType aType,
  154. NotNull<RasterImage*> aImage,
  155. NotNull<SourceBuffer*> aSourceBuffer,
  156. const IntSize& aIntrinsicSize,
  157. DecoderFlags aDecoderFlags,
  158. SurfaceFlags aSurfaceFlags)
  159. {
  160. if (aType == DecoderType::UNKNOWN) {
  161. return nullptr;
  162. }
  163. MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG ||
  164. aType == DecoderType::WEBP,
  165. "Calling CreateAnimationDecoder for non-animating DecoderType");
  166. // Create an anonymous decoder. Interaction with the SurfaceCache and the
  167. // owning RasterImage will be mediated by AnimationSurfaceProvider.
  168. RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, /* aIsRedecode = */ true);
  169. MOZ_ASSERT(decoder, "Should have a decoder now");
  170. // Initialize the decoder.
  171. decoder->SetMetadataDecode(false);
  172. decoder->SetIterator(aSourceBuffer->Iterator());
  173. decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
  174. decoder->SetSurfaceFlags(aSurfaceFlags);
  175. if (NS_FAILED(decoder->Init())) {
  176. return nullptr;
  177. }
  178. // Create an AnimationSurfaceProvider which will manage the decoding process
  179. // and make this decoder's output available in the surface cache.
  180. SurfaceKey surfaceKey =
  181. RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated);
  182. NotNull<RefPtr<AnimationSurfaceProvider>> provider =
  183. WrapNotNull(new AnimationSurfaceProvider(aImage,
  184. surfaceKey,
  185. WrapNotNull(decoder)));
  186. // Attempt to insert the surface provider into the surface cache right away so
  187. // we won't trigger any more decoders with the same parameters.
  188. if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
  189. return nullptr;
  190. }
  191. // Return the surface provider in its IDecodingTask guise.
  192. RefPtr<IDecodingTask> task = provider.get();
  193. return task.forget();
  194. }
  195. /* static */ already_AddRefed<IDecodingTask>
  196. DecoderFactory::CreateMetadataDecoder(DecoderType aType,
  197. NotNull<RasterImage*> aImage,
  198. NotNull<SourceBuffer*> aSourceBuffer,
  199. int aSampleSize)
  200. {
  201. if (aType == DecoderType::UNKNOWN) {
  202. return nullptr;
  203. }
  204. RefPtr<Decoder> decoder =
  205. GetDecoder(aType, aImage, /* aIsRedecode = */ false);
  206. MOZ_ASSERT(decoder, "Should have a decoder now");
  207. // Initialize the decoder.
  208. decoder->SetMetadataDecode(true);
  209. decoder->SetIterator(aSourceBuffer->Iterator());
  210. decoder->SetSampleSize(aSampleSize);
  211. if (NS_FAILED(decoder->Init())) {
  212. return nullptr;
  213. }
  214. RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
  215. return task.forget();
  216. }
  217. /* static */ already_AddRefed<Decoder>
  218. DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
  219. NotNull<SourceBuffer*> aSourceBuffer,
  220. NotNull<nsICODecoder*> aICODecoder,
  221. const Maybe<uint32_t>& aDataOffset
  222. /* = Nothing() */)
  223. {
  224. // Create the decoder.
  225. RefPtr<Decoder> decoder;
  226. switch (aType) {
  227. case DecoderType::BMP:
  228. MOZ_ASSERT(aDataOffset);
  229. decoder = new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset);
  230. break;
  231. case DecoderType::PNG:
  232. MOZ_ASSERT(!aDataOffset);
  233. decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull());
  234. break;
  235. default:
  236. MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
  237. return nullptr;
  238. }
  239. MOZ_ASSERT(decoder);
  240. // Initialize the decoder, copying settings from @aICODecoder.
  241. MOZ_ASSERT(!aICODecoder->IsMetadataDecode());
  242. decoder->SetMetadataDecode(aICODecoder->IsMetadataDecode());
  243. decoder->SetIterator(aSourceBuffer->Iterator());
  244. decoder->SetOutputSize(aICODecoder->OutputSize());
  245. decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
  246. decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
  247. if (NS_FAILED(decoder->Init())) {
  248. return nullptr;
  249. }
  250. return decoder.forget();
  251. }
  252. /* static */ already_AddRefed<Decoder>
  253. DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
  254. NotNull<SourceBuffer*> aSourceBuffer,
  255. const Maybe<IntSize>& aOutputSize,
  256. SurfaceFlags aSurfaceFlags)
  257. {
  258. if (aType == DecoderType::UNKNOWN) {
  259. return nullptr;
  260. }
  261. RefPtr<Decoder> decoder =
  262. GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
  263. MOZ_ASSERT(decoder, "Should have a decoder now");
  264. // Initialize the decoder.
  265. decoder->SetMetadataDecode(false);
  266. decoder->SetIterator(aSourceBuffer->Iterator());
  267. // Anonymous decoders are always transient; we don't want to optimize surfaces
  268. // or do any other expensive work that might be wasted.
  269. DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT;
  270. // Without an image, the decoder can't store anything in the SurfaceCache, so
  271. // callers will only be able to retrieve the most recent frame via
  272. // Decoder::GetCurrentFrame(). That means that anonymous decoders should
  273. // always be first-frame-only decoders, because nobody ever wants the *last*
  274. // frame.
  275. decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY;
  276. decoder->SetDecoderFlags(decoderFlags);
  277. decoder->SetSurfaceFlags(aSurfaceFlags);
  278. // Set an output size for downscale-during-decode if requested.
  279. if (aOutputSize) {
  280. decoder->SetOutputSize(*aOutputSize);
  281. }
  282. if (NS_FAILED(decoder->Init())) {
  283. return nullptr;
  284. }
  285. return decoder.forget();
  286. }
  287. /* static */ already_AddRefed<Decoder>
  288. DecoderFactory::CreateAnonymousMetadataDecoder(DecoderType aType,
  289. NotNull<SourceBuffer*> aSourceBuffer)
  290. {
  291. if (aType == DecoderType::UNKNOWN) {
  292. return nullptr;
  293. }
  294. RefPtr<Decoder> decoder =
  295. GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
  296. MOZ_ASSERT(decoder, "Should have a decoder now");
  297. // Initialize the decoder.
  298. decoder->SetMetadataDecode(true);
  299. decoder->SetIterator(aSourceBuffer->Iterator());
  300. decoder->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY);
  301. if (NS_FAILED(decoder->Init())) {
  302. return nullptr;
  303. }
  304. return decoder.forget();
  305. }
  306. } // namespace image
  307. } // namespace mozilla