Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/asf.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2000, 2001 Fabrice Bellard
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "libavutil/mem.h"
22
#include "asf.h"
23
#include "demux.h"
24
#include "id3v2.h"
25
#include "internal.h"
26
27
/* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
28
const AVMetadataConv ff_asf_metadata_conv[] = {
29
    { "WM/AlbumArtist",          "album_artist"     },
30
    { "WM/AlbumTitle",           "album"            },
31
    { "Author",                  "artist"           },
32
    { "Description",             "comment"          },
33
    { "WM/Composer",             "composer"         },
34
    { "WM/EncodedBy",            "encoded_by"       },
35
    { "WM/EncodingSettings",     "encoder"          },
36
    { "WM/Genre",                "genre"            },
37
    { "WM/Language",             "language"         },
38
    { "WM/OriginalFilename",     "filename"         },
39
    { "WM/PartOfSet",            "disc"             },
40
    /* SetSubTitle can be found in this mapping:
41
     * https://learn.microsoft.com/en-gb/windows/win32/wmformat/id3-tag-support */
42
    { "WM/SetSubTitle",          "disc_subtitle"    },
43
    { "WM/Publisher",            "publisher"        },
44
    { "WM/Tool",                 "encoder"          },
45
    { "WM/TrackNumber",          "track"            },
46
    { "WM/MediaStationCallSign", "service_provider" },
47
    { "WM/MediaStationName",     "service_name"     },
48
//  { "Year"               , "date"        }, TODO: conversion year<->date
49
    { 0 }
50
};
51
52
/* MSDN claims that this should be "compatible with the ID3 frame, APIC",
53
 * but in reality this is only loosely similar */
54
static int asf_read_picture(AVFormatContext *s, int len)
55
607
{
56
607
    const CodecMime *mime = ff_id3v2_mime_tags;
57
607
    enum  AVCodecID id    = AV_CODEC_ID_NONE;
58
607
    char mimetype[64];
59
607
    uint8_t  *desc = NULL;
60
607
    AVStream   *st = NULL;
61
607
    int ret, type, picsize, desc_len;
62
63
    /* type + picsize + mime + desc */
64
607
    if (len < 1 + 4 + 2 + 2) {
65
10
        av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len);
66
10
        return AVERROR_INVALIDDATA;
67
10
    }
68
69
    /* picture type */
70
597
    type = avio_r8(s->pb);
71
597
    len--;
72
597
    if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) {
73
188
        av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type);
74
188
        type = 0;
75
188
    }
76
77
    /* picture data size */
78
597
    picsize = avio_rl32(s->pb);
79
597
    len    -= 4;
80
81
    /* picture MIME type */
82
597
    len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype));
83
3.82k
    while (mime->id != AV_CODEC_ID_NONE) {
84
3.53k
        if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
85
305
            id = mime->id;
86
305
            break;
87
305
        }
88
3.22k
        mime++;
89
3.22k
    }
90
597
    if (id == AV_CODEC_ID_NONE) {
91
292
        av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n",
92
292
               mimetype);
93
292
        return 0;
94
292
    }
95
96
305
    if (picsize >= len || ((int64_t)len - picsize) * 2 + 1 > INT_MAX) {
97
18
        av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d  (len = %d).\n",
98
18
               picsize, len);
99
18
        return AVERROR_INVALIDDATA;
100
18
    }
101
102
    /* picture description */
103
287
    desc_len = (len - picsize) * 2 + 1;
104
287
    desc     = av_malloc(desc_len);
105
287
    if (!desc)
106
0
        return AVERROR(ENOMEM);
107
287
    len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);
108
109
287
    ret = ff_add_attached_pic(s, NULL, s->pb, NULL, picsize);
110
287
    if (ret < 0)
111
75
        goto fail;
112
212
    st = s->streams[s->nb_streams - 1];
113
114
212
    st->codecpar->codec_id        = id;
115
116
212
    if (*desc) {
117
208
        if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0)
118
0
            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
119
208
    } else
120
4
        av_freep(&desc);
121
122
212
    if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0) < 0)
123
0
        av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
124
125
212
    return 0;
126
127
75
fail:
128
75
    av_freep(&desc);
129
75
    return ret;
130
287
}
131
132
static int get_id3_tag(AVFormatContext *s, int len)
133
17.9k
{
134
17.9k
    ID3v2ExtraMeta *id3v2_extra_meta;
135
136
17.9k
    ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len);
137
17.9k
    if (id3v2_extra_meta) {
138
3.69k
        ff_id3v2_parse_apic(s, id3v2_extra_meta);
139
3.69k
        ff_id3v2_parse_chapters(s, id3v2_extra_meta);
140
3.69k
        ff_id3v2_free_extra_meta(&id3v2_extra_meta);
141
3.69k
    }
142
17.9k
    return 0;
143
17.9k
}
144
145
int ff_asf_handle_byte_array(AVFormatContext *s, const char *name,
146
                             int val_len)
147
236k
{
148
236k
    if (!strcmp(name, "WM/Picture")) // handle cover art
149
607
        return asf_read_picture(s, val_len);
150
235k
    else if (!strcmp(name, "ID3")) // handle ID3 tag
151
17.9k
        return get_id3_tag(s, val_len);
152
153
217k
    return 1;
154
236k
}