Browse code

Use AV_METADATA_DONT_STRDUP* / use av_malloced metadata instead of strduped arrays of fixed length. Code from ffmbc with changes to adapt to our metadata API.

Originally committed as revision 20836 to svn://svn.ffmpeg.org/ffmpeg/trunk

Michael Niedermayer authored on 2009/12/14 05:27:29
Showing 9 changed files
... ...
@@ -66,19 +66,20 @@ static int get_tag(ByteIOContext *pb, uint32_t * tag)
66 66
 /* Metadata string read */
67 67
 static void get_meta(AVFormatContext *s, const char *key, int size)
68 68
 {
69
-    uint8_t str[1024];
70
-    int res = get_buffer(s->pb, str, FFMIN(sizeof(str)-1, size));
69
+    uint8_t *str = av_malloc(size+1);
70
+    int res;
71
+
72
+    if (!str) {
73
+        url_fskip(s->pb, size);
74
+        return;
75
+    }
76
+
77
+    res = get_buffer(s->pb, str, size);
71 78
     if (res < 0)
72 79
         return;
73 80
 
74 81
     str[res] = 0;
75
-    if (size & 1)
76
-        size++;
77
-    size -= res;
78
-    if (size)
79
-        url_fskip(s->pb, size);
80
-
81
-    av_metadata_set(&s->metadata, key, str);
82
+    av_metadata_set2(&s->metadata, key, str, AV_METADATA_DONT_STRDUP_VAL);
82 83
 }
83 84
 
84 85
 /* Returns the number of sound data frames or negative on error */
... ...
@@ -33,7 +33,7 @@
33 33
 static int ape_tag_read_field(AVFormatContext *s)
34 34
 {
35 35
     ByteIOContext *pb = s->pb;
36
-    uint8_t key[1024], value[1024];
36
+    uint8_t key[1024], *value;
37 37
     uint32_t size, flags;
38 38
     int i, l, c;
39 39
 
... ...
@@ -51,13 +51,14 @@ static int ape_tag_read_field(AVFormatContext *s)
51 51
         av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key);
52 52
         return -1;
53 53
     }
54
-    l = FFMIN(size, sizeof(value)-1);
55
-    get_buffer(pb, value, l);
56
-    value[l] = 0;
57
-    url_fskip(pb, size-l);
58
-    if (l < size)
59
-        av_log(s, AV_LOG_WARNING, "Too long '%s' tag was truncated.\n", key);
60
-    av_metadata_set(&s->metadata, key, value);
54
+    if (size >= UINT_MAX)
55
+        return -1;
56
+    value = av_malloc(size+1);
57
+    if (!value)
58
+        return AVERROR_NOMEM;
59
+    get_buffer(pb, value, size);
60
+    value[size] = 0;
61
+    av_metadata_set2(&s->metadata, key, value, AV_METADATA_DONT_STRDUP_VAL);
61 62
     return 0;
62 63
 }
63 64
 
... ...
@@ -152,19 +152,27 @@ static int get_value(ByteIOContext *pb, int type){
152 152
 
153 153
 static void get_tag(AVFormatContext *s, const char *key, int type, int len)
154 154
 {
155
-    char value[1024];
155
+    char *value;
156
+
157
+    if ((unsigned)len >= UINT_MAX)
158
+        return;
159
+
160
+    value = av_malloc(len+1);
161
+    if (!value)
162
+        return;
163
+
156 164
     if (type <= 1) {         // unicode or byte
157
-        get_str16_nolen(s->pb, len, value, sizeof(value));
165
+        get_str16_nolen(s->pb, len, value, len);
158 166
     } else if (type <= 5) {  // boolean or DWORD or QWORD or WORD
159 167
         uint64_t num = get_value(s->pb, type);
160
-        snprintf(value, sizeof(value), "%"PRIu64, num);
168
+        snprintf(value, len, "%"PRIu64, num);
161 169
     } else {
162 170
         url_fskip(s->pb, len);
163 171
         return;
164 172
     }
165 173
     if (!strncmp(key, "WM/", 3))
166 174
         key += 3;
167
-    av_metadata_set(&s->metadata, key, value);
175
+    av_metadata_set2(&s->metadata, key, value, AV_METADATA_DONT_STRDUP_VAL);
168 176
 }
169 177
 
170 178
 static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
... ...
@@ -230,14 +230,19 @@ static void clean_index(AVFormatContext *s){
230 230
 static int avi_read_tag(AVFormatContext *s, const char *key, unsigned int size)
231 231
 {
232 232
     ByteIOContext *pb = s->pb;
233
-    uint8_t value[1024];
233
+    char *value;
234 234
 
235
-    int64_t i = url_ftell(pb);
236 235
     size += (size & 1);
237
-    get_strz(pb, value, sizeof(value));
238
-    url_fseek(pb, i+size, SEEK_SET);
239 236
 
240
-    return av_metadata_set(&s->metadata, key, value);
237
+    if (size == UINT_MAX)
238
+        return -1;
239
+    value = av_malloc(size+1);
240
+    if (!value)
241
+        return -1;
242
+    get_strz(pb, value, size);
243
+
244
+    return av_metadata_set2(&s->metadata, key, value,
245
+                                  AV_METADATA_DONT_STRDUP_VAL);
241 246
 }
242 247
 
243 248
 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
... ...
@@ -104,25 +104,25 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_co
104 104
     return 0;
105 105
 }
106 106
 
107
-static int amf_get_string(ByteIOContext *ioc, char *buffer, int buffsize) {
108
-    int length = get_be16(ioc);
109
-    if(length >= buffsize) {
110
-        url_fskip(ioc, length);
111
-        return -1;
112
-    }
107
+static int amf_get_string(ByteIOContext *ioc, char **buf)
108
+{
109
+    uint16_t len = get_be16(ioc);
113 110
 
114
-    get_buffer(ioc, buffer, length);
111
+    *buf = av_malloc(len+1);
112
+    if (!*buf)
113
+        return AVERROR_NOMEM;
115 114
 
116
-    buffer[length] = '\0';
115
+    get_buffer(ioc, *buf, len);
116
+    (*buf)[len] = '\0';
117 117
 
118
-    return length;
118
+    return len;
119 119
 }
120 120
 
121 121
 static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, int64_t max_pos, int depth) {
122 122
     AVCodecContext *acodec, *vcodec;
123 123
     ByteIOContext *ioc;
124 124
     AMFDataType amf_type;
125
-    char str_val[256];
125
+    char *str = NULL;
126 126
     double num_val;
127 127
 
128 128
     num_val = 0;
... ...
@@ -136,7 +136,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
136 136
         case AMF_DATA_TYPE_BOOL:
137 137
             num_val = get_byte(ioc); break;
138 138
         case AMF_DATA_TYPE_STRING:
139
-            if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0)
139
+            if(amf_get_string(ioc, &str) < 0)
140 140
                 return -1;
141 141
             break;
142 142
         case AMF_DATA_TYPE_OBJECT: {
... ...
@@ -157,10 +157,11 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
157 157
             break; //these take up no additional space
158 158
         case AMF_DATA_TYPE_MIXEDARRAY:
159 159
             url_fskip(ioc, 4); //skip 32-bit max array index
160
-            while(url_ftell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
160
+            while(url_ftell(ioc) < max_pos - 2 && amf_get_string(ioc, &str) > 0) {
161 161
                 //this is the only case in which we would want a nested parse to not skip over the object
162
-                if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0)
162
+                if(amf_parse_object(s, astream, vstream, str, max_pos, depth + 1) < 0)
163 163
                     return -1;
164
+                av_freep(&str);
164 165
             }
165 166
             if(get_byte(ioc) != AMF_END_OF_OBJECT)
166 167
                 return -1;
... ...
@@ -187,16 +188,15 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
187 187
         vcodec = vstream ? vstream->codec : NULL;
188 188
 
189 189
         if(amf_type == AMF_DATA_TYPE_BOOL) {
190
-            av_strlcpy(str_val, num_val > 0 ? "true" : "false", sizeof(str_val));
191
-            av_metadata_set(&s->metadata, key, str_val);
190
+            av_metadata_set2(&s->metadata, key, av_d2str(num_val), AV_METADATA_DONT_STRDUP_VAL);
192 191
         } else if(amf_type == AMF_DATA_TYPE_NUMBER) {
193
-            snprintf(str_val, sizeof(str_val), "%.f", num_val);
194
-            av_metadata_set(&s->metadata, key, str_val);
192
+            av_metadata_set2(&s->metadata, key, av_d2str(num_val), AV_METADATA_DONT_STRDUP_VAL);
195 193
             if(!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE;
196 194
             else if(!strcmp(key, "videodatarate") && vcodec && 0 <= (int)(num_val * 1024.0))
197 195
                 vcodec->bit_rate = num_val * 1024.0;
198 196
         } else if (amf_type == AMF_DATA_TYPE_STRING)
199
-          av_metadata_set(&s->metadata, key, str_val);
197
+            av_metadata_set2(&s->metadata, key, str,
198
+                                   AV_METADATA_DONT_STRDUP_VAL);
200 199
     }
201 200
 
202 201
     return 0;
... ...
@@ -207,7 +207,7 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
207 207
     AVStream *stream, *astream, *vstream;
208 208
     ByteIOContext *ioc;
209 209
     int i;
210
-    char buffer[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want.
210
+    char *buf = NULL; //only needs to hold the string "onMetaData". Anything longer is something we don't want.
211 211
 
212 212
     astream = NULL;
213 213
     vstream = NULL;
... ...
@@ -215,8 +215,11 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
215 215
 
216 216
     //first object needs to be "onMetaData" string
217 217
     type = get_byte(ioc);
218
-    if(type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0 || strcmp(buffer, "onMetaData"))
218
+    if (type != AMF_DATA_TYPE_STRING ||
219
+        amf_get_string(ioc, &buf) < 0 || strcmp(buf, "onMetaData")) {
220
+        av_freep(&buf);
219 221
         return -1;
222
+    }
220 223
 
221 224
     //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
222 225
     for(i = 0; i < s->nb_streams; i++) {
... ...
@@ -226,8 +229,9 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
226 226
     }
227 227
 
228 228
     //parse the second object (we want a mixed array)
229
-    if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)
229
+    if(amf_parse_object(s, astream, vstream, buf, next_pos, 0) < 0)
230 230
         return -1;
231
+    av_freep(&buf);
231 232
 
232 233
     return 0;
233 234
 }
... ...
@@ -102,10 +102,9 @@ vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
102 102
             memcpy(ct, v, vl);
103 103
             ct[vl] = 0;
104 104
 
105
-            av_metadata_set(&as->metadata, tt, ct);
106
-
107
-            av_freep(&tt);
108
-            av_freep(&ct);
105
+            av_metadata_set2(&as->metadata, tt, ct,
106
+                                   AV_METADATA_DONT_STRDUP_KEY |
107
+                                   AV_METADATA_DONT_STRDUP_VAL);
109 108
         }
110 109
     }
111 110
 
... ...
@@ -93,15 +93,16 @@ static int sox_read_header(AVFormatContext *s,
93 93
         return -1;
94 94
     }
95 95
 
96
-    if (comment_size &&
97
-        comment_size + FF_INPUT_BUFFER_PADDING_SIZE >= comment_size) {
98
-        char *comment = av_mallocz(comment_size + FF_INPUT_BUFFER_PADDING_SIZE);
96
+    if (comment_size && comment_size < UINT_MAX) {
97
+        char *comment = av_malloc(comment_size+1);
99 98
         if (get_buffer(pb, comment, comment_size) != comment_size) {
100 99
             av_freep(&comment);
101 100
             return AVERROR_IO;
102 101
         }
103
-        av_metadata_set(&s->metadata, "comment", comment);
104
-        av_freep(&comment);
102
+        comment[comment_size] = 0;
103
+
104
+        av_metadata_set2(&s->metadata, "comment", comment,
105
+                               AV_METADATA_DONT_STRDUP_VAL);
105 106
     }
106 107
 
107 108
     url_fskip(pb, header_size - SOX_FIXED_HDR - comment_size);
... ...
@@ -45,15 +45,18 @@ static int vqf_probe(AVProbeData *probe_packet)
45 45
 static void add_metadata(AVFormatContext *s, const char *tag,
46 46
                          unsigned int tag_len, unsigned int remaining)
47 47
 {
48
-    char buf[2048];
49
-    int len = FFMIN3(tag_len, remaining, sizeof(buf) - 1);
48
+    int len = FFMIN(tag_len, remaining);
49
+    char *buf;
50 50
 
51
-    if (len != tag_len)
52
-        av_log(s, AV_LOG_ERROR, "Warning: truncating metadata!\n");
51
+    if (len == UINT_MAX)
52
+        return;
53 53
 
54
+    buf = av_malloc(len+1);
55
+    if (!buf)
56
+        return;
54 57
     get_buffer(s->pb, buf, len);
55 58
     buf[len] = 0;
56
-    av_metadata_set(&s->metadata, tag, buf);
59
+    av_metadata_set2(&s->metadata, tag, buf, AV_METADATA_DONT_STRDUP_VAL);
57 60
 }
58 61
 
59 62
 static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap)
... ...
@@ -140,10 +140,9 @@ static int wc3_read_header(AVFormatContext *s,
140 140
     unsigned int fourcc_tag;
141 141
     unsigned int size;
142 142
     AVStream *st;
143
-    char buffer[513];
144 143
     int ret = 0;
145 144
     int current_palette = 0;
146
-    int bytes_to_read;
145
+    char *buffer;
147 146
     int i;
148 147
     unsigned char rotate;
149 148
 
... ...
@@ -185,14 +184,14 @@ static int wc3_read_header(AVFormatContext *s,
185 185
 
186 186
         case BNAM_TAG:
187 187
             /* load up the name */
188
-            if ((unsigned)size < 512)
189
-                bytes_to_read = size;
190
-            else
191
-                bytes_to_read = 512;
192
-            if ((ret = get_buffer(pb, buffer, bytes_to_read)) != bytes_to_read)
188
+            buffer = av_malloc(size+1);
189
+            if (!buffer)
190
+                return AVERROR_NOMEM;
191
+            if ((ret = get_buffer(pb, buffer, size)) != size)
193 192
                 return AVERROR(EIO);
194
-            buffer[bytes_to_read] = 0;
195
-            av_metadata_set(&s->metadata, "title", buffer);
193
+            buffer[size] = 0;
194
+            av_metadata_set2(&s->metadata, "title", buffer,
195
+                                   AV_METADATA_DONT_STRDUP_VAL);
196 196
             break;
197 197
 
198 198
         case SIZE_TAG: