LCOV - code coverage report
Current view: top level - libavformat - flvenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 420 641 65.5 %
Date: 2017-12-18 06:23:41 Functions: 13 15 86.7 %

          Line data    Source code
       1             : /*
       2             :  * FLV muxer
       3             :  * Copyright (c) 2003 The FFmpeg Project
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include "libavutil/intreadwrite.h"
      23             : #include "libavutil/dict.h"
      24             : #include "libavutil/intfloat.h"
      25             : #include "libavutil/avassert.h"
      26             : #include "libavutil/mathematics.h"
      27             : #include "avio_internal.h"
      28             : #include "avio.h"
      29             : #include "avc.h"
      30             : #include "avformat.h"
      31             : #include "flv.h"
      32             : #include "internal.h"
      33             : #include "metadata.h"
      34             : #include "libavutil/opt.h"
      35             : #include "libavcodec/put_bits.h"
      36             : #include "libavcodec/aacenctab.h"
      37             : 
      38             : 
      39             : static const AVCodecTag flv_video_codec_ids[] = {
      40             :     { AV_CODEC_ID_FLV1,     FLV_CODECID_H263 },
      41             :     { AV_CODEC_ID_H263,     FLV_CODECID_REALH263 },
      42             :     { AV_CODEC_ID_MPEG4,    FLV_CODECID_MPEG4 },
      43             :     { AV_CODEC_ID_FLASHSV,  FLV_CODECID_SCREEN },
      44             :     { AV_CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 },
      45             :     { AV_CODEC_ID_VP6F,     FLV_CODECID_VP6 },
      46             :     { AV_CODEC_ID_VP6,      FLV_CODECID_VP6 },
      47             :     { AV_CODEC_ID_VP6A,     FLV_CODECID_VP6A },
      48             :     { AV_CODEC_ID_H264,     FLV_CODECID_H264 },
      49             :     { AV_CODEC_ID_NONE,     0 }
      50             : };
      51             : 
      52             : static const AVCodecTag flv_audio_codec_ids[] = {
      53             :     { AV_CODEC_ID_MP3,        FLV_CODECID_MP3        >> FLV_AUDIO_CODECID_OFFSET },
      54             :     { AV_CODEC_ID_PCM_U8,     FLV_CODECID_PCM        >> FLV_AUDIO_CODECID_OFFSET },
      55             :     { AV_CODEC_ID_PCM_S16BE,  FLV_CODECID_PCM        >> FLV_AUDIO_CODECID_OFFSET },
      56             :     { AV_CODEC_ID_PCM_S16LE,  FLV_CODECID_PCM_LE     >> FLV_AUDIO_CODECID_OFFSET },
      57             :     { AV_CODEC_ID_ADPCM_SWF,  FLV_CODECID_ADPCM      >> FLV_AUDIO_CODECID_OFFSET },
      58             :     { AV_CODEC_ID_AAC,        FLV_CODECID_AAC        >> FLV_AUDIO_CODECID_OFFSET },
      59             :     { AV_CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET },
      60             :     { AV_CODEC_ID_PCM_MULAW,  FLV_CODECID_PCM_MULAW  >> FLV_AUDIO_CODECID_OFFSET },
      61             :     { AV_CODEC_ID_PCM_ALAW,   FLV_CODECID_PCM_ALAW   >> FLV_AUDIO_CODECID_OFFSET },
      62             :     { AV_CODEC_ID_SPEEX,      FLV_CODECID_SPEEX      >> FLV_AUDIO_CODECID_OFFSET },
      63             :     { AV_CODEC_ID_NONE,       0 }
      64             : };
      65             : 
      66             : typedef enum {
      67             :     FLV_AAC_SEQ_HEADER_DETECT = (1 << 0),
      68             :     FLV_NO_SEQUENCE_END = (1 << 1),
      69             :     FLV_ADD_KEYFRAME_INDEX = (1 << 2),
      70             :     FLV_NO_METADATA = (1 << 3),
      71             :     FLV_NO_DURATION_FILESIZE = (1 << 4),
      72             : } FLVFlags;
      73             : 
      74             : typedef struct FLVFileposition {
      75             :     int64_t keyframe_position;
      76             :     double keyframe_timestamp;
      77             :     struct FLVFileposition *next;
      78             : } FLVFileposition;
      79             : 
      80             : typedef struct FLVContext {
      81             :     AVClass *av_class;
      82             :     int     reserved;
      83             :     int64_t duration_offset;
      84             :     int64_t filesize_offset;
      85             :     int64_t duration;
      86             :     int64_t delay;      ///< first dts delay (needed for AVC & Speex)
      87             : 
      88             :     int64_t datastart_offset;
      89             :     int64_t datasize_offset;
      90             :     int64_t datasize;
      91             :     int64_t videosize_offset;
      92             :     int64_t videosize;
      93             :     int64_t audiosize_offset;
      94             :     int64_t audiosize;
      95             : 
      96             :     int64_t metadata_size_pos;
      97             :     int64_t metadata_totalsize_pos;
      98             :     int64_t metadata_totalsize;
      99             :     int64_t keyframe_index_size;
     100             : 
     101             :     int64_t lasttimestamp_offset;
     102             :     double lasttimestamp;
     103             :     int64_t lastkeyframetimestamp_offset;
     104             :     double lastkeyframetimestamp;
     105             :     int64_t lastkeyframelocation_offset;
     106             :     int64_t lastkeyframelocation;
     107             : 
     108             :     int acurframeindex;
     109             :     int64_t keyframes_info_offset;
     110             : 
     111             :     int64_t filepositions_count;
     112             :     FLVFileposition *filepositions;
     113             :     FLVFileposition *head_filepositions;
     114             : 
     115             :     AVCodecParameters *audio_par;
     116             :     AVCodecParameters *video_par;
     117             :     double framerate;
     118             :     AVCodecParameters *data_par;
     119             : 
     120             :     int flags;
     121             : } FLVContext;
     122             : 
     123             : typedef struct FLVStreamContext {
     124             :     int64_t last_ts;    ///< last timestamp for each stream
     125             : } FLVStreamContext;
     126             : 
     127         639 : static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par)
     128             : {
     129        1278 :     int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
     130         639 :                                                    : FLV_SAMPLESSIZE_8BIT;
     131             : 
     132         639 :     if (par->codec_id == AV_CODEC_ID_AAC) // specs force these parameters
     133           0 :         return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ |
     134             :                FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
     135         639 :     else if (par->codec_id == AV_CODEC_ID_SPEEX) {
     136           0 :         if (par->sample_rate != 16000) {
     137           0 :             av_log(s, AV_LOG_ERROR,
     138             :                    "FLV only supports wideband (16kHz) Speex audio\n");
     139           0 :             return AVERROR(EINVAL);
     140             :         }
     141           0 :         if (par->channels != 1) {
     142           0 :             av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n");
     143           0 :             return AVERROR(EINVAL);
     144             :         }
     145           0 :         return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;
     146             :     } else {
     147         639 :         switch (par->sample_rate) {
     148           0 :         case 48000:
     149             :             // 48khz mp3 is stored with 44k1 samplerate identifer
     150           0 :             if (par->codec_id == AV_CODEC_ID_MP3) {
     151           0 :                 flags |= FLV_SAMPLERATE_44100HZ;
     152           0 :                 break;
     153             :             } else {
     154           0 :                 goto error;
     155             :             }
     156         262 :         case 44100:
     157         262 :             flags |= FLV_SAMPLERATE_44100HZ;
     158         262 :             break;
     159           0 :         case 22050:
     160           0 :             flags |= FLV_SAMPLERATE_22050HZ;
     161           0 :             break;
     162           0 :         case 11025:
     163           0 :             flags |= FLV_SAMPLERATE_11025HZ;
     164           0 :             break;
     165         377 :         case 16000: // nellymoser only
     166             :         case  8000: // nellymoser only
     167             :         case  5512: // not MP3
     168         377 :             if (par->codec_id != AV_CODEC_ID_MP3) {
     169         377 :                 flags |= FLV_SAMPLERATE_SPECIAL;
     170         377 :                 break;
     171             :             }
     172             :         default:
     173           0 : error:
     174           0 :             av_log(s, AV_LOG_ERROR,
     175             :                    "FLV does not support sample rate %d, "
     176             :                    "choose from (44100, 22050, 11025)\n", par->sample_rate);
     177           0 :             return AVERROR(EINVAL);
     178             :         }
     179             :     }
     180             : 
     181         639 :     if (par->channels > 1)
     182         262 :         flags |= FLV_STEREO;
     183             : 
     184         639 :     switch (par->codec_id) {
     185           0 :     case AV_CODEC_ID_MP3:
     186           0 :         flags |= FLV_CODECID_MP3    | FLV_SAMPLESSIZE_16BIT;
     187           0 :         break;
     188           0 :     case AV_CODEC_ID_PCM_U8:
     189           0 :         flags |= FLV_CODECID_PCM    | FLV_SAMPLESSIZE_8BIT;
     190           0 :         break;
     191           0 :     case AV_CODEC_ID_PCM_S16BE:
     192           0 :         flags |= FLV_CODECID_PCM    | FLV_SAMPLESSIZE_16BIT;
     193           0 :         break;
     194           0 :     case AV_CODEC_ID_PCM_S16LE:
     195           0 :         flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;
     196           0 :         break;
     197         262 :     case AV_CODEC_ID_ADPCM_SWF:
     198         262 :         flags |= FLV_CODECID_ADPCM  | FLV_SAMPLESSIZE_16BIT;
     199         262 :         break;
     200         377 :     case AV_CODEC_ID_NELLYMOSER:
     201         377 :         if (par->sample_rate == 8000)
     202           0 :             flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO  | FLV_SAMPLESSIZE_16BIT;
     203         377 :         else if (par->sample_rate == 16000)
     204         377 :             flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
     205             :         else
     206           0 :             flags |= FLV_CODECID_NELLYMOSER            | FLV_SAMPLESSIZE_16BIT;
     207         377 :         break;
     208           0 :     case AV_CODEC_ID_PCM_MULAW:
     209           0 :         flags = FLV_CODECID_PCM_MULAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
     210           0 :         break;
     211           0 :     case AV_CODEC_ID_PCM_ALAW:
     212           0 :         flags = FLV_CODECID_PCM_ALAW  | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
     213           0 :         break;
     214           0 :     case 0:
     215           0 :         flags |= par->codec_tag << 4;
     216           0 :         break;
     217           0 :     default:
     218           0 :         av_log(s, AV_LOG_ERROR, "Audio codec '%s' not compatible with FLV\n",
     219             :                avcodec_get_name(par->codec_id));
     220           0 :         return AVERROR(EINVAL);
     221             :     }
     222             : 
     223         639 :     return flags;
     224             : }
     225             : 
     226         172 : static void put_amf_string(AVIOContext *pb, const char *str)
     227             : {
     228         172 :     size_t len = strlen(str);
     229         172 :     avio_wb16(pb, len);
     230         172 :     avio_write(pb, str, len);
     231         172 : }
     232             : 
     233           0 : static void put_avc_eos_tag(AVIOContext *pb, unsigned ts)
     234             : {
     235           0 :     avio_w8(pb, FLV_TAG_TYPE_VIDEO);
     236           0 :     avio_wb24(pb, 5);               /* Tag Data Size */
     237           0 :     avio_wb24(pb, ts);              /* lower 24 bits of timestamp in ms */
     238           0 :     avio_w8(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms */
     239           0 :     avio_wb24(pb, 0);               /* StreamId = 0 */
     240           0 :     avio_w8(pb, 23);                /* ub[4] FrameType = 1, ub[4] CodecId = 7 */
     241           0 :     avio_w8(pb, 2);                 /* AVC end of sequence */
     242           0 :     avio_wb24(pb, 0);               /* Always 0 for AVC EOS. */
     243           0 :     avio_wb32(pb, 16);              /* Size of FLV tag */
     244           0 : }
     245             : 
     246         202 : static void put_amf_double(AVIOContext *pb, double d)
     247             : {
     248         202 :     avio_w8(pb, AMF_DATA_TYPE_NUMBER);
     249         202 :     avio_wb64(pb, av_double2int(d));
     250         202 : }
     251             : 
     252           1 : static void put_amf_byte(AVIOContext *pb, unsigned char abyte)
     253             : {
     254           1 :     avio_w8(pb, abyte);
     255           1 : }
     256             : 
     257           2 : static void put_amf_dword_array(AVIOContext *pb, uint32_t dw)
     258             : {
     259           2 :     avio_w8(pb, AMF_DATA_TYPE_ARRAY);
     260           2 :     avio_wb32(pb, dw);
     261           2 : }
     262             : 
     263           8 : static void put_amf_bool(AVIOContext *pb, int b)
     264             : {
     265           8 :     avio_w8(pb, AMF_DATA_TYPE_BOOL);
     266           8 :     avio_w8(pb, !!b);
     267           8 : }
     268             : 
     269          17 : static void write_metadata(AVFormatContext *s, unsigned int ts)
     270             : {
     271          17 :     AVIOContext *pb = s->pb;
     272          17 :     FLVContext *flv = s->priv_data;
     273          17 :     int write_duration_filesize = !(flv->flags & FLV_NO_DURATION_FILESIZE);
     274          17 :     int metadata_count = 0;
     275             :     int64_t metadata_count_pos;
     276          17 :     AVDictionaryEntry *tag = NULL;
     277             : 
     278             :     /* write meta_tag */
     279          17 :     avio_w8(pb, FLV_TAG_TYPE_META);            // tag type META
     280          17 :     flv->metadata_size_pos = avio_tell(pb);
     281          17 :     avio_wb24(pb, 0);           // size of data part (sum of all parts below)
     282          17 :     avio_wb24(pb, ts);          // timestamp
     283          17 :     avio_wb32(pb, 0);           // reserved
     284             : 
     285             :     /* now data of data_size size */
     286             : 
     287             :     /* first event name as a string */
     288          17 :     avio_w8(pb, AMF_DATA_TYPE_STRING);
     289          17 :     put_amf_string(pb, "onMetaData"); // 12 bytes
     290             : 
     291             :     /* mixed array (hash) with size and string/type/data tuples */
     292          17 :     avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
     293          17 :     metadata_count_pos = avio_tell(pb);
     294          51 :     metadata_count = 4 * !!flv->video_par +
     295          17 :                      5 * !!flv->audio_par +
     296          17 :                      1 * !!flv->data_par;
     297          17 :     if (write_duration_filesize) {
     298          17 :         metadata_count += 2; // +2 for duration and file size
     299             :     }
     300          17 :     avio_wb32(pb, metadata_count);
     301             : 
     302          17 :     if (write_duration_filesize) {
     303          17 :         put_amf_string(pb, "duration");
     304          17 :         flv->duration_offset = avio_tell(pb);
     305             :         // fill in the guessed duration, it'll be corrected later if incorrect
     306          17 :         put_amf_double(pb, s->duration / AV_TIME_BASE);
     307             :     }
     308             : 
     309          17 :     if (flv->video_par) {
     310          14 :         put_amf_string(pb, "width");
     311          14 :         put_amf_double(pb, flv->video_par->width);
     312             : 
     313          14 :         put_amf_string(pb, "height");
     314          14 :         put_amf_double(pb, flv->video_par->height);
     315             : 
     316          14 :         put_amf_string(pb, "videodatarate");
     317          14 :         put_amf_double(pb, flv->video_par->bit_rate / 1024.0);
     318             : 
     319          14 :         if (flv->framerate != 0.0) {
     320          14 :             put_amf_string(pb, "framerate");
     321          14 :             put_amf_double(pb, flv->framerate);
     322          14 :             metadata_count++;
     323             :         }
     324             : 
     325          14 :         put_amf_string(pb, "videocodecid");
     326          14 :         put_amf_double(pb, flv->video_par->codec_tag);
     327             :     }
     328             : 
     329          17 :     if (flv->audio_par) {
     330           3 :         put_amf_string(pb, "audiodatarate");
     331           3 :         put_amf_double(pb, flv->audio_par->bit_rate / 1024.0);
     332             : 
     333           3 :         put_amf_string(pb, "audiosamplerate");
     334           3 :         put_amf_double(pb, flv->audio_par->sample_rate);
     335             : 
     336           3 :         put_amf_string(pb, "audiosamplesize");
     337           3 :         put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
     338             : 
     339           3 :         put_amf_string(pb, "stereo");
     340           3 :         put_amf_bool(pb, flv->audio_par->channels == 2);
     341             : 
     342           3 :         put_amf_string(pb, "audiocodecid");
     343           3 :         put_amf_double(pb, flv->audio_par->codec_tag);
     344             :     }
     345             : 
     346          17 :     if (flv->data_par) {
     347           0 :         put_amf_string(pb, "datastream");
     348           0 :         put_amf_double(pb, 0.0);
     349             :     }
     350             : 
     351          17 :     ff_standardize_creation_time(s);
     352          36 :     while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
     353           2 :         if(   !strcmp(tag->key, "width")
     354           2 :             ||!strcmp(tag->key, "height")
     355           2 :             ||!strcmp(tag->key, "videodatarate")
     356           2 :             ||!strcmp(tag->key, "framerate")
     357           2 :             ||!strcmp(tag->key, "videocodecid")
     358           2 :             ||!strcmp(tag->key, "audiodatarate")
     359           2 :             ||!strcmp(tag->key, "audiosamplerate")
     360           2 :             ||!strcmp(tag->key, "audiosamplesize")
     361           2 :             ||!strcmp(tag->key, "stereo")
     362           2 :             ||!strcmp(tag->key, "audiocodecid")
     363           2 :             ||!strcmp(tag->key, "duration")
     364           2 :             ||!strcmp(tag->key, "onMetaData")
     365           2 :             ||!strcmp(tag->key, "datasize")
     366           2 :             ||!strcmp(tag->key, "lasttimestamp")
     367           2 :             ||!strcmp(tag->key, "totalframes")
     368           2 :             ||!strcmp(tag->key, "hasAudio")
     369           2 :             ||!strcmp(tag->key, "hasVideo")
     370           2 :             ||!strcmp(tag->key, "hasCuePoints")
     371           2 :             ||!strcmp(tag->key, "hasMetadata")
     372           2 :             ||!strcmp(tag->key, "hasKeyframes")
     373             :         ){
     374           0 :             av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key);
     375           0 :             continue;
     376             :         }
     377           2 :         put_amf_string(pb, tag->key);
     378           2 :         avio_w8(pb, AMF_DATA_TYPE_STRING);
     379           2 :         put_amf_string(pb, tag->value);
     380           2 :         metadata_count++;
     381             :     }
     382             : 
     383          17 :     if (write_duration_filesize) {
     384          17 :         put_amf_string(pb, "filesize");
     385          17 :         flv->filesize_offset = avio_tell(pb);
     386          17 :         put_amf_double(pb, 0); // delayed write
     387             :     }
     388             : 
     389          17 :     if (flv->flags & FLV_ADD_KEYFRAME_INDEX) {
     390           1 :         flv->acurframeindex = 0;
     391           1 :         flv->keyframe_index_size = 0;
     392             : 
     393           1 :         put_amf_string(pb, "hasVideo");
     394           1 :         put_amf_bool(pb, !!flv->video_par);
     395           1 :         metadata_count++;
     396             : 
     397           1 :         put_amf_string(pb, "hasKeyframes");
     398           1 :         put_amf_bool(pb, 1);
     399           1 :         metadata_count++;
     400             : 
     401           1 :         put_amf_string(pb, "hasAudio");
     402           1 :         put_amf_bool(pb, !!flv->audio_par);
     403           1 :         metadata_count++;
     404             : 
     405           1 :         put_amf_string(pb, "hasMetadata");
     406           1 :         put_amf_bool(pb, 1);
     407           1 :         metadata_count++;
     408             : 
     409           1 :         put_amf_string(pb, "canSeekToEnd");
     410           1 :         put_amf_bool(pb, 1);
     411           1 :         metadata_count++;
     412             : 
     413           1 :         put_amf_string(pb, "datasize");
     414           1 :         flv->datasize_offset = avio_tell(pb);
     415           1 :         flv->datasize = 0;
     416           1 :         put_amf_double(pb, flv->datasize);
     417           1 :         metadata_count++;
     418             : 
     419           1 :         put_amf_string(pb, "videosize");
     420           1 :         flv->videosize_offset = avio_tell(pb);
     421           1 :         flv->videosize = 0;
     422           1 :         put_amf_double(pb, flv->videosize);
     423           1 :         metadata_count++;
     424             : 
     425           1 :         put_amf_string(pb, "audiosize");
     426           1 :         flv->audiosize_offset = avio_tell(pb);
     427           1 :         flv->audiosize = 0;
     428           1 :         put_amf_double(pb, flv->audiosize);
     429           1 :         metadata_count++;
     430             : 
     431           1 :         put_amf_string(pb, "lasttimestamp");
     432           1 :         flv->lasttimestamp_offset = avio_tell(pb);
     433           1 :         flv->lasttimestamp = 0;
     434           1 :         put_amf_double(pb, 0);
     435           1 :         metadata_count++;
     436             : 
     437           1 :         put_amf_string(pb, "lastkeyframetimestamp");
     438           1 :         flv->lastkeyframetimestamp_offset = avio_tell(pb);
     439           1 :         flv->lastkeyframetimestamp = 0;
     440           1 :         put_amf_double(pb, 0);
     441           1 :         metadata_count++;
     442             : 
     443           1 :         put_amf_string(pb, "lastkeyframelocation");
     444           1 :         flv->lastkeyframelocation_offset = avio_tell(pb);
     445           1 :         flv->lastkeyframelocation = 0;
     446           1 :         put_amf_double(pb, 0);
     447           1 :         metadata_count++;
     448             : 
     449           1 :         put_amf_string(pb, "keyframes");
     450           1 :         put_amf_byte(pb, AMF_DATA_TYPE_OBJECT);
     451           1 :         metadata_count++;
     452             : 
     453           1 :         flv->keyframes_info_offset = avio_tell(pb);
     454             :     }
     455             : 
     456          17 :     put_amf_string(pb, "");
     457          17 :     avio_w8(pb, AMF_END_OF_OBJECT);
     458             : 
     459             :     /* write total size of tag */
     460          17 :     flv->metadata_totalsize = avio_tell(pb) - flv->metadata_size_pos - 10;
     461             : 
     462          17 :     avio_seek(pb, metadata_count_pos, SEEK_SET);
     463          17 :     avio_wb32(pb, metadata_count);
     464             : 
     465          17 :     avio_seek(pb, flv->metadata_size_pos, SEEK_SET);
     466          17 :     avio_wb24(pb, flv->metadata_totalsize);
     467          17 :     avio_skip(pb, flv->metadata_totalsize + 10 - 3);
     468          17 :     flv->metadata_totalsize_pos = avio_tell(pb);
     469          17 :     avio_wb32(pb, flv->metadata_totalsize + 11);
     470          17 : }
     471             : 
     472           0 : static int unsupported_codec(AVFormatContext *s,
     473             :                              const char* type, int codec_id)
     474             : {
     475           0 :     const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
     476           0 :     av_log(s, AV_LOG_ERROR,
     477             :            "%s codec %s not compatible with flv\n",
     478             :             type,
     479             :             desc ? desc->name : "unknown");
     480           0 :     return AVERROR(ENOSYS);
     481             : }
     482             : 
     483          17 : static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par) {
     484             :     int64_t data_size;
     485          17 :     AVIOContext *pb = s->pb;
     486          17 :     FLVContext *flv = s->priv_data;
     487             : 
     488          17 :     if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
     489          17 :             || par->codec_id == AV_CODEC_ID_MPEG4) {
     490             :         int64_t pos;
     491           0 :         avio_w8(pb,
     492           0 :                 par->codec_type == AVMEDIA_TYPE_VIDEO ?
     493             :                         FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
     494           0 :         avio_wb24(pb, 0); // size patched later
     495           0 :         avio_wb24(pb, 0); // ts
     496           0 :         avio_w8(pb, 0);   // ts ext
     497           0 :         avio_wb24(pb, 0); // streamid
     498           0 :         pos = avio_tell(pb);
     499           0 :         if (par->codec_id == AV_CODEC_ID_AAC) {
     500           0 :             avio_w8(pb, get_audio_flags(s, par));
     501           0 :             avio_w8(pb, 0); // AAC sequence header
     502             : 
     503           0 :             if (!par->extradata_size && (flv->flags & FLV_AAC_SEQ_HEADER_DETECT)) {
     504             :                 PutBitContext pbc;
     505             :                 int samplerate_index;
     506           0 :                 int channels = flv->audio_par->channels
     507           0 :                         - (flv->audio_par->channels == 8 ? 1 : 0);
     508             :                 uint8_t data[2];
     509             : 
     510           0 :                 for (samplerate_index = 0; samplerate_index < 16;
     511           0 :                         samplerate_index++)
     512           0 :                     if (flv->audio_par->sample_rate
     513           0 :                             == mpeg4audio_sample_rates[samplerate_index])
     514           0 :                         break;
     515             : 
     516           0 :                 init_put_bits(&pbc, data, sizeof(data));
     517           0 :                 put_bits(&pbc, 5, flv->audio_par->profile + 1); //profile
     518           0 :                 put_bits(&pbc, 4, samplerate_index); //sample rate index
     519           0 :                 put_bits(&pbc, 4, channels);
     520           0 :                 put_bits(&pbc, 1, 0); //frame length - 1024 samples
     521           0 :                 put_bits(&pbc, 1, 0); //does not depend on core coder
     522           0 :                 put_bits(&pbc, 1, 0); //is not extension
     523           0 :                 flush_put_bits(&pbc);
     524             : 
     525           0 :                 avio_w8(pb, data[0]);
     526           0 :                 avio_w8(pb, data[1]);
     527             : 
     528           0 :                 av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n",
     529           0 :                         data[0], data[1]);
     530             :             }
     531           0 :             avio_write(pb, par->extradata, par->extradata_size);
     532             :         } else {
     533           0 :             avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
     534           0 :             avio_w8(pb, 0); // AVC sequence header
     535           0 :             avio_wb24(pb, 0); // composition time
     536           0 :             ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
     537             :         }
     538           0 :         data_size = avio_tell(pb) - pos;
     539           0 :         avio_seek(pb, -data_size - 10, SEEK_CUR);
     540           0 :         avio_wb24(pb, data_size);
     541           0 :         avio_skip(pb, data_size + 10 - 3);
     542           0 :         avio_wb32(pb, data_size + 11); // previous tag size
     543             :     }
     544          17 : }
     545             : 
     546          20 : static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double ts, int64_t pos)
     547             : {
     548          20 :     FLVFileposition *position = av_malloc(sizeof(FLVFileposition));
     549             : 
     550          20 :     if (!position) {
     551           0 :         av_log(s, AV_LOG_WARNING, "no mem for add keyframe index!\n");
     552           0 :         return AVERROR(ENOMEM);
     553             :     }
     554             : 
     555          20 :     position->keyframe_timestamp = ts;
     556          20 :     position->keyframe_position = pos;
     557             : 
     558          20 :     if (!flv->filepositions_count) {
     559           1 :         flv->filepositions = position;
     560           1 :         flv->head_filepositions = flv->filepositions;
     561           1 :         position->next = NULL;
     562             :     } else {
     563          19 :         flv->filepositions->next = position;
     564          19 :         position->next = NULL;
     565          19 :         flv->filepositions = flv->filepositions->next;
     566             :     }
     567             : 
     568          20 :     flv->filepositions_count++;
     569             : 
     570          20 :     return 0;
     571             : }
     572             : 
     573           1 : static int shift_data(AVFormatContext *s)
     574             : {
     575           1 :     int ret = 0;
     576           1 :     int n = 0;
     577           1 :     int64_t metadata_size = 0;
     578           1 :     FLVContext *flv = s->priv_data;
     579           1 :     int64_t pos, pos_end = avio_tell(s->pb);
     580             :     uint8_t *buf, *read_buf[2];
     581           1 :     int read_buf_id = 0;
     582             :     int read_size[2];
     583             :     AVIOContext *read_pb;
     584             : 
     585           1 :     metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */
     586           1 :     metadata_size += 2 + 13; /* filepositions String */
     587           1 :     metadata_size += 2 + 5; /* times String */
     588           1 :     metadata_size += 3; /* Object end */
     589             : 
     590           1 :     flv->keyframe_index_size = metadata_size;
     591             : 
     592           1 :     if (metadata_size < 0)
     593           0 :         return metadata_size;
     594             : 
     595           1 :     buf = av_malloc_array(metadata_size, 2);
     596           1 :     if (!buf) {
     597           0 :         return AVERROR(ENOMEM);
     598             :     }
     599           1 :     read_buf[0] = buf;
     600           1 :     read_buf[1] = buf + metadata_size;
     601             : 
     602           1 :     avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET);
     603           1 :     avio_wb24(s->pb, flv->metadata_totalsize + metadata_size);
     604             : 
     605           1 :     avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET);
     606           1 :     avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size);
     607           1 :     avio_seek(s->pb, pos_end, SEEK_SET);
     608             : 
     609             :     /* Shift the data: the AVIO context of the output can only be used for
     610             :      * writing, so we re-open the same output, but for reading. It also avoids
     611             :      * a read/seek/write/seek back and forth. */
     612           1 :     avio_flush(s->pb);
     613           1 :     ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL);
     614           1 :     if (ret < 0) {
     615           0 :         av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
     616           0 :                "the second pass (add_keyframe_index)\n", s->filename);
     617           0 :         goto end;
     618             :     }
     619             : 
     620             :     /* mark the end of the shift to up to the last data we wrote, and get ready
     621             :      * for writing */
     622           1 :     pos_end = avio_tell(s->pb);
     623           1 :     avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET);
     624             : 
     625             :     /* start reading at where the keyframe index information will be placed */
     626           1 :     avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET);
     627           1 :     pos = avio_tell(read_pb);
     628             : 
     629             : #define READ_BLOCK do {                                                             \
     630             :     read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size);  \
     631             :     read_buf_id ^= 1;                                                               \
     632             : } while (0)
     633             : 
     634             :     /* shift data by chunk of at most keyframe *filepositions* and *times* size */
     635           1 :     READ_BLOCK;
     636             :     do {
     637        1595 :         READ_BLOCK;
     638        1595 :         n = read_size[read_buf_id];
     639        1595 :         if (n < 0)
     640           1 :             break;
     641        1594 :         avio_write(s->pb, read_buf[read_buf_id], n);
     642        1594 :         pos += n;
     643        1594 :     } while (pos <= pos_end);
     644             : 
     645           1 :     ff_format_io_close(s, &read_pb);
     646             : 
     647           1 : end:
     648           1 :     av_free(buf);
     649           1 :     return ret;
     650             : }
     651             : 
     652             : 
     653          17 : static int flv_write_header(AVFormatContext *s)
     654             : {
     655             :     int i;
     656          17 :     AVIOContext *pb = s->pb;
     657          17 :     FLVContext *flv = s->priv_data;
     658             : 
     659          34 :     for (i = 0; i < s->nb_streams; i++) {
     660          17 :         AVCodecParameters *par = s->streams[i]->codecpar;
     661             :         FLVStreamContext *sc;
     662          17 :         switch (par->codec_type) {
     663          14 :         case AVMEDIA_TYPE_VIDEO:
     664          28 :             if (s->streams[i]->avg_frame_rate.den &&
     665          14 :                 s->streams[i]->avg_frame_rate.num) {
     666          14 :                 flv->framerate = av_q2d(s->streams[i]->avg_frame_rate);
     667             :             }
     668          14 :             if (flv->video_par) {
     669           0 :                 av_log(s, AV_LOG_ERROR,
     670             :                        "at most one video stream is supported in flv\n");
     671           0 :                 return AVERROR(EINVAL);
     672             :             }
     673          14 :             flv->video_par = par;
     674          14 :             if (!ff_codec_get_tag(flv_video_codec_ids, par->codec_id))
     675           0 :                 return unsupported_codec(s, "Video", par->codec_id);
     676             : 
     677          28 :             if (par->codec_id == AV_CODEC_ID_MPEG4 ||
     678          14 :                 par->codec_id == AV_CODEC_ID_H263) {
     679           0 :                 int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
     680           0 :                 av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
     681             :                        "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(par->codec_id));
     682             : 
     683           0 :                 if (error) {
     684           0 :                     av_log(s, AV_LOG_ERROR,
     685             :                            "use vstrict=-1 / -strict -1 to use it anyway.\n");
     686           0 :                     return AVERROR(EINVAL);
     687             :                 }
     688          14 :             } else if (par->codec_id == AV_CODEC_ID_VP6) {
     689           0 :                 av_log(s, AV_LOG_WARNING,
     690             :                        "Muxing VP6 in flv will produce flipped video on playback.\n");
     691             :             }
     692          14 :             break;
     693           3 :         case AVMEDIA_TYPE_AUDIO:
     694           3 :             if (flv->audio_par) {
     695           0 :                 av_log(s, AV_LOG_ERROR,
     696             :                        "at most one audio stream is supported in flv\n");
     697           0 :                 return AVERROR(EINVAL);
     698             :             }
     699           3 :             flv->audio_par = par;
     700           3 :             if (get_audio_flags(s, par) < 0)
     701           0 :                 return unsupported_codec(s, "Audio", par->codec_id);
     702           3 :             if (par->codec_id == AV_CODEC_ID_PCM_S16BE)
     703           0 :                 av_log(s, AV_LOG_WARNING,
     704             :                        "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
     705           3 :             break;
     706           0 :         case AVMEDIA_TYPE_DATA:
     707           0 :             if (par->codec_id != AV_CODEC_ID_TEXT && par->codec_id != AV_CODEC_ID_NONE)
     708           0 :                 return unsupported_codec(s, "Data", par->codec_id);
     709           0 :             flv->data_par = par;
     710           0 :             break;
     711           0 :         case AVMEDIA_TYPE_SUBTITLE:
     712           0 :             if (par->codec_id != AV_CODEC_ID_TEXT) {
     713           0 :                 av_log(s, AV_LOG_ERROR, "Subtitle codec '%s' for stream %d is not compatible with FLV\n",
     714             :                        avcodec_get_name(par->codec_id), i);
     715           0 :                 return AVERROR_INVALIDDATA;
     716             :             }
     717           0 :             flv->data_par = par;
     718           0 :             break;
     719           0 :         default:
     720           0 :             av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
     721             :                    av_get_media_type_string(par->codec_type), i);
     722           0 :             return AVERROR(EINVAL);
     723             :         }
     724          17 :         avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
     725             : 
     726          17 :         sc = av_mallocz(sizeof(FLVStreamContext));
     727          17 :         if (!sc)
     728           0 :             return AVERROR(ENOMEM);
     729          17 :         s->streams[i]->priv_data = sc;
     730          17 :         sc->last_ts = -1;
     731             :     }
     732             : 
     733          17 :     flv->delay = AV_NOPTS_VALUE;
     734             : 
     735          17 :     avio_write(pb, "FLV", 3);
     736          17 :     avio_w8(pb, 1);
     737          34 :     avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par +
     738          17 :                 FLV_HEADER_FLAG_HASVIDEO * !!flv->video_par);
     739          17 :     avio_wb32(pb, 9);
     740          17 :     avio_wb32(pb, 0);
     741             : 
     742          34 :     for (i = 0; i < s->nb_streams; i++)
     743          17 :         if (s->streams[i]->codecpar->codec_tag == 5) {
     744           0 :             avio_w8(pb, 8);     // message type
     745           0 :             avio_wb24(pb, 0);   // include flags
     746           0 :             avio_wb24(pb, 0);   // time stamp
     747           0 :             avio_wb32(pb, 0);   // reserved
     748           0 :             avio_wb32(pb, 11);  // size
     749           0 :             flv->reserved = 5;
     750             :         }
     751             : 
     752          17 :     if (flv->flags & FLV_NO_METADATA) {
     753           0 :         pb->seekable = 0;
     754             :     } else {
     755          17 :         write_metadata(s, 0);
     756             :     }
     757             : 
     758          34 :     for (i = 0; i < s->nb_streams; i++) {
     759          17 :         flv_write_codec_header(s, s->streams[i]->codecpar);
     760             :     }
     761             : 
     762          17 :     flv->datastart_offset = avio_tell(pb);
     763          17 :     return 0;
     764             : }
     765             : 
     766          17 : static int flv_write_trailer(AVFormatContext *s)
     767             : {
     768             :     int64_t file_size;
     769          17 :     AVIOContext *pb = s->pb;
     770          17 :     FLVContext *flv = s->priv_data;
     771          17 :     int build_keyframes_idx = flv->flags & FLV_ADD_KEYFRAME_INDEX;
     772             :     int i, res;
     773          17 :     int64_t cur_pos = avio_tell(s->pb);
     774             : 
     775          17 :     if (build_keyframes_idx) {
     776             :         FLVFileposition *newflv_posinfo, *p;
     777             : 
     778           1 :         avio_seek(pb, flv->videosize_offset, SEEK_SET);
     779           1 :         put_amf_double(pb, flv->videosize);
     780             : 
     781           1 :         avio_seek(pb, flv->audiosize_offset, SEEK_SET);
     782           1 :         put_amf_double(pb, flv->audiosize);
     783             : 
     784           1 :         avio_seek(pb, flv->lasttimestamp_offset, SEEK_SET);
     785           1 :         put_amf_double(pb, flv->lasttimestamp);
     786             : 
     787           1 :         avio_seek(pb, flv->lastkeyframetimestamp_offset, SEEK_SET);
     788           1 :         put_amf_double(pb, flv->lastkeyframetimestamp);
     789             : 
     790           1 :         avio_seek(pb, flv->lastkeyframelocation_offset, SEEK_SET);
     791           1 :         put_amf_double(pb, flv->lastkeyframelocation + flv->keyframe_index_size);
     792           1 :         avio_seek(pb, cur_pos, SEEK_SET);
     793             : 
     794           1 :         res = shift_data(s);
     795           1 :         if (res < 0) {
     796           0 :              goto end;
     797             :         }
     798           1 :         avio_seek(pb, flv->keyframes_info_offset, SEEK_SET);
     799           1 :         put_amf_string(pb, "filepositions");
     800           1 :         put_amf_dword_array(pb, flv->filepositions_count);
     801          21 :         for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) {
     802          20 :             put_amf_double(pb, newflv_posinfo->keyframe_position + flv->keyframe_index_size);
     803             :         }
     804             : 
     805           1 :         put_amf_string(pb, "times");
     806           1 :         put_amf_dword_array(pb, flv->filepositions_count);
     807          21 :         for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) {
     808          20 :             put_amf_double(pb, newflv_posinfo->keyframe_timestamp);
     809             :         }
     810             : 
     811           1 :         newflv_posinfo = flv->head_filepositions;
     812          22 :         while (newflv_posinfo) {
     813          20 :             p = newflv_posinfo->next;
     814          20 :             if (p) {
     815          19 :                 newflv_posinfo->next = p->next;
     816          19 :                 av_free(p);
     817          19 :                 p = NULL;
     818             :             } else {
     819           1 :                 av_free(newflv_posinfo);
     820           1 :                 newflv_posinfo = NULL;
     821             :             }
     822             :         }
     823             : 
     824           1 :         put_amf_string(pb, "");
     825           1 :         avio_w8(pb, AMF_END_OF_OBJECT);
     826             : 
     827           1 :         avio_seek(pb, cur_pos + flv->keyframe_index_size, SEEK_SET);
     828             :     }
     829             : 
     830          33 : end:
     831          17 :     if (flv->flags & FLV_NO_SEQUENCE_END) {
     832           0 :         av_log(s, AV_LOG_DEBUG, "FLV no sequence end mode open\n");
     833             :     } else {
     834             :         /* Add EOS tag */
     835          34 :         for (i = 0; i < s->nb_streams; i++) {
     836          17 :             AVCodecParameters *par = s->streams[i]->codecpar;
     837          17 :             FLVStreamContext *sc = s->streams[i]->priv_data;
     838          31 :             if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
     839          28 :                     (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
     840           0 :                 put_avc_eos_tag(pb, sc->last_ts);
     841             :         }
     842             :     }
     843             : 
     844          17 :     file_size = avio_tell(pb);
     845             : 
     846          17 :     if (build_keyframes_idx) {
     847           1 :         flv->datasize = file_size - flv->datastart_offset;
     848           1 :         avio_seek(pb, flv->datasize_offset, SEEK_SET);
     849           1 :         put_amf_double(pb, flv->datasize);
     850             :     }
     851          17 :     if (!(flv->flags & FLV_NO_METADATA)) {
     852          17 :         if (!(flv->flags & FLV_NO_DURATION_FILESIZE)) {
     853             :             /* update information */
     854          17 :             if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0) {
     855           0 :                 av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n");
     856             :             } else {
     857          17 :                 put_amf_double(pb, flv->duration / (double)1000);
     858             :             }
     859          17 :             if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0) {
     860           0 :                 av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n");
     861             :             } else {
     862          17 :                 put_amf_double(pb, file_size);
     863             :             }
     864             :         }
     865             :     }
     866             : 
     867          17 :     return 0;
     868             : }
     869             : 
     870        1401 : static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     871             : {
     872        1401 :     AVIOContext *pb      = s->pb;
     873        1401 :     AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
     874        1401 :     FLVContext *flv      = s->priv_data;
     875        1401 :     FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
     876             :     unsigned ts;
     877        1401 :     int size = pkt->size;
     878        1401 :     uint8_t *data = NULL;
     879        1401 :     int flags = -1, flags_size, ret;
     880        1401 :     int64_t cur_offset = avio_tell(pb);
     881             : 
     882        2802 :     if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
     883        2802 :         par->codec_id == AV_CODEC_ID_VP6  || par->codec_id == AV_CODEC_ID_AAC)
     884           0 :         flags_size = 2;
     885        1401 :     else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
     886           0 :         flags_size = 5;
     887             :     else
     888        1401 :         flags_size = 1;
     889             : 
     890        1401 :     if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
     891        1401 :             || par->codec_id == AV_CODEC_ID_MPEG4) {
     892           0 :         int side_size = 0;
     893           0 :         uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
     894           0 :         if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
     895           0 :             av_free(par->extradata);
     896           0 :             par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
     897           0 :             if (!par->extradata) {
     898           0 :                 par->extradata_size = 0;
     899           0 :                 return AVERROR(ENOMEM);
     900             :             }
     901           0 :             memcpy(par->extradata, side, side_size);
     902           0 :             par->extradata_size = side_size;
     903           0 :             flv_write_codec_header(s, par);
     904             :         }
     905             :     }
     906             : 
     907        1401 :     if (flv->delay == AV_NOPTS_VALUE)
     908          17 :         flv->delay = -pkt->dts;
     909             : 
     910        1401 :     if (pkt->dts < -flv->delay) {
     911           0 :         av_log(s, AV_LOG_WARNING,
     912             :                "Packets are not in the proper order with respect to DTS\n");
     913           0 :         return AVERROR(EINVAL);
     914             :     }
     915             : 
     916        1401 :     ts = pkt->dts;
     917             : 
     918        1401 :     if (s->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
     919           0 :         write_metadata(s, ts);
     920           0 :         s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
     921             :     }
     922             : 
     923        2300 :     avio_write_marker(pb, av_rescale(ts, AV_TIME_BASE, 1000),
     924        2300 :                       pkt->flags & AV_PKT_FLAG_KEY && (flv->video_par ? par->codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
     925             : 
     926        1401 :     switch (par->codec_type) {
     927         765 :     case AVMEDIA_TYPE_VIDEO:
     928         765 :         avio_w8(pb, FLV_TAG_TYPE_VIDEO);
     929             : 
     930         765 :         flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id);
     931             : 
     932         765 :         flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER;
     933         765 :         break;
     934         636 :     case AVMEDIA_TYPE_AUDIO:
     935         636 :         flags = get_audio_flags(s, par);
     936             : 
     937         636 :         av_assert0(size);
     938             : 
     939         636 :         avio_w8(pb, FLV_TAG_TYPE_AUDIO);
     940         636 :         break;
     941           0 :     case AVMEDIA_TYPE_SUBTITLE:
     942             :     case AVMEDIA_TYPE_DATA:
     943           0 :         avio_w8(pb, FLV_TAG_TYPE_META);
     944           0 :         break;
     945           0 :     default:
     946           0 :         return AVERROR(EINVAL);
     947             :     }
     948             : 
     949        1401 :     if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
     950             :         /* check if extradata looks like mp4 formatted */
     951           0 :         if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
     952           0 :             if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
     953           0 :                 return ret;
     954        1401 :     } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
     955           0 :                (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
     956           0 :         if (!s->streams[pkt->stream_index]->nb_frames) {
     957           0 :         av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
     958             :                "use the audio bitstream filter 'aac_adtstoasc' to fix it "
     959             :                "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
     960           0 :         return AVERROR_INVALIDDATA;
     961             :         }
     962           0 :         av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
     963             :     }
     964             : 
     965             :     /* check Speex packet duration */
     966        1401 :     if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
     967           0 :         av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
     968             :                                   "8 frames per packet. Adobe Flash "
     969             :                                   "Player cannot handle this!\n");
     970             : 
     971        1401 :     if (sc->last_ts < ts)
     972        1401 :         sc->last_ts = ts;
     973             : 
     974        1401 :     if (size + flags_size >= 1<<24) {
     975           0 :         av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n",
     976             :                size + flags_size, 1<<24);
     977           0 :         return AVERROR(EINVAL);
     978             :     }
     979             : 
     980        1401 :     avio_wb24(pb, size + flags_size);
     981        1401 :     avio_wb24(pb, ts & 0xFFFFFF);
     982        1401 :     avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_
     983        1401 :     avio_wb24(pb, flv->reserved);
     984             : 
     985        2802 :     if (par->codec_type == AVMEDIA_TYPE_DATA ||
     986        1401 :         par->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
     987             :         int data_size;
     988           0 :         int64_t metadata_size_pos = avio_tell(pb);
     989           0 :         if (par->codec_id == AV_CODEC_ID_TEXT) {
     990             :             // legacy FFmpeg magic?
     991           0 :             avio_w8(pb, AMF_DATA_TYPE_STRING);
     992           0 :             put_amf_string(pb, "onTextData");
     993           0 :             avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
     994           0 :             avio_wb32(pb, 2);
     995           0 :             put_amf_string(pb, "type");
     996           0 :             avio_w8(pb, AMF_DATA_TYPE_STRING);
     997           0 :             put_amf_string(pb, "Text");
     998           0 :             put_amf_string(pb, "text");
     999           0 :             avio_w8(pb, AMF_DATA_TYPE_STRING);
    1000           0 :             put_amf_string(pb, pkt->data);
    1001           0 :             put_amf_string(pb, "");
    1002           0 :             avio_w8(pb, AMF_END_OF_OBJECT);
    1003             :         } else {
    1004             :             // just pass the metadata through
    1005           0 :             avio_write(pb, data ? data : pkt->data, size);
    1006             :         }
    1007             :         /* write total size of tag */
    1008           0 :         data_size = avio_tell(pb) - metadata_size_pos;
    1009           0 :         avio_seek(pb, metadata_size_pos - 10, SEEK_SET);
    1010           0 :         avio_wb24(pb, data_size);
    1011           0 :         avio_seek(pb, data_size + 10 - 3, SEEK_CUR);
    1012           0 :         avio_wb32(pb, data_size + 11);
    1013             :     } else {
    1014             :         av_assert1(flags>=0);
    1015        1401 :         avio_w8(pb,flags);
    1016        1401 :         if (par->codec_id == AV_CODEC_ID_VP6)
    1017           0 :             avio_w8(pb,0);
    1018        1401 :         if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) {
    1019           0 :             if (par->extradata_size)
    1020           0 :                 avio_w8(pb, par->extradata[0]);
    1021             :             else
    1022           0 :                 avio_w8(pb, ((FFALIGN(par->width,  16) - par->width) << 4) |
    1023           0 :                              (FFALIGN(par->height, 16) - par->height));
    1024        1401 :         } else if (par->codec_id == AV_CODEC_ID_AAC)
    1025           0 :             avio_w8(pb, 1); // AAC raw
    1026        1401 :         else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
    1027           0 :             avio_w8(pb, 1); // AVC NALU
    1028           0 :             avio_wb24(pb, pkt->pts - pkt->dts);
    1029             :         }
    1030             : 
    1031        1401 :         avio_write(pb, data ? data : pkt->data, size);
    1032             : 
    1033        1401 :         avio_wb32(pb, size + flags_size + 11); // previous tag size
    1034        1401 :         flv->duration = FFMAX(flv->duration,
    1035             :                               pkt->pts + flv->delay + pkt->duration);
    1036             :     }
    1037             : 
    1038        1401 :     if (flv->flags & FLV_ADD_KEYFRAME_INDEX) {
    1039         140 :         switch (par->codec_type) {
    1040         140 :             case AVMEDIA_TYPE_VIDEO:
    1041         140 :                 flv->videosize += (avio_tell(pb) - cur_offset);
    1042         140 :                 flv->lasttimestamp = flv->acurframeindex / flv->framerate;
    1043         140 :                 if (pkt->flags & AV_PKT_FLAG_KEY) {
    1044          20 :                     double ts = flv->acurframeindex / flv->framerate;
    1045          20 :                     int64_t pos = cur_offset;
    1046             : 
    1047          20 :                     flv->lastkeyframetimestamp = flv->acurframeindex / flv->framerate;
    1048          20 :                     flv->lastkeyframelocation = pos;
    1049          20 :                     flv_append_keyframe_info(s, flv, ts, pos);
    1050             :                 }
    1051         140 :                 flv->acurframeindex++;
    1052         140 :                 break;
    1053             : 
    1054           0 :             case AVMEDIA_TYPE_AUDIO:
    1055           0 :                 flv->audiosize += (avio_tell(pb) - cur_offset);
    1056           0 :                 break;
    1057             : 
    1058           0 :             default:
    1059           0 :                 av_log(s, AV_LOG_WARNING, "par->codec_type is type = [%d]\n", par->codec_type);
    1060           0 :                 break;
    1061             :         }
    1062        1261 :     }
    1063             : 
    1064        1401 :     av_free(data);
    1065             : 
    1066        1401 :     return pb->error;
    1067             : }
    1068             : 
    1069             : static const AVOption options[] = {
    1070             :     { "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1071             :     { "aac_seq_header_detect", "Put AAC sequence header based on stream data", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_AAC_SEQ_HEADER_DETECT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1072             :     { "no_sequence_end", "disable sequence end for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_SEQUENCE_END}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1073             :     { "no_metadata", "disable metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1074             :     { "no_duration_filesize", "disable duration and filesize zero value metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_DURATION_FILESIZE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1075             :     { "add_keyframe_index", "Add keyframe index metadata", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_ADD_KEYFRAME_INDEX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
    1076             :     { NULL },
    1077             : };
    1078             : 
    1079             : static const AVClass flv_muxer_class = {
    1080             :     .class_name = "flv muxer",
    1081             :     .item_name  = av_default_item_name,
    1082             :     .option     = options,
    1083             :     .version    = LIBAVUTIL_VERSION_INT,
    1084             : };
    1085             : 
    1086             : AVOutputFormat ff_flv_muxer = {
    1087             :     .name           = "flv",
    1088             :     .long_name      = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
    1089             :     .mime_type      = "video/x-flv",
    1090             :     .extensions     = "flv",
    1091             :     .priv_data_size = sizeof(FLVContext),
    1092             :     .audio_codec    = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,
    1093             :     .video_codec    = AV_CODEC_ID_FLV1,
    1094             :     .write_header   = flv_write_header,
    1095             :     .write_packet   = flv_write_packet,
    1096             :     .write_trailer  = flv_write_trailer,
    1097             :     .codec_tag      = (const AVCodecTag* const []) {
    1098             :                           flv_video_codec_ids, flv_audio_codec_ids, 0
    1099             :                       },
    1100             :     .flags          = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
    1101             :                       AVFMT_TS_NONSTRICT,
    1102             :     .priv_class     = &flv_muxer_class,
    1103             : };

Generated by: LCOV version 1.13