• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "asf.h"
22 #include "demux.h"
23 #include "id3v2.h"
24 #include "internal.h"
25 
26 /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
27 const AVMetadataConv ff_asf_metadata_conv[] = {
28     { "WM/AlbumArtist",          "album_artist"     },
29     { "WM/AlbumTitle",           "album"            },
30     { "Author",                  "artist"           },
31     { "Description",             "comment"          },
32     { "WM/Composer",             "composer"         },
33     { "WM/EncodedBy",            "encoded_by"       },
34     { "WM/EncodingSettings",     "encoder"          },
35     { "WM/Genre",                "genre"            },
36     { "WM/Language",             "language"         },
37     { "WM/OriginalFilename",     "filename"         },
38     { "WM/PartOfSet",            "disc"             },
39     { "WM/Publisher",            "publisher"        },
40     { "WM/Tool",                 "encoder"          },
41     { "WM/TrackNumber",          "track"            },
42     { "WM/MediaStationCallSign", "service_provider" },
43     { "WM/MediaStationName",     "service_name"     },
44 //  { "Year"               , "date"        }, TODO: conversion year<->date
45     { 0 }
46 };
47 
48 /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
49  * but in reality this is only loosely similar */
asf_read_picture(AVFormatContext * s,int len)50 static int asf_read_picture(AVFormatContext *s, int len)
51 {
52     const CodecMime *mime = ff_id3v2_mime_tags;
53     enum  AVCodecID id    = AV_CODEC_ID_NONE;
54     char mimetype[64];
55     uint8_t  *desc = NULL;
56     AVStream   *st = NULL;
57     int ret, type, picsize, desc_len;
58 
59     /* type + picsize + mime + desc */
60     if (len < 1 + 4 + 2 + 2) {
61         av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len);
62         return AVERROR_INVALIDDATA;
63     }
64 
65     /* picture type */
66     type = avio_r8(s->pb);
67     len--;
68     if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) {
69         av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type);
70         type = 0;
71     }
72 
73     /* picture data size */
74     picsize = avio_rl32(s->pb);
75     len    -= 4;
76 
77     /* picture MIME type */
78     len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype));
79     while (mime->id != AV_CODEC_ID_NONE) {
80         if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
81             id = mime->id;
82             break;
83         }
84         mime++;
85     }
86     if (id == AV_CODEC_ID_NONE) {
87         av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n",
88                mimetype);
89         return 0;
90     }
91 
92     if (picsize >= len) {
93         av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n",
94                picsize, len);
95         return AVERROR_INVALIDDATA;
96     }
97 
98     /* picture description */
99     desc_len = (len - picsize) * 2 + 1;
100     desc     = av_malloc(desc_len);
101     if (!desc)
102         return AVERROR(ENOMEM);
103     len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);
104 
105     ret = ff_add_attached_pic(s, NULL, s->pb, NULL, picsize);
106     if (ret < 0)
107         goto fail;
108     st = s->streams[s->nb_streams - 1];
109 
110     st->codecpar->codec_id        = id;
111 
112     if (*desc) {
113         if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0)
114             av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
115     } else
116         av_freep(&desc);
117 
118     if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0) < 0)
119         av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
120 
121     return 0;
122 
123 fail:
124     av_freep(&desc);
125     return ret;
126 }
127 
get_id3_tag(AVFormatContext * s,int len)128 static int get_id3_tag(AVFormatContext *s, int len)
129 {
130     ID3v2ExtraMeta *id3v2_extra_meta;
131 
132     ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len);
133     if (id3v2_extra_meta) {
134         ff_id3v2_parse_apic(s, id3v2_extra_meta);
135         ff_id3v2_parse_chapters(s, id3v2_extra_meta);
136         ff_id3v2_free_extra_meta(&id3v2_extra_meta);
137     }
138     return 0;
139 }
140 
ff_asf_handle_byte_array(AVFormatContext * s,const char * name,int val_len)141 int ff_asf_handle_byte_array(AVFormatContext *s, const char *name,
142                              int val_len)
143 {
144     if (!strcmp(name, "WM/Picture")) // handle cover art
145         return asf_read_picture(s, val_len);
146     else if (!strcmp(name, "ID3")) // handle ID3 tag
147         return get_id3_tag(s, val_len);
148 
149     return 1;
150 }
151