demux.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. // Copyright 2012 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // WebP container demux.
  11. //
  12. #ifdef HAVE_CONFIG_H
  13. #include "../webp/config.h"
  14. #endif
  15. #include <assert.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "../utils/utils.h"
  19. #include "../webp/decode.h" // WebPGetFeatures
  20. #include "../webp/demux.h"
  21. #include "../webp/format_constants.h"
  22. #define DMUX_MAJ_VERSION 0
  23. #define DMUX_MIN_VERSION 3
  24. #define DMUX_REV_VERSION 2
  25. typedef struct {
  26. size_t start_; // start location of the data
  27. size_t end_; // end location
  28. size_t riff_end_; // riff chunk end location, can be > end_.
  29. size_t buf_size_; // size of the buffer
  30. const uint8_t* buf_;
  31. } MemBuffer;
  32. typedef struct {
  33. size_t offset_;
  34. size_t size_;
  35. } ChunkData;
  36. typedef struct Frame {
  37. int x_offset_, y_offset_;
  38. int width_, height_;
  39. int has_alpha_;
  40. int duration_;
  41. WebPMuxAnimDispose dispose_method_;
  42. WebPMuxAnimBlend blend_method_;
  43. int frame_num_;
  44. int complete_; // img_components_ contains a full image.
  45. ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH
  46. struct Frame* next_;
  47. } Frame;
  48. typedef struct Chunk {
  49. ChunkData data_;
  50. struct Chunk* next_;
  51. } Chunk;
  52. struct WebPDemuxer {
  53. MemBuffer mem_;
  54. WebPDemuxState state_;
  55. int is_ext_format_;
  56. uint32_t feature_flags_;
  57. int canvas_width_, canvas_height_;
  58. int loop_count_;
  59. uint32_t bgcolor_;
  60. int num_frames_;
  61. Frame* frames_;
  62. Frame** frames_tail_;
  63. Chunk* chunks_; // non-image chunks
  64. Chunk** chunks_tail_;
  65. };
  66. typedef enum {
  67. PARSE_OK,
  68. PARSE_NEED_MORE_DATA,
  69. PARSE_ERROR
  70. } ParseStatus;
  71. typedef struct ChunkParser {
  72. uint8_t id[4];
  73. ParseStatus (*parse)(WebPDemuxer* const dmux);
  74. int (*valid)(const WebPDemuxer* const dmux);
  75. } ChunkParser;
  76. static ParseStatus ParseSingleImage(WebPDemuxer* const dmux);
  77. static ParseStatus ParseVP8X(WebPDemuxer* const dmux);
  78. static int IsValidSimpleFormat(const WebPDemuxer* const dmux);
  79. static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
  80. static const ChunkParser kMasterChunks[] = {
  81. { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat },
  82. { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat },
  83. { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat },
  84. { { '0', '0', '0', '0' }, NULL, NULL },
  85. };
  86. //------------------------------------------------------------------------------
  87. int WebPGetDemuxVersion(void) {
  88. return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION;
  89. }
  90. // -----------------------------------------------------------------------------
  91. // MemBuffer
  92. static int RemapMemBuffer(MemBuffer* const mem,
  93. const uint8_t* data, size_t size) {
  94. if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
  95. mem->buf_ = data;
  96. mem->end_ = mem->buf_size_ = size;
  97. return 1;
  98. }
  99. static int InitMemBuffer(MemBuffer* const mem,
  100. const uint8_t* data, size_t size) {
  101. memset(mem, 0, sizeof(*mem));
  102. return RemapMemBuffer(mem, data, size);
  103. }
  104. // Return the remaining data size available in 'mem'.
  105. static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) {
  106. return (mem->end_ - mem->start_);
  107. }
  108. // Return true if 'size' exceeds the end of the RIFF chunk.
  109. static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) {
  110. return (size > mem->riff_end_ - mem->start_);
  111. }
  112. static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) {
  113. mem->start_ += size;
  114. }
  115. static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) {
  116. mem->start_ -= size;
  117. }
  118. static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) {
  119. return mem->buf_ + mem->start_;
  120. }
  121. // Read from 'mem' and skip the read bytes.
  122. static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) {
  123. const uint8_t byte = mem->buf_[mem->start_];
  124. Skip(mem, 1);
  125. return byte;
  126. }
  127. static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) {
  128. const uint8_t* const data = mem->buf_ + mem->start_;
  129. const int val = GetLE16(data);
  130. Skip(mem, 2);
  131. return val;
  132. }
  133. static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) {
  134. const uint8_t* const data = mem->buf_ + mem->start_;
  135. const int val = GetLE24(data);
  136. Skip(mem, 3);
  137. return val;
  138. }
  139. static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) {
  140. const uint8_t* const data = mem->buf_ + mem->start_;
  141. const uint32_t val = GetLE32(data);
  142. Skip(mem, 4);
  143. return val;
  144. }
  145. // -----------------------------------------------------------------------------
  146. // Secondary chunk parsing
  147. static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
  148. *dmux->chunks_tail_ = chunk;
  149. chunk->next_ = NULL;
  150. dmux->chunks_tail_ = &chunk->next_;
  151. }
  152. // Add a frame to the end of the list, ensuring the last frame is complete.
  153. // Returns true on success, false otherwise.
  154. static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
  155. const Frame* const last_frame = *dmux->frames_tail_;
  156. if (last_frame != NULL && !last_frame->complete_) return 0;
  157. *dmux->frames_tail_ = frame;
  158. frame->next_ = NULL;
  159. dmux->frames_tail_ = &frame->next_;
  160. return 1;
  161. }
  162. static void SetFrameInfo(size_t start_offset, size_t size,
  163. int frame_num, int complete,
  164. const WebPBitstreamFeatures* const features,
  165. Frame* const frame) {
  166. frame->img_components_[0].offset_ = start_offset;
  167. frame->img_components_[0].size_ = size;
  168. frame->width_ = features->width;
  169. frame->height_ = features->height;
  170. frame->has_alpha_ |= features->has_alpha;
  171. frame->frame_num_ = frame_num;
  172. frame->complete_ = complete;
  173. }
  174. // Store image bearing chunks to 'frame'.
  175. static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
  176. MemBuffer* const mem, Frame* const frame) {
  177. int alpha_chunks = 0;
  178. int image_chunks = 0;
  179. int done = (MemDataSize(mem) < min_size);
  180. ParseStatus status = PARSE_OK;
  181. if (done) return PARSE_NEED_MORE_DATA;
  182. do {
  183. const size_t chunk_start_offset = mem->start_;
  184. const uint32_t fourcc = ReadLE32(mem);
  185. const uint32_t payload_size = ReadLE32(mem);
  186. const uint32_t payload_size_padded = payload_size + (payload_size & 1);
  187. const size_t payload_available = (payload_size_padded > MemDataSize(mem))
  188. ? MemDataSize(mem) : payload_size_padded;
  189. const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available;
  190. if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  191. if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
  192. if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
  193. switch (fourcc) {
  194. case MKFOURCC('A', 'L', 'P', 'H'):
  195. if (alpha_chunks == 0) {
  196. ++alpha_chunks;
  197. frame->img_components_[1].offset_ = chunk_start_offset;
  198. frame->img_components_[1].size_ = chunk_size;
  199. frame->has_alpha_ = 1;
  200. frame->frame_num_ = frame_num;
  201. Skip(mem, payload_available);
  202. } else {
  203. goto Done;
  204. }
  205. break;
  206. case MKFOURCC('V', 'P', '8', 'L'):
  207. if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha
  208. // fall through
  209. case MKFOURCC('V', 'P', '8', ' '):
  210. if (image_chunks == 0) {
  211. // Extract the bitstream features, tolerating failures when the data
  212. // is incomplete.
  213. WebPBitstreamFeatures features;
  214. const VP8StatusCode vp8_status =
  215. WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size,
  216. &features);
  217. if (status == PARSE_NEED_MORE_DATA &&
  218. vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
  219. return PARSE_NEED_MORE_DATA;
  220. } else if (vp8_status != VP8_STATUS_OK) {
  221. // We have enough data, and yet WebPGetFeatures() failed.
  222. return PARSE_ERROR;
  223. }
  224. ++image_chunks;
  225. SetFrameInfo(chunk_start_offset, chunk_size, frame_num,
  226. status == PARSE_OK, &features, frame);
  227. Skip(mem, payload_available);
  228. } else {
  229. goto Done;
  230. }
  231. break;
  232. Done:
  233. default:
  234. // Restore fourcc/size when moving up one level in parsing.
  235. Rewind(mem, CHUNK_HEADER_SIZE);
  236. done = 1;
  237. break;
  238. }
  239. if (mem->start_ == mem->riff_end_) {
  240. done = 1;
  241. } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
  242. status = PARSE_NEED_MORE_DATA;
  243. }
  244. } while (!done && status == PARSE_OK);
  245. return status;
  246. }
  247. // Creates a new Frame if 'actual_size' is within bounds and 'mem' contains
  248. // enough data ('min_size') to parse the payload.
  249. // Returns PARSE_OK on success with *frame pointing to the new Frame.
  250. // Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
  251. static ParseStatus NewFrame(const MemBuffer* const mem,
  252. uint32_t min_size, uint32_t actual_size,
  253. Frame** frame) {
  254. if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  255. if (actual_size < min_size) return PARSE_ERROR;
  256. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  257. *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame));
  258. return (*frame == NULL) ? PARSE_ERROR : PARSE_OK;
  259. }
  260. // Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
  261. // 'frame_chunk_size' is the previously validated, padded chunk size.
  262. static ParseStatus ParseAnimationFrame(
  263. WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
  264. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  265. const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
  266. int added_frame = 0;
  267. int bits;
  268. MemBuffer* const mem = &dmux->mem_;
  269. Frame* frame;
  270. ParseStatus status =
  271. NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
  272. if (status != PARSE_OK) return status;
  273. frame->x_offset_ = 2 * ReadLE24s(mem);
  274. frame->y_offset_ = 2 * ReadLE24s(mem);
  275. frame->width_ = 1 + ReadLE24s(mem);
  276. frame->height_ = 1 + ReadLE24s(mem);
  277. frame->duration_ = ReadLE24s(mem);
  278. bits = ReadByte(mem);
  279. frame->dispose_method_ =
  280. (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
  281. frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
  282. if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
  283. WebPSafeFree(frame);
  284. return PARSE_ERROR;
  285. }
  286. // Store a frame only if the animation flag is set there is some data for
  287. // this frame is available.
  288. status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
  289. if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
  290. added_frame = AddFrame(dmux, frame);
  291. if (added_frame) {
  292. ++dmux->num_frames_;
  293. } else {
  294. status = PARSE_ERROR;
  295. }
  296. }
  297. if (!added_frame) WebPSafeFree(frame);
  298. return status;
  299. }
  300. // General chunk storage, starting with the header at 'start_offset', allowing
  301. // the user to request the payload via a fourcc string. 'size' includes the
  302. // header and the unpadded payload size.
  303. // Returns true on success, false otherwise.
  304. static int StoreChunk(WebPDemuxer* const dmux,
  305. size_t start_offset, uint32_t size) {
  306. Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
  307. if (chunk == NULL) return 0;
  308. chunk->data_.offset_ = start_offset;
  309. chunk->data_.size_ = size;
  310. AddChunk(dmux, chunk);
  311. return 1;
  312. }
  313. // -----------------------------------------------------------------------------
  314. // Primary chunk parsing
  315. static ParseStatus ReadHeader(MemBuffer* const mem) {
  316. const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
  317. uint32_t riff_size;
  318. // Basic file level validation.
  319. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  320. if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) ||
  321. memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) {
  322. return PARSE_ERROR;
  323. }
  324. riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE);
  325. if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR;
  326. if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  327. // There's no point in reading past the end of the RIFF chunk
  328. mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE;
  329. if (mem->buf_size_ > mem->riff_end_) {
  330. mem->buf_size_ = mem->end_ = mem->riff_end_;
  331. }
  332. Skip(mem, RIFF_HEADER_SIZE);
  333. return PARSE_OK;
  334. }
  335. static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
  336. const size_t min_size = CHUNK_HEADER_SIZE;
  337. MemBuffer* const mem = &dmux->mem_;
  338. Frame* frame;
  339. ParseStatus status;
  340. int image_added = 0;
  341. if (dmux->frames_ != NULL) return PARSE_ERROR;
  342. if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
  343. if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
  344. frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
  345. if (frame == NULL) return PARSE_ERROR;
  346. // For the single image case we allow parsing of a partial frame, but we need
  347. // at least CHUNK_HEADER_SIZE for parsing.
  348. status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame);
  349. if (status != PARSE_ERROR) {
  350. const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
  351. // Clear any alpha when the alpha flag is missing.
  352. if (!has_alpha && frame->img_components_[1].size_ > 0) {
  353. frame->img_components_[1].offset_ = 0;
  354. frame->img_components_[1].size_ = 0;
  355. frame->has_alpha_ = 0;
  356. }
  357. // Use the frame width/height as the canvas values for non-vp8x files.
  358. // Also, set ALPHA_FLAG if this is a lossless image with alpha.
  359. if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
  360. dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
  361. dmux->canvas_width_ = frame->width_;
  362. dmux->canvas_height_ = frame->height_;
  363. dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
  364. }
  365. if (!AddFrame(dmux, frame)) {
  366. status = PARSE_ERROR; // last frame was left incomplete
  367. } else {
  368. image_added = 1;
  369. dmux->num_frames_ = 1;
  370. }
  371. }
  372. if (!image_added) WebPSafeFree(frame);
  373. return status;
  374. }
  375. static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) {
  376. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  377. MemBuffer* const mem = &dmux->mem_;
  378. int anim_chunks = 0;
  379. ParseStatus status = PARSE_OK;
  380. do {
  381. int store_chunk = 1;
  382. const size_t chunk_start_offset = mem->start_;
  383. const uint32_t fourcc = ReadLE32(mem);
  384. const uint32_t chunk_size = ReadLE32(mem);
  385. const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1);
  386. if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  387. if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR;
  388. switch (fourcc) {
  389. case MKFOURCC('V', 'P', '8', 'X'): {
  390. return PARSE_ERROR;
  391. }
  392. case MKFOURCC('A', 'L', 'P', 'H'):
  393. case MKFOURCC('V', 'P', '8', ' '):
  394. case MKFOURCC('V', 'P', '8', 'L'): {
  395. // check that this isn't an animation (all frames should be in an ANMF).
  396. if (anim_chunks > 0 || is_animation) return PARSE_ERROR;
  397. Rewind(mem, CHUNK_HEADER_SIZE);
  398. status = ParseSingleImage(dmux);
  399. break;
  400. }
  401. case MKFOURCC('A', 'N', 'I', 'M'): {
  402. if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR;
  403. if (MemDataSize(mem) < chunk_size_padded) {
  404. status = PARSE_NEED_MORE_DATA;
  405. } else if (anim_chunks == 0) {
  406. ++anim_chunks;
  407. dmux->bgcolor_ = ReadLE32(mem);
  408. dmux->loop_count_ = ReadLE16s(mem);
  409. Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE);
  410. } else {
  411. store_chunk = 0;
  412. goto Skip;
  413. }
  414. break;
  415. }
  416. case MKFOURCC('A', 'N', 'M', 'F'): {
  417. if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames.
  418. status = ParseAnimationFrame(dmux, chunk_size_padded);
  419. break;
  420. }
  421. case MKFOURCC('I', 'C', 'C', 'P'): {
  422. store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
  423. goto Skip;
  424. }
  425. case MKFOURCC('E', 'X', 'I', 'F'): {
  426. store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG);
  427. goto Skip;
  428. }
  429. case MKFOURCC('X', 'M', 'P', ' '): {
  430. store_chunk = !!(dmux->feature_flags_ & XMP_FLAG);
  431. goto Skip;
  432. }
  433. Skip:
  434. default: {
  435. if (chunk_size_padded <= MemDataSize(mem)) {
  436. if (store_chunk) {
  437. // Store only the chunk header and unpadded size as only the payload
  438. // will be returned to the user.
  439. if (!StoreChunk(dmux, chunk_start_offset,
  440. CHUNK_HEADER_SIZE + chunk_size)) {
  441. return PARSE_ERROR;
  442. }
  443. }
  444. Skip(mem, chunk_size_padded);
  445. } else {
  446. status = PARSE_NEED_MORE_DATA;
  447. }
  448. }
  449. }
  450. if (mem->start_ == mem->riff_end_) {
  451. break;
  452. } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
  453. status = PARSE_NEED_MORE_DATA;
  454. }
  455. } while (status == PARSE_OK);
  456. return status;
  457. }
  458. static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
  459. MemBuffer* const mem = &dmux->mem_;
  460. uint32_t vp8x_size;
  461. if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
  462. dmux->is_ext_format_ = 1;
  463. Skip(mem, TAG_SIZE); // VP8X
  464. vp8x_size = ReadLE32(mem);
  465. if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
  466. if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR;
  467. vp8x_size += vp8x_size & 1;
  468. if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR;
  469. if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA;
  470. dmux->feature_flags_ = ReadByte(mem);
  471. Skip(mem, 3); // Reserved.
  472. dmux->canvas_width_ = 1 + ReadLE24s(mem);
  473. dmux->canvas_height_ = 1 + ReadLE24s(mem);
  474. if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) {
  475. return PARSE_ERROR; // image final dimension is too large
  476. }
  477. Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data.
  478. dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
  479. if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR;
  480. if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
  481. return ParseVP8XChunks(dmux);
  482. }
  483. // -----------------------------------------------------------------------------
  484. // Format validation
  485. static int IsValidSimpleFormat(const WebPDemuxer* const dmux) {
  486. const Frame* const frame = dmux->frames_;
  487. if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
  488. if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
  489. if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0;
  490. if (frame->width_ <= 0 || frame->height_ <= 0) return 0;
  491. return 1;
  492. }
  493. // If 'exact' is true, check that the image resolution matches the canvas.
  494. // If 'exact' is false, check that the x/y offsets do not exceed the canvas.
  495. static int CheckFrameBounds(const Frame* const frame, int exact,
  496. int canvas_width, int canvas_height) {
  497. if (exact) {
  498. if (frame->x_offset_ != 0 || frame->y_offset_ != 0) {
  499. return 0;
  500. }
  501. if (frame->width_ != canvas_width || frame->height_ != canvas_height) {
  502. return 0;
  503. }
  504. } else {
  505. if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0;
  506. if (frame->width_ + frame->x_offset_ > canvas_width) return 0;
  507. if (frame->height_ + frame->y_offset_ > canvas_height) return 0;
  508. }
  509. return 1;
  510. }
  511. static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
  512. const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
  513. const Frame* f = dmux->frames_;
  514. if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
  515. if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
  516. if (dmux->loop_count_ < 0) return 0;
  517. if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0;
  518. if (dmux->feature_flags_ & ~ALL_VALID_FLAGS) return 0; // invalid bitstream
  519. while (f != NULL) {
  520. const int cur_frame_set = f->frame_num_;
  521. int frame_count = 0;
  522. // Check frame properties.
  523. for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) {
  524. const ChunkData* const image = f->img_components_;
  525. const ChunkData* const alpha = f->img_components_ + 1;
  526. if (!is_animation && f->frame_num_ > 1) return 0;
  527. if (f->complete_) {
  528. if (alpha->size_ == 0 && image->size_ == 0) return 0;
  529. // Ensure alpha precedes image bitstream.
  530. if (alpha->size_ > 0 && alpha->offset_ > image->offset_) {
  531. return 0;
  532. }
  533. if (f->width_ <= 0 || f->height_ <= 0) return 0;
  534. } else {
  535. // There shouldn't be a partial frame in a complete file.
  536. if (dmux->state_ == WEBP_DEMUX_DONE) return 0;
  537. // Ensure alpha precedes image bitstream.
  538. if (alpha->size_ > 0 && image->size_ > 0 &&
  539. alpha->offset_ > image->offset_) {
  540. return 0;
  541. }
  542. // There shouldn't be any frames after an incomplete one.
  543. if (f->next_ != NULL) return 0;
  544. }
  545. if (f->width_ > 0 && f->height_ > 0 &&
  546. !CheckFrameBounds(f, !is_animation,
  547. dmux->canvas_width_, dmux->canvas_height_)) {
  548. return 0;
  549. }
  550. ++frame_count;
  551. }
  552. }
  553. return 1;
  554. }
  555. // -----------------------------------------------------------------------------
  556. // WebPDemuxer object
  557. static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
  558. dmux->state_ = WEBP_DEMUX_PARSING_HEADER;
  559. dmux->loop_count_ = 1;
  560. dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
  561. dmux->canvas_width_ = -1;
  562. dmux->canvas_height_ = -1;
  563. dmux->frames_tail_ = &dmux->frames_;
  564. dmux->chunks_tail_ = &dmux->chunks_;
  565. dmux->mem_ = *mem;
  566. }
  567. static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem,
  568. WebPDemuxer** demuxer) {
  569. WebPBitstreamFeatures features;
  570. const VP8StatusCode status =
  571. WebPGetFeatures(mem->buf_, mem->buf_size_, &features);
  572. *demuxer = NULL;
  573. if (status != VP8_STATUS_OK) {
  574. return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA
  575. : PARSE_ERROR;
  576. }
  577. {
  578. WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
  579. Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
  580. if (dmux == NULL || frame == NULL) goto Error;
  581. InitDemux(dmux, mem);
  582. SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features,
  583. frame);
  584. if (!AddFrame(dmux, frame)) goto Error;
  585. dmux->state_ = WEBP_DEMUX_DONE;
  586. dmux->canvas_width_ = frame->width_;
  587. dmux->canvas_height_ = frame->height_;
  588. dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
  589. dmux->num_frames_ = 1;
  590. assert(IsValidSimpleFormat(dmux));
  591. *demuxer = dmux;
  592. return PARSE_OK;
  593. Error:
  594. WebPSafeFree(dmux);
  595. WebPSafeFree(frame);
  596. return PARSE_ERROR;
  597. }
  598. }
  599. WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
  600. WebPDemuxState* state, int version) {
  601. const ChunkParser* parser;
  602. int partial;
  603. ParseStatus status = PARSE_ERROR;
  604. MemBuffer mem;
  605. WebPDemuxer* dmux;
  606. if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR;
  607. if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL;
  608. if (data == NULL || data->bytes == NULL || data->size == 0) return NULL;
  609. if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
  610. status = ReadHeader(&mem);
  611. if (status != PARSE_OK) {
  612. // If parsing of the webp file header fails attempt to handle a raw
  613. // VP8/VP8L frame. Note 'allow_partial' is ignored in this case.
  614. if (status == PARSE_ERROR) {
  615. status = CreateRawImageDemuxer(&mem, &dmux);
  616. if (status == PARSE_OK) {
  617. if (state != NULL) *state = WEBP_DEMUX_DONE;
  618. return dmux;
  619. }
  620. }
  621. if (state != NULL) {
  622. *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
  623. : WEBP_DEMUX_PARSE_ERROR;
  624. }
  625. return NULL;
  626. }
  627. partial = (mem.buf_size_ < mem.riff_end_);
  628. if (!allow_partial && partial) return NULL;
  629. dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
  630. if (dmux == NULL) return NULL;
  631. InitDemux(dmux, &mem);
  632. status = PARSE_ERROR;
  633. for (parser = kMasterChunks; parser->parse != NULL; ++parser) {
  634. if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) {
  635. status = parser->parse(dmux);
  636. if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE;
  637. if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR;
  638. if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR;
  639. if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR;
  640. break;
  641. }
  642. }
  643. if (state != NULL) *state = dmux->state_;
  644. if (status == PARSE_ERROR) {
  645. WebPDemuxDelete(dmux);
  646. return NULL;
  647. }
  648. return dmux;
  649. }
  650. void WebPDemuxDelete(WebPDemuxer* dmux) {
  651. Chunk* c;
  652. Frame* f;
  653. if (dmux == NULL) return;
  654. for (f = dmux->frames_; f != NULL;) {
  655. Frame* const cur_frame = f;
  656. f = f->next_;
  657. WebPSafeFree(cur_frame);
  658. }
  659. for (c = dmux->chunks_; c != NULL;) {
  660. Chunk* const cur_chunk = c;
  661. c = c->next_;
  662. WebPSafeFree(cur_chunk);
  663. }
  664. WebPSafeFree(dmux);
  665. }
  666. // -----------------------------------------------------------------------------
  667. uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) {
  668. if (dmux == NULL) return 0;
  669. switch (feature) {
  670. case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_;
  671. case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_;
  672. case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_;
  673. case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_;
  674. case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_;
  675. case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_;
  676. }
  677. return 0;
  678. }
  679. // -----------------------------------------------------------------------------
  680. // Frame iteration
  681. static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) {
  682. const Frame* f;
  683. for (f = dmux->frames_; f != NULL; f = f->next_) {
  684. if (frame_num == f->frame_num_) break;
  685. }
  686. return f;
  687. }
  688. static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
  689. const Frame* const frame,
  690. size_t* const data_size) {
  691. *data_size = 0;
  692. if (frame != NULL) {
  693. const ChunkData* const image = frame->img_components_;
  694. const ChunkData* const alpha = frame->img_components_ + 1;
  695. size_t start_offset = image->offset_;
  696. *data_size = image->size_;
  697. // if alpha exists it precedes image, update the size allowing for
  698. // intervening chunks.
  699. if (alpha->size_ > 0) {
  700. const size_t inter_size = (image->offset_ > 0)
  701. ? image->offset_ - (alpha->offset_ + alpha->size_)
  702. : 0;
  703. start_offset = alpha->offset_;
  704. *data_size += alpha->size_ + inter_size;
  705. }
  706. return mem_buf + start_offset;
  707. }
  708. return NULL;
  709. }
  710. // Create a whole 'frame' from VP8 (+ alpha) or lossless.
  711. static int SynthesizeFrame(const WebPDemuxer* const dmux,
  712. const Frame* const frame,
  713. WebPIterator* const iter) {
  714. const uint8_t* const mem_buf = dmux->mem_.buf_;
  715. size_t payload_size = 0;
  716. const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size);
  717. if (payload == NULL) return 0;
  718. assert(frame != NULL);
  719. iter->frame_num = frame->frame_num_;
  720. iter->num_frames = dmux->num_frames_;
  721. iter->x_offset = frame->x_offset_;
  722. iter->y_offset = frame->y_offset_;
  723. iter->width = frame->width_;
  724. iter->height = frame->height_;
  725. iter->has_alpha = frame->has_alpha_;
  726. iter->duration = frame->duration_;
  727. iter->dispose_method = frame->dispose_method_;
  728. iter->blend_method = frame->blend_method_;
  729. iter->complete = frame->complete_;
  730. iter->fragment.bytes = payload;
  731. iter->fragment.size = payload_size;
  732. return 1;
  733. }
  734. static int SetFrame(int frame_num, WebPIterator* const iter) {
  735. const Frame* frame;
  736. const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
  737. if (dmux == NULL || frame_num < 0) return 0;
  738. if (frame_num > dmux->num_frames_) return 0;
  739. if (frame_num == 0) frame_num = dmux->num_frames_;
  740. frame = GetFrame(dmux, frame_num);
  741. if (frame == NULL) return 0;
  742. return SynthesizeFrame(dmux, frame, iter);
  743. }
  744. int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) {
  745. if (iter == NULL) return 0;
  746. memset(iter, 0, sizeof(*iter));
  747. iter->private_ = (void*)dmux;
  748. return SetFrame(frame, iter);
  749. }
  750. int WebPDemuxNextFrame(WebPIterator* iter) {
  751. if (iter == NULL) return 0;
  752. return SetFrame(iter->frame_num + 1, iter);
  753. }
  754. int WebPDemuxPrevFrame(WebPIterator* iter) {
  755. if (iter == NULL) return 0;
  756. if (iter->frame_num <= 1) return 0;
  757. return SetFrame(iter->frame_num - 1, iter);
  758. }
  759. void WebPDemuxReleaseIterator(WebPIterator* iter) {
  760. (void)iter;
  761. }
  762. // -----------------------------------------------------------------------------
  763. // Chunk iteration
  764. static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) {
  765. const uint8_t* const mem_buf = dmux->mem_.buf_;
  766. const Chunk* c;
  767. int count = 0;
  768. for (c = dmux->chunks_; c != NULL; c = c->next_) {
  769. const uint8_t* const header = mem_buf + c->data_.offset_;
  770. if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
  771. }
  772. return count;
  773. }
  774. static const Chunk* GetChunk(const WebPDemuxer* const dmux,
  775. const char fourcc[4], int chunk_num) {
  776. const uint8_t* const mem_buf = dmux->mem_.buf_;
  777. const Chunk* c;
  778. int count = 0;
  779. for (c = dmux->chunks_; c != NULL; c = c->next_) {
  780. const uint8_t* const header = mem_buf + c->data_.offset_;
  781. if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
  782. if (count == chunk_num) break;
  783. }
  784. return c;
  785. }
  786. static int SetChunk(const char fourcc[4], int chunk_num,
  787. WebPChunkIterator* const iter) {
  788. const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
  789. int count;
  790. if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0;
  791. count = ChunkCount(dmux, fourcc);
  792. if (count == 0) return 0;
  793. if (chunk_num == 0) chunk_num = count;
  794. if (chunk_num <= count) {
  795. const uint8_t* const mem_buf = dmux->mem_.buf_;
  796. const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num);
  797. iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE;
  798. iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE;
  799. iter->num_chunks = count;
  800. iter->chunk_num = chunk_num;
  801. return 1;
  802. }
  803. return 0;
  804. }
  805. int WebPDemuxGetChunk(const WebPDemuxer* dmux,
  806. const char fourcc[4], int chunk_num,
  807. WebPChunkIterator* iter) {
  808. if (iter == NULL) return 0;
  809. memset(iter, 0, sizeof(*iter));
  810. iter->private_ = (void*)dmux;
  811. return SetChunk(fourcc, chunk_num, iter);
  812. }
  813. int WebPDemuxNextChunk(WebPChunkIterator* iter) {
  814. if (iter != NULL) {
  815. const char* const fourcc =
  816. (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
  817. return SetChunk(fourcc, iter->chunk_num + 1, iter);
  818. }
  819. return 0;
  820. }
  821. int WebPDemuxPrevChunk(WebPChunkIterator* iter) {
  822. if (iter != NULL && iter->chunk_num > 1) {
  823. const char* const fourcc =
  824. (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
  825. return SetChunk(fourcc, iter->chunk_num - 1, iter);
  826. }
  827. return 0;
  828. }
  829. void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) {
  830. (void)iter;
  831. }