[FFmpeg-devel] [PATCH v3] avformat/dashdec: fix memleak for commit commit e134c203

Steven Liu lq at chinaffmpeg.org
Sat Mar 28 03:47:20 EET 2020



> 2020年3月28日 上午9:37,Andreas Rheinhardt <andreas.rheinhardt at gmail.com> 写道:
> 
> Steven Liu:
>> These member will be used for get more correct information of the MPD
>> 
>> Suggested-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
>> Suggested-by: Nicolas George <george at nsup.org>
>> Signed-off-by: Steven Liu <lq at chinaffmpeg.org>
>> ---
>> libavformat/dashdec.c | 244 ++++++++++++++++++++++++++++++++++++------
>> 1 file changed, 214 insertions(+), 30 deletions(-)
>> 
>> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
>> index 5bbe5d3985..b5bb8e674c 100644
>> --- a/libavformat/dashdec.c
>> +++ b/libavformat/dashdec.c
>> @@ -108,6 +108,7 @@ struct representation {
>>     int64_t cur_seg_offset;
>>     int64_t cur_seg_size;
>>     struct fragment *cur_seg;
>> +    char *lang;
>> 
>>     /* Currently active Media Initialization Section */
>>     struct fragment *init_section;
>> @@ -122,19 +123,15 @@ struct representation {
>> typedef struct DASHContext {
>>     const AVClass *class;
>>     char *base_url;
>> -    char *adaptionset_contenttype_val;
>> -    char *adaptionset_par_val;
>> -    char *adaptionset_lang_val;
>> -    char *adaptionset_minbw_val;
>> -    char *adaptionset_maxbw_val;
>> -    char *adaptionset_minwidth_val;
>> -    char *adaptionset_maxwidth_val;
>> -    char *adaptionset_minheight_val;
>> -    char *adaptionset_maxheight_val;
>> -    char *adaptionset_minframerate_val;
>> -    char *adaptionset_maxframerate_val;
>> -    char *adaptionset_segmentalignment_val;
>> -    char *adaptionset_bitstreamswitching_val;
>> +    char *adaptionset_lang;
>> +    uint64_t adaptionset_minbw;
>> +    uint64_t adaptionset_maxbw;
>> +    uint64_t adaptionset_minwidth;
>> +    uint64_t adaptionset_maxwidth;
>> +    uint64_t adaptionset_minheight;
>> +    uint64_t adaptionset_maxheight;
>> +    AVRational adaptionset_minframerate;
>> +    AVRational adaptionset_maxframerate;
>> 
>>     int n_videos;
>>     struct representation **videos;
>> @@ -169,6 +166,79 @@ typedef struct DASHContext {
>> 
>> } DASHContext;
>> 
>> +static int get_ratio_from_string(AVRational *dst, char *src)
>> +{
>> +    char *p = src;
>> +    char *end = NULL;
>> +    char *end_ptr = NULL;
>> +    int num, den;
>> +
>> +    num = (int)strtol(p, &end_ptr, 10);
>> +    if (errno == ERANGE || end_ptr == src) {
>> +        return AVERROR_INVALIDDATA;
>> +    }
>> +
>> +    if (end_ptr[0] == '\0') {
>> +        dst->den = 1;
>> +        dst->num = num;
>> +        return 0;
>> +    }
>> +
>> +    if (end_ptr[0] != '/')
>> +        return AVERROR_INVALIDDATA;
>> +    p = end_ptr + 1;
>> +    den = (int)strtol(p, &end, 10);
>> +    if (errno == ERANGE || end == src) {
>> +        dst->den = 1;
>> +        return AVERROR_INVALIDDATA;
>> +    }
>> +    dst->den = den;
>> +
>> +    return 0;
>> +}
>> +
>> +static uint64_t dash_prop_get_int64(AVFormatContext *s, xmlNodePtr node, uint64_t *dst, const char *key)
>> +{
>> +    char *end_ptr = NULL;
>> +    char *val = xmlGetProp(node, key);
>> +    int ret = 0;
>> +
>> +    if (val) {
>> +        ret = strtoull(val, &end_ptr, 10);
>> +        if (errno == ERANGE) {
>> +            av_log(s, AV_LOG_WARNING, "overflow/underflow when get value of %s\n", key);
>> +            xmlFree(val);
>> +            return AVERROR_INVALIDDATA;
>> +        }
>> +        if (end_ptr == val || end_ptr[0] != '\0') {
>> +            av_log(s, AV_LOG_ERROR, "The %s field value is "
>> +            "not a valid number: %s\n", key, val);
>> +            xmlFree(val);
>> +            return AVERROR_INVALIDDATA;
>> +        }
>> +        *dst = ret;
>> +        xmlFree(val);
>> +    }
>> +    return ret;
>> +}
>> +
>> +static int dash_get_prop_ratio(AVFormatContext *s, xmlNodePtr node, AVRational *member, const char *key)
>> +{
>> +    char *val = xmlGetProp(node, key);
>> +    int ret = 0;
>> +    AVRational rate;
>> +
>> +    if (val) {
>> +        ret = get_ratio_from_string(&rate, val);
>> +        if (ret < 0)
>> +            av_log(s, AV_LOG_WARNING, "Ignoring invalid %s frame rate '%s'\n", key, val);
>> +        xmlFree(val);
>> +    }
>> +    member->num = rate.num;
>> +    member->den = rate.den;
>> +    return ret;
>> +}
>> +
>> static int ishttp(char *url)
>> {
>>     const char *proto_name = avio_find_protocol_name(url);
>> @@ -885,6 +955,15 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
>>             ret = AVERROR(ENOMEM);
>>             goto end;
>>         }
>> +        if (c->adaptionset_lang) {
>> +            rep->lang = av_strdup(c->adaptionset_lang);
>> +            if (!rep->lang) {
>> +                av_log(s, AV_LOG_ERROR, "alloc language memory failure\n");
>> +                av_freep(&rep);
>> +                ret = AVERROR(ENOMEM);
>> +                goto end;
>> +            }
>> +        }
>>         rep->parent = s;
>>         representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate");
>>         representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL");
>> @@ -1070,15 +1149,61 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
>>         }
>> 
>>         if (rep) {
>> +            uint64_t width = 0;
>> +            uint64_t height = 0;
>> +
>>             if (rep->fragment_duration > 0 && !rep->fragment_timescale)
>>                 rep->fragment_timescale = 1;
>>             rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0;
>> +            if (rep_bandwidth_val && (rep->bandwidth > c->adaptionset_maxbw || rep->bandwidth < c->adaptionset_minbw)) {
>> +                av_log(s, AV_LOG_WARNING, "The bandwidth of representation %s is incorrect, "
>> +                        "will ignore this representation.\n", rep_id_val);
>> +                free_representation(rep);
>> +                goto end;
>> +            }
>> +
>> +            ret = dash_prop_get_int64(s, representation_node, &width, "width");
>> +            if (ret < 0)
>> +                av_log(s, AV_LOG_WARNING, "Ignoring the width of representation %s is incorrect.\n", rep_id_val);
>> +            if (width > c->adaptionset_maxwidth || width < c->adaptionset_minwidth) {
>> +                av_log(s, AV_LOG_WARNING, "Ignoring width of representation %s is incorrect, "
>> +                "will ignore this representation.\n", rep_id_val);
>> +                free_representation(rep);
>> +                goto end;
>> +            }
>> +
>> +            ret = dash_prop_get_int64(s, representation_node, &height, "height");
>> +            if (ret < 0)
>> +                av_log(s, AV_LOG_WARNING, "Ignoring the height of representation %s is incorrect.\n", rep_id_val);
>> +            if (height > c->adaptionset_maxheight || height < c->adaptionset_minheight) {
>> +                av_log(s, AV_LOG_WARNING, "Ignoring height of representation %s is incorrect, "
>> +                "will ignore this representation.\n", rep_id_val);
>> +                free_representation(rep);
>> +                goto end;
>> +            }
>> +
>>             strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id));
>>             rep->framerate = av_make_q(0, 0);
>>             if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) {
>> -                ret = av_parse_video_rate(&rep->framerate, rep_framerate_val);
>> +                ret = get_ratio_from_string(&rep->framerate, rep_framerate_val);
>>                 if (ret < 0)
>> -                    av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val);
>> +                    av_log(s, AV_LOG_WARNING, "Ignoring invalid frame rate '%s'\n", rep_framerate_val);
>> +                if (c->adaptionset_maxframerate.num > 0) {
>> +                    if (av_cmp_q(rep->framerate, c->adaptionset_maxframerate) == 1) {
>> +                        av_log(s, AV_LOG_WARNING, "Ignoring frame rate of representation %s incorrect, "
>> +                        "will ignore this representation.\n", rep_id_val);
>> +                        free_representation(rep);
>> +                        goto end;
>> +                    }
>> +                }
>> +                if (c->adaptionset_minframerate.num > 0) {
>> +                    if (av_cmp_q(rep->framerate, c->adaptionset_minframerate) == -1) {
>> +                        av_log(s, AV_LOG_WARNING, "Ignoring frame rate of representation %s incorrect, "
>> +                        "will ignore this representation.\n", rep_id_val);
>> +                        free_representation(rep);
>> +                        goto end;
>> +                    }
>> +                }
>>             }
>> 
>>             switch (type) {
>> @@ -1106,6 +1231,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
>>     subtitle_rep_idx += type == AVMEDIA_TYPE_SUBTITLE;
>> 
>> end:
>> +
>>     if (rep_id_val)
>>         xmlFree(rep_id_val);
>>     if (rep_bandwidth_val)
>> @@ -1116,6 +1242,62 @@ end:
>>     return ret;
>> }
>> 
>> +static int parse_manifest_adaptationset_attr(AVFormatContext *s, xmlNodePtr adaptionset_node)
>> +{
>> +    int ret = 0;
>> +    DASHContext *c = s->priv_data;
>> +
>> +    if (!adaptionset_node) {
>> +        av_log(s, AV_LOG_WARNING, "Cannot get AdaptionSet\n");
>> +        return AVERROR(EINVAL);
>> +    }
>> +    c->adaptionset_minframerate = av_make_q(0, 0);
>> +    c->adaptionset_maxframerate = av_make_q(0, 0);
>> +    c->adaptionset_maxbw = UINT64_MAX;
>> +    c->adaptionset_minbw = 0;
>> +    c->adaptionset_minwidth = 0;
>> +    c->adaptionset_maxwidth = UINT64_MAX;
>> +    c->adaptionset_minheight = 0;
>> +    c->adaptionset_maxheight = UINT64_MAX;
>> +
>> +    c->adaptionset_lang = xmlGetProp(adaptionset_node, "lang");
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_minbw, "minBandwidth");
>> +    if (ret  < 0)
>> +        c->adaptionset_minbw = 0;
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_maxbw, "maxBandwidth");
>> +    if (ret <= 0)
>> +        c->adaptionset_maxbw = UINT64_MAX;
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_minwidth, "minWidth");
>> +    if (ret < 0)
>> +        c->adaptionset_minwidth = 0;
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_maxwidth, "maxWidth");
>> +    if (ret <= 0)
>> +        c->adaptionset_maxwidth = UINT64_MAX;
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_minheight, "minHeight");
>> +    if (ret < 0)
>> +        c->adaptionset_minheight = 0;
>> +
>> +    ret = dash_prop_get_int64(s, adaptionset_node, &c->adaptionset_maxheight, "maxHeight");
>> +    if (ret <= 0)
>> +        c->adaptionset_maxheight = UINT64_MAX;
>> +
>> +    ret = dash_get_prop_ratio(s, adaptionset_node, &c->adaptionset_minframerate, "minFrameRate");
>> +    if (ret < 0) {
>> +        c->adaptionset_minframerate = av_make_q(0, 0);
>> +    }
>> +
>> +    ret = dash_get_prop_ratio(s, adaptionset_node, &c->adaptionset_maxframerate, "maxFrameRate");
>> +    if (ret < 0)
>> +        c->adaptionset_maxframerate = av_make_q(0, 0);
>> +
>> +    return ret;
>> +}
>> +
>> static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
>>                                         xmlNodePtr adaptionset_node,
>>                                         xmlNodePtr mpd_baseurl_node,
>> @@ -1131,19 +1313,10 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
>>     xmlNodePtr adaptionset_segmentlist_node = NULL;
>>     xmlNodePtr adaptionset_supplementalproperty_node = NULL;
>>     xmlNodePtr node = NULL;
>> -    c->adaptionset_contenttype_val = xmlGetProp(adaptionset_node, "contentType");
>> -    c->adaptionset_par_val = xmlGetProp(adaptionset_node, "par");
>> -    c->adaptionset_lang_val = xmlGetProp(adaptionset_node, "lang");
>> -    c->adaptionset_minbw_val = xmlGetProp(adaptionset_node, "minBandwidth");
>> -    c->adaptionset_maxbw_val = xmlGetProp(adaptionset_node, "maxBandwidth");
>> -    c->adaptionset_minwidth_val = xmlGetProp(adaptionset_node, "minWidth");
>> -    c->adaptionset_maxwidth_val = xmlGetProp(adaptionset_node, "maxWidth");
>> -    c->adaptionset_minheight_val = xmlGetProp(adaptionset_node, "minHeight");
>> -    c->adaptionset_maxheight_val = xmlGetProp(adaptionset_node, "maxHeight");
>> -    c->adaptionset_minframerate_val = xmlGetProp(adaptionset_node, "minFrameRate");
>> -    c->adaptionset_maxframerate_val = xmlGetProp(adaptionset_node, "maxFrameRate");
>> -    c->adaptionset_segmentalignment_val = xmlGetProp(adaptionset_node, "segmentAlignment");
>> -    c->adaptionset_bitstreamswitching_val = xmlGetProp(adaptionset_node, "bitstreamSwitching");
>> +
>> +    ret = parse_manifest_adaptationset_attr(s, adaptionset_node);
>> +    if (ret < 0)
>> +        return ret;
>> 
>>     node = xmlFirstElementChild(adaptionset_node);
>>     while (node) {
>> @@ -1170,12 +1343,15 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
>>                                                 adaptionset_segmentlist_node,
>>                                                 adaptionset_supplementalproperty_node);
>>             if (ret < 0) {
>> -                return ret;
>> +                goto end;
>>             }
>>         }
>>         node = xmlNextElementSibling(node);
>>     }
>> -    return 0;
>> +
>> +end:
>> +    av_freep(&c->adaptionset_lang);
>> +    return ret;
>> }
>> 
>> static int parse_programinformation(AVFormatContext *s, xmlNodePtr node)
>> @@ -2148,6 +2324,10 @@ static int dash_read_header(AVFormatContext *s)
>>                 av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0);
>>             if (rep->id[0])
>>                 av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0);
>> +            if (rep->lang) {
>> +                av_dict_set(&rep->assoc_stream->metadata, "lang", rep->lang, 0);
>> +                av_freep(&rep->lang);
>> +            }
>>         }
>>         for (i = 0; i < c->n_subtitles; i++) {
>>             rep = c->subtitles[i];
>> @@ -2155,6 +2335,10 @@ static int dash_read_header(AVFormatContext *s)
>>             rep->assoc_stream = s->streams[rep->stream_index];
>>             if (rep->id[0])
>>                 av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0);
>> +            if (rep->lang) {
>> +                av_dict_set(&rep->assoc_stream->metadata, "lang", rep->lang, 0);
>> +                av_freep(&rep->lang);
>> +            }
>>         }
>>     }
>> 
>> 
> The commit title says that this commit is about fixing a memleak (it btw
> has one "commit" too much in it), whereas most of this patch is about
> adding new functionality. Which makes me wonder how you intend to fix
> this in the old releases? Backport everything?
> (This problem would of course not exist if the new functionality would
> be split from fixing the memleak.)
What about modify to: avformat/dashdec: refine functionally for commit e134c203
> 
> - Andreas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".

Thanks

Steven Liu





More information about the ffmpeg-devel mailing list