| 750 | } |
| 751 | |
| 752 | int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode) |
| 753 | { |
| 754 | AVBufferRef *buf = NULL; |
| 755 | size_t size, headsize = 8; |
| 756 | PutByteContext pb; |
| 757 | int ret = 0, off = 0, next; |
| 758 | AVExifMetadata *ifd_new = NULL; |
| 759 | AVExifMetadata extra_ifds[16] = { 0 }; |
| 760 | |
| 761 | int le = 1; |
| 762 | |
| 763 | if (*buffer) { |
| 764 | ret = AVERROR(EINVAL); |
| 765 | goto end; |
| 766 | } |
| 767 | |
| 768 | size = exif_get_ifd_size(ifd); |
| 769 | switch (header_mode) { |
| 770 | case AV_EXIF_EXIF00: |
| 771 | off = 6; |
| 772 | break; |
| 773 | case AV_EXIF_T_OFF: |
| 774 | off = 4; |
| 775 | break; |
| 776 | case AV_EXIF_ASSUME_BE: |
| 777 | le = 0; |
| 778 | headsize = 0; |
| 779 | break; |
| 780 | case AV_EXIF_ASSUME_LE: |
| 781 | le = 1; |
| 782 | headsize = 0; |
| 783 | break; |
| 784 | } |
| 785 | |
| 786 | ret = av_buffer_realloc(&buf, size + off + headsize); |
| 787 | if (ret < 0) |
| 788 | goto end; |
| 789 | |
| 790 | if (header_mode == AV_EXIF_EXIF00) { |
| 791 | AV_WL32(buf->data, MKTAG('E','x','i','f')); |
| 792 | AV_WN16(buf->data + 4, 0); |
| 793 | } else if (header_mode == AV_EXIF_T_OFF) { |
| 794 | AV_WN32(buf->data, 0); |
| 795 | } |
| 796 | |
| 797 | bytestream2_init_writer(&pb, buf->data + off, buf->size - off); |
| 798 | |
| 799 | if (header_mode != AV_EXIF_ASSUME_BE && header_mode != AV_EXIF_ASSUME_LE) { |
| 800 | /* these constants are be32 in both cases */ |
| 801 | /* le == 1 always in this case */ |
| 802 | bytestream2_put_be32(&pb, EXIF_II_LONG); |
| 803 | tput32(&pb, le, 8); |
| 804 | } |
| 805 | |
| 806 | int extras = 0; |
| 807 | for (int i = 0; i < FF_ARRAY_ELEMS(extra_ifds); i++) { |
| 808 | AVExifEntry *extra_entry = NULL; |
| 809 | uint16_t extra_tag = 0xFFFCu - i; |
no test coverage detected