flvdec.c

Go to the documentation of this file.
00001 /*
00002  * FLV demuxer
00003  * Copyright (c) 2003 The FFmpeg Project.
00004  *
00005  * This demuxer will generate a 1 byte extradata for VP6F content.
00006  * It is composed of:
00007  *  - upper 4bits: difference between encoded width and visible width
00008  *  - lower 4bits: difference between encoded height and visible height
00009  *
00010  * This file is part of FFmpeg.
00011  *
00012  * FFmpeg is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2.1 of the License, or (at your option) any later version.
00016  *
00017  * FFmpeg is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with FFmpeg; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00025  */
00026 #include "avformat.h"
00027 #include "flv.h"
00028 
00029 static int flv_probe(AVProbeData *p)
00030 {
00031     const uint8_t *d;
00032 
00033     d = p->buf;
00034     if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5]==0) {
00035         return AVPROBE_SCORE_MAX;
00036     }
00037     return 0;
00038 }
00039 
00040 static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_codecid) {
00041     AVCodecContext *acodec = astream->codec;
00042     switch(flv_codecid) {
00043         //no distinction between S16 and S8 PCM codec flags
00044         case FLV_CODECID_PCM:
00045             acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 :
00046 #ifdef WORDS_BIGENDIAN
00047                                 CODEC_ID_PCM_S16BE;
00048 #else
00049                                 CODEC_ID_PCM_S16LE;
00050 #endif
00051             break;
00052         case FLV_CODECID_PCM_LE:
00053             acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 : CODEC_ID_PCM_S16LE; break;
00054         case FLV_CODECID_AAC  : acodec->codec_id = CODEC_ID_AAC;                                    break;
00055         case FLV_CODECID_ADPCM: acodec->codec_id = CODEC_ID_ADPCM_SWF;                              break;
00056         case FLV_CODECID_MP3  : acodec->codec_id = CODEC_ID_MP3      ; astream->need_parsing = AVSTREAM_PARSE_FULL; break;
00057         case FLV_CODECID_NELLYMOSER_8HZ_MONO:
00058             acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate
00059         case FLV_CODECID_NELLYMOSER:
00060             acodec->codec_id = CODEC_ID_NELLYMOSER;
00061             break;
00062         default:
00063             av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
00064             acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
00065     }
00066 }
00067 
00068 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid) {
00069     AVCodecContext *vcodec = vstream->codec;
00070     switch(flv_codecid) {
00071         case FLV_CODECID_H263  : vcodec->codec_id = CODEC_ID_FLV1   ; break;
00072         case FLV_CODECID_SCREEN: vcodec->codec_id = CODEC_ID_FLASHSV; break;
00073         case FLV_CODECID_VP6   : vcodec->codec_id = CODEC_ID_VP6F   ;
00074         case FLV_CODECID_VP6A  :
00075             if(flv_codecid == FLV_CODECID_VP6A)
00076                 vcodec->codec_id = CODEC_ID_VP6A;
00077             if(vcodec->extradata_size != 1) {
00078                 vcodec->extradata_size = 1;
00079                 vcodec->extradata = av_malloc(1);
00080             }
00081             vcodec->extradata[0] = get_byte(s->pb);
00082             return 1; // 1 byte body size adjustment for flv_read_packet()
00083         case FLV_CODECID_H264:
00084             vcodec->codec_id = CODEC_ID_H264;
00085             return 3; // not 4, reading packet type will consume one byte
00086         default:
00087             av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid);
00088             vcodec->codec_tag = flv_codecid;
00089     }
00090 
00091     return 0;
00092 }
00093 
00094 static int amf_get_string(ByteIOContext *ioc, char *buffer, int buffsize) {
00095     int length = get_be16(ioc);
00096     if(length >= buffsize) {
00097         url_fskip(ioc, length);
00098         return -1;
00099     }
00100 
00101     get_buffer(ioc, buffer, length);
00102 
00103     buffer[length] = '\0';
00104 
00105     return length;
00106 }
00107 
00108 static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, unsigned int max_pos, int depth) {
00109     AVCodecContext *acodec, *vcodec;
00110     ByteIOContext *ioc;
00111     AMFDataType amf_type;
00112     char str_val[256];
00113     double num_val;
00114 
00115     num_val = 0;
00116     ioc = s->pb;
00117 
00118     amf_type = get_byte(ioc);
00119 
00120     switch(amf_type) {
00121         case AMF_DATA_TYPE_NUMBER:
00122             num_val = av_int2dbl(get_be64(ioc)); break;
00123         case AMF_DATA_TYPE_BOOL:
00124             num_val = get_byte(ioc); break;
00125         case AMF_DATA_TYPE_STRING:
00126             if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0)
00127                 return -1;
00128             break;
00129         case AMF_DATA_TYPE_OBJECT: {
00130             unsigned int keylen;
00131 
00132             while(url_ftell(ioc) < max_pos - 2 && (keylen = get_be16(ioc))) {
00133                 url_fskip(ioc, keylen); //skip key string
00134                 if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0)
00135                     return -1; //if we couldn't skip, bomb out.
00136             }
00137             if(get_byte(ioc) != AMF_END_OF_OBJECT)
00138                 return -1;
00139         }
00140             break;
00141         case AMF_DATA_TYPE_NULL:
00142         case AMF_DATA_TYPE_UNDEFINED:
00143         case AMF_DATA_TYPE_UNSUPPORTED:
00144             break; //these take up no additional space
00145         case AMF_DATA_TYPE_MIXEDARRAY:
00146             url_fskip(ioc, 4); //skip 32-bit max array index
00147             while(url_ftell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
00148                 //this is the only case in which we would want a nested parse to not skip over the object
00149                 if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0)
00150                     return -1;
00151             }
00152             if(get_byte(ioc) != AMF_END_OF_OBJECT)
00153                 return -1;
00154             break;
00155         case AMF_DATA_TYPE_ARRAY: {
00156             unsigned int arraylen, i;
00157 
00158             arraylen = get_be32(ioc);
00159             for(i = 0; i < arraylen && url_ftell(ioc) < max_pos - 1; i++) {
00160                 if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0)
00161                     return -1; //if we couldn't skip, bomb out.
00162             }
00163         }
00164             break;
00165         case AMF_DATA_TYPE_DATE:
00166             url_fskip(ioc, 8 + 2); //timestamp (double) and UTC offset (int16)
00167             break;
00168         default: //unsupported type, we couldn't skip
00169             return -1;
00170     }
00171 
00172     if(depth == 1 && key) { //only look for metadata values when we are not nested and key != NULL
00173         acodec = astream ? astream->codec : NULL;
00174         vcodec = vstream ? vstream->codec : NULL;
00175 
00176         if(amf_type == AMF_DATA_TYPE_BOOL) {
00177             if(!strcmp(key, "stereo") && acodec) acodec->channels = num_val > 0 ? 2 : 1;
00178         } else if(amf_type == AMF_DATA_TYPE_NUMBER) {
00179             if(!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE;
00180 //            else if(!strcmp(key, "width")  && vcodec && num_val > 0) vcodec->width  = num_val;
00181 //            else if(!strcmp(key, "height") && vcodec && num_val > 0) vcodec->height = num_val;
00182             else if(!strcmp(key, "audiocodecid") && acodec && 0 <= (int)num_val)
00183                 flv_set_audio_codec(s, astream, (int)num_val << FLV_AUDIO_CODECID_OFFSET);
00184             else if(!strcmp(key, "videocodecid") && vcodec && 0 <= (int)num_val)
00185                 flv_set_video_codec(s, vstream, (int)num_val);
00186             else if(!strcmp(key, "audiosamplesize") && acodec && 0 < (int)num_val) {
00187                 acodec->bits_per_sample = num_val;
00188                 //we may have to rewrite a previously read codecid because FLV only marks PCM endianness.
00189                 if(num_val == 8 && (acodec->codec_id == CODEC_ID_PCM_S16BE || acodec->codec_id == CODEC_ID_PCM_S16LE))
00190                     acodec->codec_id = CODEC_ID_PCM_S8;
00191             }
00192             else if(!strcmp(key, "audiosamplerate") && acodec && num_val >= 0) {
00193                 //some tools, like FLVTool2, write consistently approximate metadata sample rates
00194                 if (!acodec->sample_rate) {
00195                     switch((int)num_val) {
00196                         case 44000: acodec->sample_rate = 44100  ; break;
00197                         case 22000: acodec->sample_rate = 22050  ; break;
00198                         case 11000: acodec->sample_rate = 11025  ; break;
00199                         case 5000 : acodec->sample_rate = 5512   ; break;
00200                         default   : acodec->sample_rate = num_val;
00201                     }
00202                 }
00203             }
00204         }
00205     }
00206 
00207     return 0;
00208 }
00209 
00210 static int flv_read_metabody(AVFormatContext *s, unsigned int next_pos) {
00211     AMFDataType type;
00212     AVStream *stream, *astream, *vstream;
00213     ByteIOContext *ioc;
00214     int i, keylen;
00215     char buffer[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want.
00216 
00217     astream = NULL;
00218     vstream = NULL;
00219     keylen = 0;
00220     ioc = s->pb;
00221 
00222     //first object needs to be "onMetaData" string
00223     type = get_byte(ioc);
00224     if(type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0 || strcmp(buffer, "onMetaData"))
00225         return -1;
00226 
00227     //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
00228     for(i = 0; i < s->nb_streams; i++) {
00229         stream = s->streams[i];
00230         if     (stream->codec->codec_type == CODEC_TYPE_AUDIO) astream = stream;
00231         else if(stream->codec->codec_type == CODEC_TYPE_VIDEO) vstream = stream;
00232     }
00233 
00234     //parse the second object (we want a mixed array)
00235     if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)
00236         return -1;
00237 
00238     return 0;
00239 }
00240 
00241 static AVStream *create_stream(AVFormatContext *s, int is_audio){
00242     AVStream *st = av_new_stream(s, is_audio);
00243     if (!st)
00244         return NULL;
00245     st->codec->codec_type = is_audio ? CODEC_TYPE_AUDIO : CODEC_TYPE_VIDEO;
00246     av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
00247     return st;
00248 }
00249 
00250 static int flv_read_header(AVFormatContext *s,
00251                            AVFormatParameters *ap)
00252 {
00253     int offset, flags;
00254 
00255     url_fskip(s->pb, 4);
00256     flags = get_byte(s->pb);
00257     /* old flvtool cleared this field */
00258     /* FIXME: better fix needed */
00259     if (!flags) {
00260         flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO;
00261         av_log(s, AV_LOG_WARNING, "Broken FLV file, which says no streams present, this might fail\n");
00262     }
00263 
00264     if((flags & (FLV_HEADER_FLAG_HASVIDEO|FLV_HEADER_FLAG_HASAUDIO))
00265              != (FLV_HEADER_FLAG_HASVIDEO|FLV_HEADER_FLAG_HASAUDIO))
00266         s->ctx_flags |= AVFMTCTX_NOHEADER;
00267 
00268     if(flags & FLV_HEADER_FLAG_HASVIDEO){
00269         if(!create_stream(s, 0))
00270             return AVERROR(ENOMEM);
00271     }
00272     if(flags & FLV_HEADER_FLAG_HASAUDIO){
00273         if(!create_stream(s, 1))
00274             return AVERROR(ENOMEM);
00275     }
00276 
00277     offset = get_be32(s->pb);
00278     url_fseek(s->pb, offset, SEEK_SET);
00279 
00280     s->start_time = 0;
00281 
00282     return 0;
00283 }
00284 
00285 static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
00286 {
00287     av_free(st->codec->extradata);
00288     st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
00289     if (!st->codec->extradata)
00290         return AVERROR(ENOMEM);
00291     st->codec->extradata_size = size;
00292     get_buffer(s->pb, st->codec->extradata, st->codec->extradata_size);
00293     return 0;
00294 }
00295 
00296 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
00297 {
00298     int ret, i, type, size, flags, is_audio, next, pos;
00299     unsigned dts;
00300     AVStream *st = NULL;
00301 
00302  retry:
00303  for(;;){
00304     pos = url_ftell(s->pb);
00305     url_fskip(s->pb, 4); /* size of previous packet */
00306     type = get_byte(s->pb);
00307     size = get_be24(s->pb);
00308     dts = get_be24(s->pb);
00309     dts |= get_byte(s->pb) << 24;
00310 //    av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, dts:%d\n", type, size, dts);
00311     if (url_feof(s->pb))
00312         return AVERROR(EIO);
00313     url_fskip(s->pb, 3); /* stream id, always 0 */
00314     flags = 0;
00315 
00316     if(size == 0)
00317         continue;
00318 
00319     next= size + url_ftell(s->pb);
00320 
00321     if (type == FLV_TAG_TYPE_AUDIO) {
00322         is_audio=1;
00323         flags = get_byte(s->pb);
00324     } else if (type == FLV_TAG_TYPE_VIDEO) {
00325         is_audio=0;
00326         flags = get_byte(s->pb);
00327     } else {
00328         if (type == FLV_TAG_TYPE_META && size > 13+1+4)
00329             flv_read_metabody(s, next);
00330         else /* skip packet */
00331             av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags);
00332         url_fseek(s->pb, next, SEEK_SET);
00333         continue;
00334     }
00335 
00336     /* now find stream */
00337     for(i=0;i<s->nb_streams;i++) {
00338         st = s->streams[i];
00339         if (st->id == is_audio)
00340             break;
00341     }
00342     if(i == s->nb_streams){
00343         av_log(NULL, AV_LOG_ERROR, "invalid stream\n");
00344         st= create_stream(s, is_audio);
00345         s->ctx_flags &= ~AVFMTCTX_NOHEADER;
00346     }
00347 //    av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard);
00348     if(  (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||         is_audio))
00349        ||(st->discard >= AVDISCARD_BIDIR  &&  ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio))
00350        || st->discard >= AVDISCARD_ALL
00351        ){
00352         url_fseek(s->pb, next, SEEK_SET);
00353         continue;
00354     }
00355     if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)
00356         av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
00357     break;
00358  }
00359 
00360     // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
00361     if(!url_is_streamed(s->pb) && s->duration==AV_NOPTS_VALUE){
00362         int size;
00363         const int pos= url_ftell(s->pb);
00364         const int fsize= url_fsize(s->pb);
00365         url_fseek(s->pb, fsize-4, SEEK_SET);
00366         size= get_be32(s->pb);
00367         url_fseek(s->pb, fsize-3-size, SEEK_SET);
00368         if(size == get_be24(s->pb) + 11){
00369             s->duration= get_be24(s->pb) * (int64_t)AV_TIME_BASE / 1000;
00370         }
00371         url_fseek(s->pb, pos, SEEK_SET);
00372     }
00373 
00374     if(is_audio){
00375         if(!st->codec->sample_rate || !st->codec->bits_per_sample || (!st->codec->codec_id && !st->codec->codec_tag)) {
00376             st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
00377             if((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_NELLYMOSER_8HZ_MONO)
00378                 st->codec->sample_rate= 8000;
00379             else
00380                 st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
00381             st->codec->bits_per_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
00382             flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK);
00383         }
00384     }else{
00385         size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK);
00386     }
00387 
00388     if (st->codec->codec_id == CODEC_ID_AAC ||
00389         st->codec->codec_id == CODEC_ID_H264) {
00390         int type = get_byte(s->pb);
00391         size--;
00392         if (st->codec->codec_id == CODEC_ID_H264) {
00393             // cts offset ignored because it might to be signed
00394             // and would cause pts < dts
00395             get_be24(s->pb);
00396         }
00397         if (type == 0) {
00398             if ((ret = flv_get_extradata(s, st, size - 1)) < 0)
00399                 return ret;
00400             goto retry;
00401         }
00402     }
00403 
00404     ret= av_get_packet(s->pb, pkt, size - 1);
00405     if (ret <= 0) {
00406         return AVERROR(EIO);
00407     }
00408     /* note: we need to modify the packet size here to handle the last
00409        packet */
00410     pkt->size = ret;
00411     pkt->dts = dts;
00412     pkt->stream_index = st->index;
00413 
00414     if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY))
00415         pkt->flags |= PKT_FLAG_KEY;
00416 
00417     return ret;
00418 }
00419 
00420 AVInputFormat flv_demuxer = {
00421     "flv",
00422     NULL_IF_CONFIG_SMALL("FLV format"),
00423     0,
00424     flv_probe,
00425     flv_read_header,
00426     flv_read_packet,
00427     .extensions = "flv",
00428     .value = CODEC_ID_FLV1,
00429 };

Generated on Fri Jan 9 14:44:29 2009 for libextractor by  doxygen 1.5.1