OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/jpeg_parser.h" | 5 #include "media/filters/jpeg_parser.h" |
6 | 6 |
7 #include "base/big_endian.h" | 7 #include "base/big_endian.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 | 9 |
10 using base::BigEndianReader; | 10 using base::BigEndianReader; |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 return false; | 262 return false; |
263 } | 263 } |
264 if (point_transform != 0) { | 264 if (point_transform != 0) { |
265 DLOG(ERROR) << "Point transform should be 0 for baseline mode"; | 265 DLOG(ERROR) << "Point transform should be 0 for baseline mode"; |
266 return false; | 266 return false; |
267 } | 267 } |
268 | 268 |
269 return true; | 269 return true; |
270 } | 270 } |
271 | 271 |
| 272 // |eoi_ptr| will point to the end of image (after EOI marker) after search |
| 273 // succeeds. Returns true on EOI marker found, or false. |
| 274 static bool SearchEOI(const char* buffer, size_t length, const char** eoi_ptr) { |
| 275 DCHECK(buffer); |
| 276 DCHECK(eoi_ptr); |
| 277 BigEndianReader reader(buffer, length); |
| 278 uint8_t marker2; |
| 279 |
| 280 while (reader.remaining() > 0) { |
| 281 const char* marker1_ptr = static_cast<const char*>( |
| 282 memchr(reader.ptr(), JPEG_MARKER_PREFIX, reader.remaining())); |
| 283 if (!marker1_ptr) |
| 284 return false; |
| 285 reader.Skip(marker1_ptr - reader.ptr() + 1); |
| 286 |
| 287 do { |
| 288 READ_U8_OR_RETURN_FALSE(&marker2); |
| 289 } while (marker2 == JPEG_MARKER_PREFIX); // skip fill bytes |
| 290 |
| 291 switch (marker2) { |
| 292 // Compressed data escape. |
| 293 case 0x00: |
| 294 break; |
| 295 // Restart |
| 296 case JPEG_RST0: |
| 297 case JPEG_RST1: |
| 298 case JPEG_RST2: |
| 299 case JPEG_RST3: |
| 300 case JPEG_RST4: |
| 301 case JPEG_RST5: |
| 302 case JPEG_RST6: |
| 303 case JPEG_RST7: |
| 304 break; |
| 305 case JPEG_EOI: |
| 306 *eoi_ptr = reader.ptr(); |
| 307 return true; |
| 308 default: |
| 309 // Skip for other markers. |
| 310 uint16_t size; |
| 311 READ_U16_OR_RETURN_FALSE(&size); |
| 312 if (size < sizeof(size)) { |
| 313 DLOG(ERROR) << "Ill-formed JPEG. Segment size (" << size |
| 314 << ") is smaller than size field (" << sizeof(size) |
| 315 << ")"; |
| 316 return false; |
| 317 } |
| 318 size -= sizeof(size); |
| 319 |
| 320 if (!reader.Skip(size)) { |
| 321 DLOG(ERROR) << "Ill-formed JPEG. Remaining size (" |
| 322 << reader.remaining() |
| 323 << ") is smaller than header specified (" << size << ")"; |
| 324 return false; |
| 325 } |
| 326 break; |
| 327 } |
| 328 } |
| 329 return false; |
| 330 } |
| 331 |
272 // |result| is already initialized to 0 in ParseJpegPicture. | 332 // |result| is already initialized to 0 in ParseJpegPicture. |
273 static bool ParseSOI(const char* buffer, | 333 static bool ParseSOI(const char* buffer, |
274 size_t length, | 334 size_t length, |
275 JpegParseResult* result) { | 335 JpegParseResult* result) { |
276 // Spec B.2.1 High-level syntax | 336 // Spec B.2.1 High-level syntax |
277 DCHECK(buffer); | 337 DCHECK(buffer); |
278 DCHECK(result); | 338 DCHECK(result); |
279 BigEndianReader reader(buffer, length); | 339 BigEndianReader reader(buffer, length); |
280 uint8_t marker1; | 340 uint8_t marker1; |
281 uint8_t marker2; | 341 uint8_t marker2; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 } | 425 } |
366 | 426 |
367 if (!has_marker_dqt) { | 427 if (!has_marker_dqt) { |
368 DLOG(ERROR) << "No DQT marker found"; | 428 DLOG(ERROR) << "No DQT marker found"; |
369 return false; | 429 return false; |
370 } | 430 } |
371 | 431 |
372 // Scan data follows scan header immediately. | 432 // Scan data follows scan header immediately. |
373 result->data = reader.ptr(); | 433 result->data = reader.ptr(); |
374 result->data_size = reader.remaining(); | 434 result->data_size = reader.remaining(); |
| 435 const size_t kSoiSize = 2; |
| 436 result->image_size = length + kSoiSize; |
375 | 437 |
376 return true; | 438 return true; |
377 } | 439 } |
378 | 440 |
379 bool ParseJpegPicture(const uint8_t* buffer, | 441 bool ParseJpegPicture(const uint8_t* buffer, |
380 size_t length, | 442 size_t length, |
381 JpegParseResult* result) { | 443 JpegParseResult* result) { |
382 DCHECK(buffer); | 444 DCHECK(buffer); |
383 DCHECK(result); | 445 DCHECK(result); |
384 BigEndianReader reader(reinterpret_cast<const char*>(buffer), length); | 446 BigEndianReader reader(reinterpret_cast<const char*>(buffer), length); |
385 memset(result, 0, sizeof(JpegParseResult)); | 447 memset(result, 0, sizeof(JpegParseResult)); |
386 | 448 |
387 uint8_t marker1, marker2; | 449 uint8_t marker1, marker2; |
388 READ_U8_OR_RETURN_FALSE(&marker1); | 450 READ_U8_OR_RETURN_FALSE(&marker1); |
389 READ_U8_OR_RETURN_FALSE(&marker2); | 451 READ_U8_OR_RETURN_FALSE(&marker2); |
390 if (marker1 != JPEG_MARKER_PREFIX || marker2 != JPEG_SOI) { | 452 if (marker1 != JPEG_MARKER_PREFIX || marker2 != JPEG_SOI) { |
391 DLOG(ERROR) << "Not a JPEG"; | 453 DLOG(ERROR) << "Not a JPEG"; |
392 return false; | 454 return false; |
393 } | 455 } |
394 | 456 |
395 return ParseSOI(reader.ptr(), reader.remaining(), result); | 457 return ParseSOI(reader.ptr(), reader.remaining(), result); |
396 } | 458 } |
397 | 459 |
| 460 bool ParseJpegStream(const uint8_t* buffer, |
| 461 size_t length, |
| 462 JpegParseResult* result) { |
| 463 DCHECK(buffer); |
| 464 DCHECK(result); |
| 465 if (!ParseJpegPicture(buffer, length, result)) |
| 466 return false; |
| 467 |
| 468 BigEndianReader reader( |
| 469 reinterpret_cast<const char*>(result->data), result->data_size); |
| 470 const char* eoi_ptr = nullptr; |
| 471 if (!SearchEOI(reader.ptr(), reader.remaining(), &eoi_ptr)) { |
| 472 DLOG(ERROR) << "SearchEOI failed"; |
| 473 return false; |
| 474 } |
| 475 DCHECK(eoi_ptr); |
| 476 result->data_size = eoi_ptr - result->data; |
| 477 result->image_size = eoi_ptr - reinterpret_cast<const char*>(buffer); |
| 478 return true; |
| 479 } |
| 480 |
398 } // namespace media | 481 } // namespace media |
OLD | NEW |