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