| 834 | |
| 835 | #define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */ |
| 836 | static int recode_subtitle(AVCodecContext *avctx, const AVPacket **outpkt, |
| 837 | const AVPacket *inpkt, AVPacket *buf_pkt) |
| 838 | { |
| 839 | #if CONFIG_ICONV |
| 840 | iconv_t cd = (iconv_t)-1; |
| 841 | int ret = 0; |
| 842 | char *inb, *outb; |
| 843 | size_t inl, outl; |
| 844 | #endif |
| 845 | |
| 846 | if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER || inpkt->size == 0) { |
| 847 | *outpkt = inpkt; |
| 848 | return 0; |
| 849 | } |
| 850 | |
| 851 | #if CONFIG_ICONV |
| 852 | inb = inpkt->data; |
| 853 | inl = inpkt->size; |
| 854 | |
| 855 | if (inl >= INT_MAX / UTF8_MAX_BYTES - AV_INPUT_BUFFER_PADDING_SIZE) { |
| 856 | av_log(avctx, AV_LOG_ERROR, "Subtitles packet is too big for recoding\n"); |
| 857 | return AVERROR(ERANGE); |
| 858 | } |
| 859 | |
| 860 | cd = iconv_open("UTF-8", avctx->sub_charenc); |
| 861 | av_assert0(cd != (iconv_t)-1); |
| 862 | |
| 863 | ret = av_new_packet(buf_pkt, inl * UTF8_MAX_BYTES); |
| 864 | if (ret < 0) |
| 865 | goto end; |
| 866 | ret = av_packet_copy_props(buf_pkt, inpkt); |
| 867 | if (ret < 0) |
| 868 | goto end; |
| 869 | outb = buf_pkt->data; |
| 870 | outl = buf_pkt->size; |
| 871 | |
| 872 | if (iconv(cd, &inb, &inl, &outb, &outl) == (size_t)-1 || |
| 873 | iconv(cd, NULL, NULL, &outb, &outl) == (size_t)-1 || |
| 874 | outl >= buf_pkt->size || inl != 0) { |
| 875 | ret = FFMIN(AVERROR(errno), -1); |
| 876 | av_log(avctx, AV_LOG_ERROR, "Unable to recode subtitle event \"%s\" " |
| 877 | "from %s to UTF-8\n", inpkt->data, avctx->sub_charenc); |
| 878 | goto end; |
| 879 | } |
| 880 | buf_pkt->size -= outl; |
| 881 | memset(buf_pkt->data + buf_pkt->size, 0, outl); |
| 882 | *outpkt = buf_pkt; |
| 883 | |
| 884 | ret = 0; |
| 885 | end: |
| 886 | if (ret < 0) |
| 887 | av_packet_unref(buf_pkt); |
| 888 | if (cd != (iconv_t)-1) |
| 889 | iconv_close(cd); |
| 890 | return ret; |
| 891 | #else |
| 892 | av_log(avctx, AV_LOG_ERROR, "requesting subtitles recoding without iconv"); |
| 893 | return AVERROR(EINVAL); |
no test coverage detected