| @@ -1732,6 +1732,109 @@ void av_opt_freep_ranges(AVOptionRanges **rangesp) · 1731 unmodified lines |
| 1732 | av_freep(rangesp); | 1732 | av_freep(rangesp); |
| 1733 | } | 1733 | } |
| 1734 | | 1734 | |
| | 1735 | int av_opt_is_set_to_default(void *obj, const AVOption *o) |
| | 1736 | { |
| | 1737 | int64_t i64; |
| | 1738 | double d, d2; |
| | 1739 | float f; |
| | 1740 | AVRational q; |
| | 1741 | int ret, w, h; |
| | 1742 | char *str; |
| | 1743 | void *dst; |
| | 1744 | |
| | 1745 | if (!o || !obj) |
| | 1746 | return AVERROR(EINVAL); |
| | 1747 | |
| | 1748 | dst = ((uint8_t*)obj) + o->offset; |
| | 1749 | |
| | 1750 | switch (o->type) { |
| | 1751 | case AV_OPT_TYPE_CONST: |
| | 1752 | return 1; |
| | 1753 | case AV_OPT_TYPE_FLAGS: |
| | 1754 | case AV_OPT_TYPE_PIXEL_FMT: |
| | 1755 | case AV_OPT_TYPE_SAMPLE_FMT: |
| | 1756 | case AV_OPT_TYPE_INT: |
| | 1757 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
| | 1758 | case AV_OPT_TYPE_DURATION: |
| | 1759 | case AV_OPT_TYPE_INT64: |
| | 1760 | read_number(o, dst, NULL, NULL, &i64); |
| | 1761 | return o->default_val.i64 == i64; |
| | 1762 | case AV_OPT_TYPE_STRING: |
| | 1763 | str = *(char **)dst; |
| | 1764 | if (str == o->default_val.str) //2 NULLs |
| | 1765 | return 1; |
| | 1766 | if (!str || !o->default_val.str) //1 NULL |
| | 1767 | return 0; |
| | 1768 | return !strcmp(str, o->default_val.str); |
| | 1769 | case AV_OPT_TYPE_DOUBLE: |
| | 1770 | read_number(o, dst, &d, NULL, NULL); |
| | 1771 | return o->default_val.dbl == d; |
| | 1772 | case AV_OPT_TYPE_FLOAT: |
| | 1773 | read_number(o, dst, &d, NULL, NULL); |
| | 1774 | f = o->default_val.dbl; |
| | 1775 | d2 = f; |
| | 1776 | return d2 == d; |
| | 1777 | case AV_OPT_TYPE_RATIONAL: |
| | 1778 | q = av_d2q(o->default_val.dbl, INT_MAX); |
| | 1779 | return !av_cmp_q(*(AVRational*)dst, q); |
| | 1780 | case AV_OPT_TYPE_BINARY: { |
| | 1781 | struct { |
| | 1782 | uint8_t *data; |
| | 1783 | int size; |
| | 1784 | } tmp = {0}; |
| | 1785 | int opt_size = *(int *)((void **)dst + 1); |
| | 1786 | void *opt_ptr = *(void **)dst; |
| | 1787 | if (!opt_ptr && (!o->default_val.str || !strlen(o->default_val.str))) |
| | 1788 | return 1; |
| | 1789 | if (opt_ptr && o->default_val.str && !strlen(o->default_val.str)) |
| | 1790 | return 0; |
| | 1791 | if (opt_size != strlen(o->default_val.str) / 2) |
| | 1792 | return 0; |
| | 1793 | ret = set_string_binary(NULL, NULL, o->default_val.str, &tmp.data); |
| | 1794 | if (!ret) |
| | 1795 | ret = !memcmp(opt_ptr, tmp.data, tmp.size); |
| | 1796 | av_free(tmp.data); |
| | 1797 | return ret; |
| | 1798 | } |
| | 1799 | case AV_OPT_TYPE_DICT: |
| | 1800 | /* Binary and dict have not default support yet. Any pointer is not default. */ |
| | 1801 | return !!(*(void **)dst); |
| | 1802 | case AV_OPT_TYPE_IMAGE_SIZE: |
| | 1803 | if (!o->default_val.str || !strcmp(o->default_val.str, "none")) |
| | 1804 | w = h = 0; |
| | 1805 | else if ((ret = av_parse_video_size(&w, &h, o->default_val.str)) < 0) |
| | 1806 | return ret; |
| | 1807 | return (w == *(int *)dst) && (h == *((int *)dst+1)); |
| | 1808 | case AV_OPT_TYPE_VIDEO_RATE: |
| | 1809 | q = (AVRational){0, 0}; |
| | 1810 | if (o->default_val.str) |
| | 1811 | av_parse_video_rate(&q, o->default_val.str); |
| | 1812 | return !av_cmp_q(*(AVRational*)dst, q); |
| | 1813 | case AV_OPT_TYPE_COLOR: { |
| | 1814 | uint8_t color[4] = {0, 0, 0, 0}; |
| | 1815 | if (o->default_val.str) |
| | 1816 | av_parse_color(color, o->default_val.str, -1, NULL); |
| | 1817 | return !memcmp(color, dst, sizeof(color)); |
| | 1818 | } |
| | 1819 | default: |
| | 1820 | av_log(obj, AV_LOG_WARNING, "Not supported option type: %d, option name: %s\n", o->type, o->name); |
| | 1821 | break; |
| | 1822 | } |
| | 1823 | return AVERROR_PATCHWELCOME; |
| | 1824 | } |
| | 1825 | |
| | 1826 | int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags) |
| | 1827 | { |
| | 1828 | const AVOption *o; |
| | 1829 | void *target; |
| | 1830 | if (!obj) |
| | 1831 | return AVERROR(EINVAL); |
| | 1832 | o = av_opt_find2(obj, name, NULL, 0, search_flags, &target); |
| | 1833 | if (!o) |
| | 1834 | return AVERROR_OPTION_NOT_FOUND; |
| | 1835 | return av_opt_is_set_to_default(target, o); |
| | 1836 | } |
| | 1837 | |
| 1735 | #ifdef TEST | 1838 | #ifdef TEST |
| 1736 | | 1839 | |
| 1737 | typedef struct TestContext | 1840 | typedef struct TestContext |
| @@ -1827,6 +1930,27 @@ int main(void) · 89 unmodified lines |
| 1827 | av_opt_free(&test_ctx); | 1930 | av_opt_free(&test_ctx); |
| 1828 | } | 1931 | } |
| 1829 | | 1932 | |
| | 1933 | printf("\nTesting av_opt_is_set_to_default()\n"); |
| | 1934 | { |
| | 1935 | int ret; |
| | 1936 | TestContext test_ctx = { 0 }; |
| | 1937 | const AVOption *o = NULL; |
| | 1938 | test_ctx.class = &test_class; |
| | 1939 | |
| | 1940 | av_log_set_level(AV_LOG_QUIET); |
| | 1941 | |
| | 1942 | while (o = av_opt_next(&test_ctx, o)) { |
| | 1943 | ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0); |
| | 1944 | printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : ""); |
| | 1945 | } |
| | 1946 | av_opt_set_defaults(&test_ctx); |
| | 1947 | while (o = av_opt_next(&test_ctx, o)) { |
| | 1948 | ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0); |
| | 1949 | printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : ""); |
| | 1950 | } |
| | 1951 | av_opt_free(&test_ctx); |
| | 1952 | } |
| | 1953 | |
| 1830 | printf("\nTesting av_set_options_string()\n"); | 1954 | printf("\nTesting av_set_options_string()\n"); |
| 1831 | { | 1955 | { |
| 1832 | TestContext test_ctx = { 0 }; | 1956 | TestContext test_ctx = { 0 }; |