| 2395 | } |
| 2396 | |
| 2397 | static int exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd, AVBufferRef **pbuf) |
| 2398 | { |
| 2399 | const AVExifEntry *orient = NULL; |
| 2400 | AVExifMetadata *cloned = NULL; |
| 2401 | int ret; |
| 2402 | |
| 2403 | for (size_t i = 0; i < ifd->count; i++) { |
| 2404 | const AVExifEntry *entry = &ifd->entries[i]; |
| 2405 | if (entry->id == av_exif_get_tag_id("Orientation") && |
| 2406 | entry->count > 0 && entry->type == AV_TIFF_SHORT) { |
| 2407 | orient = entry; |
| 2408 | break; |
| 2409 | } |
| 2410 | } |
| 2411 | |
| 2412 | if (orient) { |
| 2413 | av_log(avctx, AV_LOG_DEBUG, "found EXIF orientation: %" PRIu64 "\n", orient->value.uint[0]); |
| 2414 | ret = attach_displaymatrix(avctx, frame, orient->value.uint[0]); |
| 2415 | if (ret < 0) { |
| 2416 | av_log(avctx, AV_LOG_WARNING, "unable to attach displaymatrix from EXIF\n"); |
| 2417 | } else { |
| 2418 | cloned = av_exif_clone_ifd(ifd); |
| 2419 | if (!cloned) { |
| 2420 | ret = AVERROR(ENOMEM); |
| 2421 | goto end; |
| 2422 | } |
| 2423 | av_exif_remove_entry(avctx, cloned, orient->id, 0); |
| 2424 | ifd = cloned; |
| 2425 | } |
| 2426 | } |
| 2427 | |
| 2428 | ret = av_exif_ifd_to_dict(avctx, ifd, &frame->metadata); |
| 2429 | if (ret < 0) |
| 2430 | goto end; |
| 2431 | |
| 2432 | if (cloned || !*pbuf) { |
| 2433 | av_buffer_unref(pbuf); |
| 2434 | ret = av_exif_write(avctx, ifd, pbuf, AV_EXIF_TIFF_HEADER); |
| 2435 | if (ret < 0) |
| 2436 | goto end; |
| 2437 | } |
| 2438 | |
| 2439 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_EXIF, pbuf); |
| 2440 | if (ret < 0) |
| 2441 | goto end; |
| 2442 | |
| 2443 | ret = 0; |
| 2444 | |
| 2445 | end: |
| 2446 | av_buffer_unref(pbuf); |
| 2447 | av_exif_free(cloned); |
| 2448 | av_free(cloned); |
| 2449 | return ret; |
| 2450 | } |
| 2451 | |
| 2452 | int ff_decode_exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd) |
| 2453 | { |
no test coverage detected