/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 | } |