annotate ffmpeg/libavformat/flvdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * FLV demuxer
yading@11 3 * Copyright (c) 2003 The FFmpeg Project
yading@11 4 *
yading@11 5 * This demuxer will generate a 1 byte extradata for VP6F content.
yading@11 6 * It is composed of:
yading@11 7 * - upper 4bits: difference between encoded width and visible width
yading@11 8 * - lower 4bits: difference between encoded height and visible height
yading@11 9 *
yading@11 10 * This file is part of FFmpeg.
yading@11 11 *
yading@11 12 * FFmpeg is free software; you can redistribute it and/or
yading@11 13 * modify it under the terms of the GNU Lesser General Public
yading@11 14 * License as published by the Free Software Foundation; either
yading@11 15 * version 2.1 of the License, or (at your option) any later version.
yading@11 16 *
yading@11 17 * FFmpeg is distributed in the hope that it will be useful,
yading@11 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 20 * Lesser General Public License for more details.
yading@11 21 *
yading@11 22 * You should have received a copy of the GNU Lesser General Public
yading@11 23 * License along with FFmpeg; if not, write to the Free Software
yading@11 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 25 */
yading@11 26
yading@11 27 #include "libavutil/avstring.h"
yading@11 28 #include "libavutil/channel_layout.h"
yading@11 29 #include "libavutil/dict.h"
yading@11 30 #include "libavutil/opt.h"
yading@11 31 #include "libavutil/intfloat.h"
yading@11 32 #include "libavutil/mathematics.h"
yading@11 33 #include "libavcodec/bytestream.h"
yading@11 34 #include "libavcodec/mpeg4audio.h"
yading@11 35 #include "avformat.h"
yading@11 36 #include "internal.h"
yading@11 37 #include "avio_internal.h"
yading@11 38 #include "flv.h"
yading@11 39
yading@11 40 #define VALIDATE_INDEX_TS_THRESH 2500
yading@11 41
yading@11 42 typedef struct {
yading@11 43 const AVClass *class; ///< Class for private options.
yading@11 44 int trust_metadata; ///< configure streams according onMetaData
yading@11 45 int wrong_dts; ///< wrong dts due to negative cts
yading@11 46 uint8_t *new_extradata[FLV_STREAM_TYPE_NB];
yading@11 47 int new_extradata_size[FLV_STREAM_TYPE_NB];
yading@11 48 int last_sample_rate;
yading@11 49 int last_channels;
yading@11 50 struct {
yading@11 51 int64_t dts;
yading@11 52 int64_t pos;
yading@11 53 } validate_index[2];
yading@11 54 int validate_next;
yading@11 55 int validate_count;
yading@11 56 int searched_for_end;
yading@11 57 } FLVContext;
yading@11 58
yading@11 59 static int flv_probe(AVProbeData *p)
yading@11 60 {
yading@11 61 const uint8_t *d;
yading@11 62
yading@11 63 d = p->buf;
yading@11 64 if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5]==0 && AV_RB32(d+5)>8) {
yading@11 65 return AVPROBE_SCORE_MAX;
yading@11 66 }
yading@11 67 return 0;
yading@11 68 }
yading@11 69
yading@11 70 static AVStream *create_stream(AVFormatContext *s, int codec_type)
yading@11 71 {
yading@11 72 AVStream *st = avformat_new_stream(s, NULL);
yading@11 73 if (!st)
yading@11 74 return NULL;
yading@11 75 st->codec->codec_type = codec_type;
yading@11 76 if(s->nb_streams>=3 ||( s->nb_streams==2
yading@11 77 && s->streams[0]->codec->codec_type != AVMEDIA_TYPE_DATA
yading@11 78 && s->streams[1]->codec->codec_type != AVMEDIA_TYPE_DATA))
yading@11 79 s->ctx_flags &= ~AVFMTCTX_NOHEADER;
yading@11 80
yading@11 81 avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
yading@11 82 return st;
yading@11 83 }
yading@11 84 static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
yading@11 85 {
yading@11 86 int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
yading@11 87 int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
yading@11 88 int codec_id;
yading@11 89
yading@11 90 if (!acodec->codec_id && !acodec->codec_tag)
yading@11 91 return 1;
yading@11 92
yading@11 93 if (acodec->bits_per_coded_sample != bits_per_coded_sample)
yading@11 94 return 0;
yading@11 95
yading@11 96 switch(flv_codecid) {
yading@11 97 //no distinction between S16 and S8 PCM codec flags
yading@11 98 case FLV_CODECID_PCM:
yading@11 99 codec_id = bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 :
yading@11 100 #if HAVE_BIGENDIAN
yading@11 101 AV_CODEC_ID_PCM_S16BE;
yading@11 102 #else
yading@11 103 AV_CODEC_ID_PCM_S16LE;
yading@11 104 #endif
yading@11 105 return codec_id == acodec->codec_id;
yading@11 106 case FLV_CODECID_PCM_LE:
yading@11 107 codec_id = bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE;
yading@11 108 return codec_id == acodec->codec_id;
yading@11 109 case FLV_CODECID_AAC:
yading@11 110 return acodec->codec_id == AV_CODEC_ID_AAC;
yading@11 111 case FLV_CODECID_ADPCM:
yading@11 112 return acodec->codec_id == AV_CODEC_ID_ADPCM_SWF;
yading@11 113 case FLV_CODECID_SPEEX:
yading@11 114 return acodec->codec_id == AV_CODEC_ID_SPEEX;
yading@11 115 case FLV_CODECID_MP3:
yading@11 116 return acodec->codec_id == AV_CODEC_ID_MP3;
yading@11 117 case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
yading@11 118 case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
yading@11 119 case FLV_CODECID_NELLYMOSER:
yading@11 120 return acodec->codec_id == AV_CODEC_ID_NELLYMOSER;
yading@11 121 case FLV_CODECID_PCM_MULAW:
yading@11 122 return acodec->sample_rate == 8000 &&
yading@11 123 acodec->codec_id == AV_CODEC_ID_PCM_MULAW;
yading@11 124 case FLV_CODECID_PCM_ALAW:
yading@11 125 return acodec->sample_rate = 8000 &&
yading@11 126 acodec->codec_id == AV_CODEC_ID_PCM_ALAW;
yading@11 127 default:
yading@11 128 return acodec->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
yading@11 129 }
yading@11 130 }
yading@11 131
yading@11 132 static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) {
yading@11 133 switch(flv_codecid) {
yading@11 134 //no distinction between S16 and S8 PCM codec flags
yading@11 135 case FLV_CODECID_PCM:
yading@11 136 acodec->codec_id = acodec->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 :
yading@11 137 #if HAVE_BIGENDIAN
yading@11 138 AV_CODEC_ID_PCM_S16BE;
yading@11 139 #else
yading@11 140 AV_CODEC_ID_PCM_S16LE;
yading@11 141 #endif
yading@11 142 break;
yading@11 143 case FLV_CODECID_PCM_LE:
yading@11 144 acodec->codec_id = acodec->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE; break;
yading@11 145 case FLV_CODECID_AAC : acodec->codec_id = AV_CODEC_ID_AAC; break;
yading@11 146 case FLV_CODECID_ADPCM: acodec->codec_id = AV_CODEC_ID_ADPCM_SWF; break;
yading@11 147 case FLV_CODECID_SPEEX:
yading@11 148 acodec->codec_id = AV_CODEC_ID_SPEEX;
yading@11 149 acodec->sample_rate = 16000;
yading@11 150 break;
yading@11 151 case FLV_CODECID_MP3 : acodec->codec_id = AV_CODEC_ID_MP3 ; astream->need_parsing = AVSTREAM_PARSE_FULL; break;
yading@11 152 case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
yading@11 153 acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate
yading@11 154 acodec->codec_id = AV_CODEC_ID_NELLYMOSER;
yading@11 155 break;
yading@11 156 case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
yading@11 157 acodec->sample_rate = 16000;
yading@11 158 acodec->codec_id = AV_CODEC_ID_NELLYMOSER;
yading@11 159 break;
yading@11 160 case FLV_CODECID_NELLYMOSER:
yading@11 161 acodec->codec_id = AV_CODEC_ID_NELLYMOSER;
yading@11 162 break;
yading@11 163 case FLV_CODECID_PCM_MULAW:
yading@11 164 acodec->sample_rate = 8000;
yading@11 165 acodec->codec_id = AV_CODEC_ID_PCM_MULAW;
yading@11 166 break;
yading@11 167 case FLV_CODECID_PCM_ALAW:
yading@11 168 acodec->sample_rate = 8000;
yading@11 169 acodec->codec_id = AV_CODEC_ID_PCM_ALAW;
yading@11 170 break;
yading@11 171 default:
yading@11 172 av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
yading@11 173 acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
yading@11 174 }
yading@11 175 }
yading@11 176
yading@11 177 static int flv_same_video_codec(AVCodecContext *vcodec, int flags)
yading@11 178 {
yading@11 179 int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
yading@11 180
yading@11 181 if (!vcodec->codec_id && !vcodec->codec_tag)
yading@11 182 return 1;
yading@11 183
yading@11 184 switch (flv_codecid) {
yading@11 185 case FLV_CODECID_H263:
yading@11 186 return vcodec->codec_id == AV_CODEC_ID_FLV1;
yading@11 187 case FLV_CODECID_SCREEN:
yading@11 188 return vcodec->codec_id == AV_CODEC_ID_FLASHSV;
yading@11 189 case FLV_CODECID_SCREEN2:
yading@11 190 return vcodec->codec_id == AV_CODEC_ID_FLASHSV2;
yading@11 191 case FLV_CODECID_VP6:
yading@11 192 return vcodec->codec_id == AV_CODEC_ID_VP6F;
yading@11 193 case FLV_CODECID_VP6A:
yading@11 194 return vcodec->codec_id == AV_CODEC_ID_VP6A;
yading@11 195 case FLV_CODECID_H264:
yading@11 196 return vcodec->codec_id == AV_CODEC_ID_H264;
yading@11 197 default:
yading@11 198 return vcodec->codec_tag == flv_codecid;
yading@11 199 }
yading@11 200 }
yading@11 201
yading@11 202 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid, int read) {
yading@11 203 AVCodecContext *vcodec = vstream->codec;
yading@11 204 switch(flv_codecid) {
yading@11 205 case FLV_CODECID_H263 : vcodec->codec_id = AV_CODEC_ID_FLV1 ; break;
yading@11 206 case FLV_CODECID_REALH263: vcodec->codec_id = AV_CODEC_ID_H263 ; break; // Really mean it this time
yading@11 207 case FLV_CODECID_SCREEN: vcodec->codec_id = AV_CODEC_ID_FLASHSV; break;
yading@11 208 case FLV_CODECID_SCREEN2: vcodec->codec_id = AV_CODEC_ID_FLASHSV2; break;
yading@11 209 case FLV_CODECID_VP6 : vcodec->codec_id = AV_CODEC_ID_VP6F ;
yading@11 210 case FLV_CODECID_VP6A :
yading@11 211 if(flv_codecid == FLV_CODECID_VP6A)
yading@11 212 vcodec->codec_id = AV_CODEC_ID_VP6A;
yading@11 213 if (read) {
yading@11 214 if (vcodec->extradata_size != 1) {
yading@11 215 vcodec->extradata = av_malloc(1 + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 216 if (vcodec->extradata)
yading@11 217 vcodec->extradata_size = 1;
yading@11 218 }
yading@11 219 if (vcodec->extradata)
yading@11 220 vcodec->extradata[0] = avio_r8(s->pb);
yading@11 221 else
yading@11 222 avio_skip(s->pb, 1);
yading@11 223 }
yading@11 224 return 1; // 1 byte body size adjustment for flv_read_packet()
yading@11 225 case FLV_CODECID_H264:
yading@11 226 vcodec->codec_id = AV_CODEC_ID_H264;
yading@11 227 return 3; // not 4, reading packet type will consume one byte
yading@11 228 case FLV_CODECID_MPEG4:
yading@11 229 vcodec->codec_id = AV_CODEC_ID_MPEG4;
yading@11 230 return 3;
yading@11 231 default:
yading@11 232 av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid);
yading@11 233 vcodec->codec_tag = flv_codecid;
yading@11 234 }
yading@11 235
yading@11 236 return 0;
yading@11 237 }
yading@11 238
yading@11 239 static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) {
yading@11 240 int length = avio_rb16(ioc);
yading@11 241 if(length >= buffsize) {
yading@11 242 avio_skip(ioc, length);
yading@11 243 return -1;
yading@11 244 }
yading@11 245
yading@11 246 avio_read(ioc, buffer, length);
yading@11 247
yading@11 248 buffer[length] = '\0';
yading@11 249
yading@11 250 return length;
yading@11 251 }
yading@11 252
yading@11 253 static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream *vstream, int64_t max_pos) {
yading@11 254 FLVContext *flv = s->priv_data;
yading@11 255 unsigned int timeslen = 0, fileposlen = 0, i;
yading@11 256 char str_val[256];
yading@11 257 int64_t *times = NULL;
yading@11 258 int64_t *filepositions = NULL;
yading@11 259 int ret = AVERROR(ENOSYS);
yading@11 260 int64_t initial_pos = avio_tell(ioc);
yading@11 261
yading@11 262 if(vstream->nb_index_entries>0){
yading@11 263 av_log(s, AV_LOG_WARNING, "Skiping duplicate index\n");
yading@11 264 return 0;
yading@11 265 }
yading@11 266
yading@11 267 if (s->flags & AVFMT_FLAG_IGNIDX)
yading@11 268 return 0;
yading@11 269
yading@11 270 while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
yading@11 271 int64_t** current_array;
yading@11 272 unsigned int arraylen;
yading@11 273
yading@11 274 // Expect array object in context
yading@11 275 if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY)
yading@11 276 break;
yading@11 277
yading@11 278 arraylen = avio_rb32(ioc);
yading@11 279 if(arraylen>>28)
yading@11 280 break;
yading@11 281
yading@11 282 if (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times){
yading@11 283 current_array= &times;
yading@11 284 timeslen= arraylen;
yading@11 285 }else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) && !filepositions){
yading@11 286 current_array= &filepositions;
yading@11 287 fileposlen= arraylen;
yading@11 288 }else // unexpected metatag inside keyframes, will not use such metadata for indexing
yading@11 289 break;
yading@11 290
yading@11 291 if (!(*current_array = av_mallocz(sizeof(**current_array) * arraylen))) {
yading@11 292 ret = AVERROR(ENOMEM);
yading@11 293 goto finish;
yading@11 294 }
yading@11 295
yading@11 296 for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
yading@11 297 if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER)
yading@11 298 goto invalid;
yading@11 299 current_array[0][i] = av_int2double(avio_rb64(ioc));
yading@11 300 }
yading@11 301 if (times && filepositions) {
yading@11 302 // All done, exiting at a position allowing amf_parse_object
yading@11 303 // to finish parsing the object
yading@11 304 ret = 0;
yading@11 305 break;
yading@11 306 }
yading@11 307 }
yading@11 308
yading@11 309 if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) {
yading@11 310 for (i = 0; i < fileposlen; i++) {
yading@11 311 av_add_index_entry(vstream, filepositions[i], times[i]*1000,
yading@11 312 0, 0, AVINDEX_KEYFRAME);
yading@11 313 if (i < 2) {
yading@11 314 flv->validate_index[i].pos = filepositions[i];
yading@11 315 flv->validate_index[i].dts = times[i] * 1000;
yading@11 316 flv->validate_count = i + 1;
yading@11 317 }
yading@11 318 }
yading@11 319 } else {
yading@11 320 invalid:
yading@11 321 av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
yading@11 322 }
yading@11 323
yading@11 324 finish:
yading@11 325 av_freep(&times);
yading@11 326 av_freep(&filepositions);
yading@11 327 avio_seek(ioc, initial_pos, SEEK_SET);
yading@11 328 return ret;
yading@11 329 }
yading@11 330
yading@11 331 static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, int64_t max_pos, int depth) {
yading@11 332 AVCodecContext *acodec, *vcodec;
yading@11 333 FLVContext *flv = s->priv_data;
yading@11 334 AVIOContext *ioc;
yading@11 335 AMFDataType amf_type;
yading@11 336 char str_val[256];
yading@11 337 double num_val;
yading@11 338
yading@11 339 num_val = 0;
yading@11 340 ioc = s->pb;
yading@11 341
yading@11 342 amf_type = avio_r8(ioc);
yading@11 343
yading@11 344 switch(amf_type) {
yading@11 345 case AMF_DATA_TYPE_NUMBER:
yading@11 346 num_val = av_int2double(avio_rb64(ioc)); break;
yading@11 347 case AMF_DATA_TYPE_BOOL:
yading@11 348 num_val = avio_r8(ioc); break;
yading@11 349 case AMF_DATA_TYPE_STRING:
yading@11 350 if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0)
yading@11 351 return -1;
yading@11 352 break;
yading@11 353 case AMF_DATA_TYPE_OBJECT:
yading@11 354 if ((vstream || astream) && ioc->seekable && key && !strcmp(KEYFRAMES_TAG, key) && depth == 1)
yading@11 355 if (parse_keyframes_index(s, ioc, vstream ? vstream : astream,
yading@11 356 max_pos) < 0)
yading@11 357 av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n");
yading@11 358
yading@11 359 while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
yading@11 360 if (amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0)
yading@11 361 return -1; //if we couldn't skip, bomb out.
yading@11 362 }
yading@11 363 if(avio_r8(ioc) != AMF_END_OF_OBJECT)
yading@11 364 return -1;
yading@11 365 break;
yading@11 366 case AMF_DATA_TYPE_NULL:
yading@11 367 case AMF_DATA_TYPE_UNDEFINED:
yading@11 368 case AMF_DATA_TYPE_UNSUPPORTED:
yading@11 369 break; //these take up no additional space
yading@11 370 case AMF_DATA_TYPE_MIXEDARRAY:
yading@11 371 avio_skip(ioc, 4); //skip 32-bit max array index
yading@11 372 while(avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
yading@11 373 //this is the only case in which we would want a nested parse to not skip over the object
yading@11 374 if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0)
yading@11 375 return -1;
yading@11 376 }
yading@11 377 if(avio_r8(ioc) != AMF_END_OF_OBJECT)
yading@11 378 return -1;
yading@11 379 break;
yading@11 380 case AMF_DATA_TYPE_ARRAY: {
yading@11 381 unsigned int arraylen, i;
yading@11 382
yading@11 383 arraylen = avio_rb32(ioc);
yading@11 384 for(i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
yading@11 385 if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0)
yading@11 386 return -1; //if we couldn't skip, bomb out.
yading@11 387 }
yading@11 388 }
yading@11 389 break;
yading@11 390 case AMF_DATA_TYPE_DATE:
yading@11 391 avio_skip(ioc, 8 + 2); //timestamp (double) and UTC offset (int16)
yading@11 392 break;
yading@11 393 default: //unsupported type, we couldn't skip
yading@11 394 return -1;
yading@11 395 }
yading@11 396
yading@11 397 if(depth == 1 && key) { //only look for metadata values when we are not nested and key != NULL
yading@11 398 acodec = astream ? astream->codec : NULL;
yading@11 399 vcodec = vstream ? vstream->codec : NULL;
yading@11 400
yading@11 401 if (amf_type == AMF_DATA_TYPE_NUMBER || amf_type == AMF_DATA_TYPE_BOOL) {
yading@11 402 if (!strcmp(key, "duration"))
yading@11 403 s->duration = num_val * AV_TIME_BASE;
yading@11 404 else if (!strcmp(key, "videodatarate") && vcodec && 0 <= (int)(num_val * 1024.0))
yading@11 405 vcodec->bit_rate = num_val * 1024.0;
yading@11 406 else if (!strcmp(key, "audiodatarate") && acodec && 0 <= (int)(num_val * 1024.0))
yading@11 407 acodec->bit_rate = num_val * 1024.0;
yading@11 408 else if (!strcmp(key, "datastream")) {
yading@11 409 AVStream *st = create_stream(s, AVMEDIA_TYPE_DATA);
yading@11 410 if (!st)
yading@11 411 return AVERROR(ENOMEM);
yading@11 412 st->codec->codec_id = AV_CODEC_ID_TEXT;
yading@11 413 } else if (flv->trust_metadata) {
yading@11 414 if (!strcmp(key, "videocodecid") && vcodec) {
yading@11 415 flv_set_video_codec(s, vstream, num_val, 0);
yading@11 416 } else
yading@11 417 if (!strcmp(key, "audiocodecid") && acodec) {
yading@11 418 int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET;
yading@11 419 flv_set_audio_codec(s, astream, acodec, id);
yading@11 420 } else
yading@11 421 if (!strcmp(key, "audiosamplerate") && acodec) {
yading@11 422 acodec->sample_rate = num_val;
yading@11 423 } else if (!strcmp(key, "audiosamplesize") && acodec) {
yading@11 424 acodec->bits_per_coded_sample = num_val;
yading@11 425 } else if (!strcmp(key, "stereo") && acodec) {
yading@11 426 acodec->channels = num_val + 1;
yading@11 427 acodec->channel_layout = acodec->channels == 2 ?
yading@11 428 AV_CH_LAYOUT_STEREO :
yading@11 429 AV_CH_LAYOUT_MONO;
yading@11 430 } else
yading@11 431 if (!strcmp(key, "width") && vcodec) {
yading@11 432 vcodec->width = num_val;
yading@11 433 } else
yading@11 434 if (!strcmp(key, "height") && vcodec) {
yading@11 435 vcodec->height = num_val;
yading@11 436 }
yading@11 437 }
yading@11 438 }
yading@11 439
yading@11 440 if (amf_type == AMF_DATA_TYPE_OBJECT && s->nb_streams == 1 &&
yading@11 441 ((!acodec && !strcmp(key, "audiocodecid")) ||
yading@11 442 (!vcodec && !strcmp(key, "videocodecid"))))
yading@11 443 s->ctx_flags &= ~AVFMTCTX_NOHEADER; //If there is either audio/video missing, codecid will be an empty object
yading@11 444
yading@11 445 if (!strcmp(key, "duration") ||
yading@11 446 !strcmp(key, "filesize") ||
yading@11 447 !strcmp(key, "width") ||
yading@11 448 !strcmp(key, "height") ||
yading@11 449 !strcmp(key, "videodatarate") ||
yading@11 450 !strcmp(key, "framerate") ||
yading@11 451 !strcmp(key, "videocodecid") ||
yading@11 452 !strcmp(key, "audiodatarate") ||
yading@11 453 !strcmp(key, "audiosamplerate") ||
yading@11 454 !strcmp(key, "audiosamplesize") ||
yading@11 455 !strcmp(key, "stereo") ||
yading@11 456 !strcmp(key, "audiocodecid"))
yading@11 457 return 0;
yading@11 458
yading@11 459 if(amf_type == AMF_DATA_TYPE_BOOL) {
yading@11 460 av_strlcpy(str_val, num_val > 0 ? "true" : "false", sizeof(str_val));
yading@11 461 av_dict_set(&s->metadata, key, str_val, 0);
yading@11 462 } else if(amf_type == AMF_DATA_TYPE_NUMBER) {
yading@11 463 snprintf(str_val, sizeof(str_val), "%.f", num_val);
yading@11 464 av_dict_set(&s->metadata, key, str_val, 0);
yading@11 465 } else if (amf_type == AMF_DATA_TYPE_STRING)
yading@11 466 av_dict_set(&s->metadata, key, str_val, 0);
yading@11 467 }
yading@11 468
yading@11 469 return 0;
yading@11 470 }
yading@11 471
yading@11 472 static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
yading@11 473 AMFDataType type;
yading@11 474 AVStream *stream, *astream, *vstream, *dstream;
yading@11 475 AVIOContext *ioc;
yading@11 476 int i;
yading@11 477 char buffer[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want.
yading@11 478
yading@11 479 vstream = astream = dstream = NULL;
yading@11 480 ioc = s->pb;
yading@11 481
yading@11 482 //first object needs to be "onMetaData" string
yading@11 483 type = avio_r8(ioc);
yading@11 484 if (type != AMF_DATA_TYPE_STRING ||
yading@11 485 amf_get_string(ioc, buffer, sizeof(buffer)) < 0)
yading@11 486 return -1;
yading@11 487
yading@11 488 if (!strcmp(buffer, "onTextData"))
yading@11 489 return 1;
yading@11 490
yading@11 491 if (strcmp(buffer, "onMetaData"))
yading@11 492 return -1;
yading@11 493
yading@11 494 //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
yading@11 495 for(i = 0; i < s->nb_streams; i++) {
yading@11 496 stream = s->streams[i];
yading@11 497 if(stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) vstream = stream;
yading@11 498 else if(stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) astream = stream;
yading@11 499 else if(stream->codec->codec_type == AVMEDIA_TYPE_DATA) dstream = stream;
yading@11 500 }
yading@11 501
yading@11 502 //parse the second object (we want a mixed array)
yading@11 503 if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)
yading@11 504 return -1;
yading@11 505
yading@11 506 return 0;
yading@11 507 }
yading@11 508
yading@11 509 static int flv_read_header(AVFormatContext *s)
yading@11 510 {
yading@11 511 int offset, flags;
yading@11 512
yading@11 513 avio_skip(s->pb, 4);
yading@11 514 flags = avio_r8(s->pb);
yading@11 515 /* old flvtool cleared this field */
yading@11 516 /* FIXME: better fix needed */
yading@11 517 if (!flags) {
yading@11 518 flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO;
yading@11 519 av_log(s, AV_LOG_WARNING, "Broken FLV file, which says no streams present, this might fail\n");
yading@11 520 }
yading@11 521
yading@11 522 s->ctx_flags |= AVFMTCTX_NOHEADER;
yading@11 523
yading@11 524 if(flags & FLV_HEADER_FLAG_HASVIDEO){
yading@11 525 if(!create_stream(s, AVMEDIA_TYPE_VIDEO))
yading@11 526 return AVERROR(ENOMEM);
yading@11 527 }
yading@11 528 if(flags & FLV_HEADER_FLAG_HASAUDIO){
yading@11 529 if(!create_stream(s, AVMEDIA_TYPE_AUDIO))
yading@11 530 return AVERROR(ENOMEM);
yading@11 531 }
yading@11 532 // Flag doesn't indicate whether or not there is script-data present. Must
yading@11 533 // create that stream if it's encountered.
yading@11 534
yading@11 535 offset = avio_rb32(s->pb);
yading@11 536 avio_seek(s->pb, offset, SEEK_SET);
yading@11 537 avio_skip(s->pb, 4);
yading@11 538
yading@11 539 s->start_time = 0;
yading@11 540
yading@11 541 return 0;
yading@11 542 }
yading@11 543
yading@11 544 static int flv_read_close(AVFormatContext *s)
yading@11 545 {
yading@11 546 int i;
yading@11 547 FLVContext *flv = s->priv_data;
yading@11 548 for(i=0; i<FLV_STREAM_TYPE_NB; i++)
yading@11 549 av_freep(&flv->new_extradata[i]);
yading@11 550 return 0;
yading@11 551 }
yading@11 552
yading@11 553 static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
yading@11 554 {
yading@11 555 av_free(st->codec->extradata);
yading@11 556 st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 557 if (!st->codec->extradata)
yading@11 558 return AVERROR(ENOMEM);
yading@11 559 st->codec->extradata_size = size;
yading@11 560 avio_read(s->pb, st->codec->extradata, st->codec->extradata_size);
yading@11 561 return 0;
yading@11 562 }
yading@11 563
yading@11 564 static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
yading@11 565 int size)
yading@11 566 {
yading@11 567 av_free(flv->new_extradata[stream]);
yading@11 568 flv->new_extradata[stream] = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 569 if (!flv->new_extradata[stream])
yading@11 570 return AVERROR(ENOMEM);
yading@11 571 flv->new_extradata_size[stream] = size;
yading@11 572 avio_read(pb, flv->new_extradata[stream], size);
yading@11 573 return 0;
yading@11 574 }
yading@11 575
yading@11 576 static void clear_index_entries(AVFormatContext *s, int64_t pos)
yading@11 577 {
yading@11 578 int i, j, out;
yading@11 579 av_log(s, AV_LOG_WARNING, "Found invalid index entries, clearing the index.\n");
yading@11 580 for (i = 0; i < s->nb_streams; i++) {
yading@11 581 AVStream *st = s->streams[i];
yading@11 582 /* Remove all index entries that point to >= pos */
yading@11 583 out = 0;
yading@11 584 for (j = 0; j < st->nb_index_entries; j++) {
yading@11 585 if (st->index_entries[j].pos < pos)
yading@11 586 st->index_entries[out++] = st->index_entries[j];
yading@11 587 }
yading@11 588 st->nb_index_entries = out;
yading@11 589 }
yading@11 590 }
yading@11 591
yading@11 592
yading@11 593 static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
yading@11 594 int64_t dts, int64_t next)
yading@11 595 {
yading@11 596 int ret = AVERROR_INVALIDDATA, i;
yading@11 597 AVIOContext *pb = s->pb;
yading@11 598 AVStream *st = NULL;
yading@11 599 AMFDataType type;
yading@11 600 char buf[20];
yading@11 601 int length;
yading@11 602
yading@11 603 type = avio_r8(pb);
yading@11 604 if (type == AMF_DATA_TYPE_MIXEDARRAY)
yading@11 605 avio_seek(pb, 4, SEEK_CUR);
yading@11 606 else if (type != AMF_DATA_TYPE_OBJECT)
yading@11 607 goto out;
yading@11 608
yading@11 609 amf_get_string(pb, buf, sizeof(buf));
yading@11 610 if (strcmp(buf, "type") || avio_r8(pb) != AMF_DATA_TYPE_STRING)
yading@11 611 goto out;
yading@11 612
yading@11 613 amf_get_string(pb, buf, sizeof(buf));
yading@11 614 //FIXME parse it as codec_id
yading@11 615 amf_get_string(pb, buf, sizeof(buf));
yading@11 616 if (strcmp(buf, "text") || avio_r8(pb) != AMF_DATA_TYPE_STRING)
yading@11 617 goto out;
yading@11 618
yading@11 619 length = avio_rb16(pb);
yading@11 620 ret = av_get_packet(s->pb, pkt, length);
yading@11 621 if (ret < 0) {
yading@11 622 ret = AVERROR(EIO);
yading@11 623 goto out;
yading@11 624 }
yading@11 625
yading@11 626 for (i = 0; i < s->nb_streams; i++) {
yading@11 627 st = s->streams[i];
yading@11 628 if (st->codec->codec_type == AVMEDIA_TYPE_DATA)
yading@11 629 break;
yading@11 630 }
yading@11 631
yading@11 632 if (i == s->nb_streams) {
yading@11 633 st = create_stream(s, AVMEDIA_TYPE_DATA);
yading@11 634 if (!st)
yading@11 635 goto out;
yading@11 636 st->codec->codec_id = AV_CODEC_ID_TEXT;
yading@11 637 }
yading@11 638
yading@11 639 pkt->dts = dts;
yading@11 640 pkt->pts = dts;
yading@11 641 pkt->size = ret;
yading@11 642
yading@11 643 pkt->stream_index = st->index;
yading@11 644 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 645
yading@11 646 avio_seek(s->pb, next + 4, SEEK_SET);
yading@11 647 out:
yading@11 648 return ret;
yading@11 649 }
yading@11 650
yading@11 651 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 652 {
yading@11 653 FLVContext *flv = s->priv_data;
yading@11 654 int ret, i, type, size, flags;
yading@11 655 int stream_type=-1;
yading@11 656 int64_t next, pos;
yading@11 657 int64_t dts, pts = AV_NOPTS_VALUE;
yading@11 658 int av_uninit(channels);
yading@11 659 int av_uninit(sample_rate);
yading@11 660 AVStream *st = NULL;
yading@11 661
yading@11 662 for(;;avio_skip(s->pb, 4)){ /* pkt size is repeated at end. skip it */
yading@11 663 pos = avio_tell(s->pb);
yading@11 664 type = avio_r8(s->pb);
yading@11 665 size = avio_rb24(s->pb);
yading@11 666 dts = avio_rb24(s->pb);
yading@11 667 dts |= avio_r8(s->pb) << 24;
yading@11 668 av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts);
yading@11 669 if (url_feof(s->pb))
yading@11 670 return AVERROR_EOF;
yading@11 671 avio_skip(s->pb, 3); /* stream id, always 0 */
yading@11 672 flags = 0;
yading@11 673
yading@11 674 if (flv->validate_next < flv->validate_count) {
yading@11 675 int64_t validate_pos = flv->validate_index[flv->validate_next].pos;
yading@11 676 if (pos == validate_pos) {
yading@11 677 if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <=
yading@11 678 VALIDATE_INDEX_TS_THRESH) {
yading@11 679 flv->validate_next++;
yading@11 680 } else {
yading@11 681 clear_index_entries(s, validate_pos);
yading@11 682 flv->validate_count = 0;
yading@11 683 }
yading@11 684 } else if (pos > validate_pos) {
yading@11 685 clear_index_entries(s, validate_pos);
yading@11 686 flv->validate_count = 0;
yading@11 687 }
yading@11 688 }
yading@11 689
yading@11 690 if(size == 0)
yading@11 691 continue;
yading@11 692
yading@11 693 next= size + avio_tell(s->pb);
yading@11 694
yading@11 695 if (type == FLV_TAG_TYPE_AUDIO) {
yading@11 696 stream_type=FLV_STREAM_TYPE_AUDIO;
yading@11 697 flags = avio_r8(s->pb);
yading@11 698 size--;
yading@11 699 } else if (type == FLV_TAG_TYPE_VIDEO) {
yading@11 700 stream_type=FLV_STREAM_TYPE_VIDEO;
yading@11 701 flags = avio_r8(s->pb);
yading@11 702 size--;
yading@11 703 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD)
yading@11 704 goto skip;
yading@11 705 } else if (type == FLV_TAG_TYPE_META) {
yading@11 706 if (size > 13+1+4 && dts == 0) { // Header-type metadata stuff
yading@11 707 flv_read_metabody(s, next);
yading@11 708 goto skip;
yading@11 709 } else if (dts != 0) { // Script-data "special" metadata frames - don't skip
yading@11 710 stream_type=FLV_STREAM_TYPE_DATA;
yading@11 711 } else {
yading@11 712 goto skip;
yading@11 713 }
yading@11 714 } else {
yading@11 715 av_log(s, AV_LOG_DEBUG, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags);
yading@11 716 skip:
yading@11 717 avio_seek(s->pb, next, SEEK_SET);
yading@11 718 continue;
yading@11 719 }
yading@11 720
yading@11 721 /* skip empty data packets */
yading@11 722 if (!size)
yading@11 723 continue;
yading@11 724
yading@11 725 /* now find stream */
yading@11 726 for(i=0;i<s->nb_streams;i++) {
yading@11 727 st = s->streams[i];
yading@11 728 if (stream_type == FLV_STREAM_TYPE_AUDIO) {
yading@11 729 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
yading@11 730 (s->audio_codec_id || flv_same_audio_codec(st->codec, flags))) {
yading@11 731 break;
yading@11 732 }
yading@11 733 } else
yading@11 734 if (stream_type == FLV_STREAM_TYPE_VIDEO) {
yading@11 735 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
yading@11 736 (s->video_codec_id || flv_same_video_codec(st->codec, flags))) {
yading@11 737 break;
yading@11 738 }
yading@11 739 } else if (stream_type == FLV_STREAM_TYPE_DATA) {
yading@11 740 if (st->codec->codec_type == AVMEDIA_TYPE_DATA)
yading@11 741 break;
yading@11 742 }
yading@11 743 }
yading@11 744 if(i == s->nb_streams){
yading@11 745 static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_DATA};
yading@11 746 av_log(s, AV_LOG_WARNING, "Stream discovered after head already parsed\n");
yading@11 747 st = create_stream(s,
yading@11 748 stream_types[stream_type]);
yading@11 749 if (!st)
yading@11 750 return AVERROR(ENOMEM);
yading@11 751
yading@11 752 }
yading@11 753 av_dlog(s, "%d %X %d \n", stream_type, flags, st->discard);
yading@11 754 if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO)))
yading@11 755 ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO)))
yading@11 756 || st->discard >= AVDISCARD_ALL
yading@11 757 ){
yading@11 758 avio_seek(s->pb, next, SEEK_SET);
yading@11 759 continue;
yading@11 760 }
yading@11 761 if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO)
yading@11 762 av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
yading@11 763 break;
yading@11 764 }
yading@11 765
yading@11 766 // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
yading@11 767 if(s->pb->seekable && (!s->duration || s->duration==AV_NOPTS_VALUE) && !flv->searched_for_end){
yading@11 768 int size;
yading@11 769 const int64_t pos= avio_tell(s->pb);
yading@11 770 int64_t fsize= avio_size(s->pb);
yading@11 771 retry_duration:
yading@11 772 avio_seek(s->pb, fsize-4, SEEK_SET);
yading@11 773 size= avio_rb32(s->pb);
yading@11 774 avio_seek(s->pb, fsize-3-size, SEEK_SET);
yading@11 775 if(size == avio_rb24(s->pb) + 11){
yading@11 776 uint32_t ts = avio_rb24(s->pb);
yading@11 777 ts |= avio_r8(s->pb) << 24;
yading@11 778 if(ts)
yading@11 779 s->duration = ts * (int64_t)AV_TIME_BASE / 1000;
yading@11 780 else if (fsize >= 8 && fsize - 8 >= size){
yading@11 781 fsize -= size+4;
yading@11 782 goto retry_duration;
yading@11 783 }
yading@11 784 }
yading@11 785
yading@11 786 avio_seek(s->pb, pos, SEEK_SET);
yading@11 787 flv->searched_for_end = 1;
yading@11 788 }
yading@11 789
yading@11 790 if(stream_type == FLV_STREAM_TYPE_AUDIO){
yading@11 791 int bits_per_coded_sample;
yading@11 792 channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
yading@11 793 sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
yading@11 794 bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
yading@11 795 if(!st->codec->channels || !st->codec->sample_rate || !st->codec->bits_per_coded_sample) {
yading@11 796 st->codec->channels = channels;
yading@11 797 st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
yading@11 798 AV_CH_LAYOUT_STEREO;
yading@11 799 st->codec->sample_rate = sample_rate;
yading@11 800 st->codec->bits_per_coded_sample = bits_per_coded_sample;
yading@11 801 }
yading@11 802 if(!st->codec->codec_id){
yading@11 803 flv_set_audio_codec(s, st, st->codec, flags & FLV_AUDIO_CODECID_MASK);
yading@11 804 flv->last_sample_rate = sample_rate = st->codec->sample_rate;
yading@11 805 flv->last_channels = channels = st->codec->channels;
yading@11 806 } else {
yading@11 807 AVCodecContext ctx;
yading@11 808 ctx.sample_rate = sample_rate;
yading@11 809 flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK);
yading@11 810 sample_rate = ctx.sample_rate;
yading@11 811 }
yading@11 812 } else if(stream_type == FLV_STREAM_TYPE_VIDEO) {
yading@11 813 size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1);
yading@11 814 }
yading@11 815
yading@11 816 if (st->codec->codec_id == AV_CODEC_ID_AAC ||
yading@11 817 st->codec->codec_id == AV_CODEC_ID_H264 ||
yading@11 818 st->codec->codec_id == AV_CODEC_ID_MPEG4) {
yading@11 819 int type = avio_r8(s->pb);
yading@11 820 size--;
yading@11 821 if (st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_MPEG4) {
yading@11 822 int32_t cts = (avio_rb24(s->pb)+0xff800000)^0xff800000; // sign extension
yading@11 823 pts = dts + cts;
yading@11 824 if (cts < 0) { // dts are wrong
yading@11 825 flv->wrong_dts = 1;
yading@11 826 av_log(s, AV_LOG_WARNING, "negative cts, previous timestamps might be wrong\n");
yading@11 827 }
yading@11 828 if (flv->wrong_dts)
yading@11 829 dts = AV_NOPTS_VALUE;
yading@11 830 }
yading@11 831 if (type == 0 && (!st->codec->extradata || st->codec->codec_id == AV_CODEC_ID_AAC)) {
yading@11 832 if (st->codec->extradata) {
yading@11 833 if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
yading@11 834 return ret;
yading@11 835 ret = AVERROR(EAGAIN);
yading@11 836 goto leave;
yading@11 837 }
yading@11 838 if ((ret = flv_get_extradata(s, st, size)) < 0)
yading@11 839 return ret;
yading@11 840 if (st->codec->codec_id == AV_CODEC_ID_AAC && 0) {
yading@11 841 MPEG4AudioConfig cfg;
yading@11 842 if (avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
yading@11 843 st->codec->extradata_size * 8, 1) >= 0) {
yading@11 844 st->codec->channels = cfg.channels;
yading@11 845 st->codec->channel_layout = 0;
yading@11 846 if (cfg.ext_sample_rate)
yading@11 847 st->codec->sample_rate = cfg.ext_sample_rate;
yading@11 848 else
yading@11 849 st->codec->sample_rate = cfg.sample_rate;
yading@11 850 av_dlog(s, "mp4a config channels %d sample rate %d\n",
yading@11 851 st->codec->channels, st->codec->sample_rate);
yading@11 852 }
yading@11 853 }
yading@11 854
yading@11 855 ret = AVERROR(EAGAIN);
yading@11 856 goto leave;
yading@11 857 }
yading@11 858 }
yading@11 859
yading@11 860 /* skip empty data packets */
yading@11 861 if (!size) {
yading@11 862 ret = AVERROR(EAGAIN);
yading@11 863 goto leave;
yading@11 864 }
yading@11 865
yading@11 866 ret= av_get_packet(s->pb, pkt, size);
yading@11 867 if (ret < 0)
yading@11 868 return ret;
yading@11 869 pkt->dts = dts;
yading@11 870 pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts;
yading@11 871 pkt->stream_index = st->index;
yading@11 872 if (flv->new_extradata[stream_type]) {
yading@11 873 uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
yading@11 874 flv->new_extradata_size[stream_type]);
yading@11 875 if (side) {
yading@11 876 memcpy(side, flv->new_extradata[stream_type],
yading@11 877 flv->new_extradata_size[stream_type]);
yading@11 878 av_freep(&flv->new_extradata[stream_type]);
yading@11 879 flv->new_extradata_size[stream_type] = 0;
yading@11 880 }
yading@11 881 }
yading@11 882 if (stream_type == FLV_STREAM_TYPE_AUDIO && (sample_rate != flv->last_sample_rate ||
yading@11 883 channels != flv->last_channels)) {
yading@11 884 flv->last_sample_rate = sample_rate;
yading@11 885 flv->last_channels = channels;
yading@11 886 ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0);
yading@11 887 }
yading@11 888
yading@11 889 if ( stream_type == FLV_STREAM_TYPE_AUDIO ||
yading@11 890 ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) ||
yading@11 891 stream_type == FLV_STREAM_TYPE_DATA)
yading@11 892 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 893
yading@11 894 leave:
yading@11 895 avio_skip(s->pb, 4);
yading@11 896 return ret;
yading@11 897 }
yading@11 898
yading@11 899 static int flv_read_seek(AVFormatContext *s, int stream_index,
yading@11 900 int64_t ts, int flags)
yading@11 901 {
yading@11 902 FLVContext *flv = s->priv_data;
yading@11 903 flv->validate_count = 0;
yading@11 904 return avio_seek_time(s->pb, stream_index, ts, flags);
yading@11 905 }
yading@11 906
yading@11 907 #define OFFSET(x) offsetof(FLVContext, x)
yading@11 908 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
yading@11 909 static const AVOption options[] = {
yading@11 910 { "flv_metadata", "Allocate streams according the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD},
yading@11 911 { NULL }
yading@11 912 };
yading@11 913
yading@11 914 static const AVClass class = {
yading@11 915 .class_name = "flvdec",
yading@11 916 .item_name = av_default_item_name,
yading@11 917 .option = options,
yading@11 918 .version = LIBAVUTIL_VERSION_INT,
yading@11 919 };
yading@11 920
yading@11 921 AVInputFormat ff_flv_demuxer = {
yading@11 922 .name = "flv",
yading@11 923 .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
yading@11 924 .priv_data_size = sizeof(FLVContext),
yading@11 925 .read_probe = flv_probe,
yading@11 926 .read_header = flv_read_header,
yading@11 927 .read_packet = flv_read_packet,
yading@11 928 .read_seek = flv_read_seek,
yading@11 929 .read_close = flv_read_close,
yading@11 930 .extensions = "flv",
yading@11 931 .priv_class = &class,
yading@11 932 };