LCOV - code coverage report
Current view: top level - src/libavformat - asfenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 384 555 69.2 %
Date: 2017-05-26 21:11:57 Functions: 14 18 77.8 %

          Line data    Source code
       1             : /*
       2             :  * ASF muxer
       3             :  * Copyright (c) 2000, 2001 Fabrice Bellard
       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/avassert.h"
      23             : #include "libavutil/dict.h"
      24             : #include "libavutil/mathematics.h"
      25             : #include "libavutil/parseutils.h"
      26             : #include "libavutil/opt.h"
      27             : #include "avformat.h"
      28             : #include "avlanguage.h"
      29             : #include "avio_internal.h"
      30             : #include "internal.h"
      31             : #include "riff.h"
      32             : #include "asf.h"
      33             : 
      34             : #define ASF_INDEXED_INTERVAL    10000000
      35             : #define ASF_INDEX_BLOCK         (1<<9)
      36             : #define ASF_PAYLOADS_PER_PACKET 63
      37             : 
      38             : #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
      39             : #define ASF_PACKET_ERROR_CORRECTION_FLAGS          \
      40             :     (ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT |    \
      41             :      ASF_PACKET_ERROR_CORRECTION_DATA_SIZE)
      42             : 
      43             : #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
      44             : #   define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
      45             : #else
      46             : #   define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
      47             : #endif
      48             : 
      49             : #define ASF_PPI_PROPERTY_FLAGS                                       \
      50             :     (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE           |    \
      51             :      ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD |    \
      52             :      ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE       |    \
      53             :      ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE)
      54             : 
      55             : #define ASF_PPI_LENGTH_TYPE_FLAGS 0
      56             : 
      57             : #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
      58             : 
      59             : #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
      60             : #   define ASF_PPI_SEQUENCE_FIELD_SIZE 1
      61             : #endif
      62             : #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
      63             : #   define ASF_PPI_SEQUENCE_FIELD_SIZE 2
      64             : #endif
      65             : #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
      66             : #   define ASF_PPI_SEQUENCE_FIELD_SIZE 4
      67             : #endif
      68             : #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
      69             : #   define ASF_PPI_SEQUENCE_FIELD_SIZE 0
      70             : #endif
      71             : 
      72             : #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
      73             : #   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
      74             : #endif
      75             : #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
      76             : #   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
      77             : #endif
      78             : #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
      79             : #   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
      80             : #endif
      81             : #ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
      82             : #   define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
      83             : #endif
      84             : 
      85             : #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
      86             : #   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
      87             : #endif
      88             : #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
      89             : #   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
      90             : #endif
      91             : #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
      92             : #   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
      93             : #endif
      94             : #ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
      95             : #   define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
      96             : #endif
      97             : 
      98             : #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
      99             : #   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
     100             : #endif
     101             : #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
     102             : #   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
     103             : #endif
     104             : #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
     105             : #   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
     106             : #endif
     107             : #ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
     108             : #   define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
     109             : #endif
     110             : 
     111             : #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
     112             : #   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
     113             : #endif
     114             : #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
     115             : #   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
     116             : #endif
     117             : #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
     118             : #   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
     119             : #endif
     120             : #ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
     121             : #   define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
     122             : #endif
     123             : 
     124             : #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
     125             : #   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
     126             : #endif
     127             : #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
     128             : #   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
     129             : #endif
     130             : #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
     131             : #   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
     132             : #endif
     133             : #ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
     134             : #   define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
     135             : #endif
     136             : 
     137             : #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
     138             : #   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
     139             : #endif
     140             : #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
     141             : #   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
     142             : #endif
     143             : #ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
     144             : #   define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
     145             : #endif
     146             : 
     147             : #define PACKET_HEADER_MIN_SIZE \
     148             :     (ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE +       \
     149             :      ASF_PACKET_ERROR_CORRECTION_DATA_SIZE +              \
     150             :      1 +        /* Length Type Flags */                   \
     151             :      1 +        /* Property Flags */                      \
     152             :      ASF_PPI_PACKET_LENGTH_FIELD_SIZE +                   \
     153             :      ASF_PPI_SEQUENCE_FIELD_SIZE +                        \
     154             :      ASF_PPI_PADDING_LENGTH_FIELD_SIZE +                  \
     155             :      4 +        /* Send Time Field */                     \
     156             :      2)         /* Duration Field */
     157             : 
     158             : // Replicated Data shall be at least 8 bytes long.
     159             : #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
     160             : 
     161             : #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD                \
     162             :     (1 +     /* Stream Number */                          \
     163             :      ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE +         \
     164             :      ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE +    \
     165             :      ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE +      \
     166             :      ASF_PAYLOAD_REPLICATED_DATA_LENGTH)
     167             : 
     168             : #define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS             \
     169             :     (1 +        /* Stream Number */                       \
     170             :      ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE +         \
     171             :      ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE +    \
     172             :      ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE +      \
     173             :      ASF_PAYLOAD_REPLICATED_DATA_LENGTH +                 \
     174             :      ASF_PAYLOAD_LENGTH_FIELD_SIZE)
     175             : 
     176             : #define SINGLE_PAYLOAD_HEADERS                            \
     177             :     (PACKET_HEADER_MIN_SIZE +                             \
     178             :      PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD)
     179             : 
     180             : #define MULTI_PAYLOAD_HEADERS                             \
     181             :     (PACKET_HEADER_MIN_SIZE +                             \
     182             :      1 +         /* Payload Flags */                      \
     183             :      2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS)
     184             : 
     185             : #define DATA_HEADER_SIZE 50
     186             : 
     187             : #define PACKET_SIZE_MAX 65536
     188             : #define PACKET_SIZE_MIN 100
     189             : 
     190             : typedef struct ASFPayload {
     191             :     uint8_t type;
     192             :     uint16_t size;
     193             : } ASFPayload;
     194             : 
     195             : typedef struct ASFStream {
     196             :     int num;
     197             :     unsigned char seq;
     198             :     /* use for reading */
     199             :     AVPacket pkt;
     200             :     int frag_offset;
     201             :     int packet_obj_size;
     202             :     int timestamp;
     203             :     int64_t duration;
     204             :     int skip_to_key;
     205             :     int pkt_clean;
     206             : 
     207             :     int ds_span;                /* descrambling  */
     208             :     int ds_packet_size;
     209             :     int ds_chunk_size;
     210             : 
     211             :     int64_t packet_pos;
     212             : 
     213             :     uint16_t stream_language_index;
     214             : 
     215             :     int      palette_changed;
     216             :     uint32_t palette[256];
     217             : 
     218             :     int payload_ext_ct;
     219             :     ASFPayload payload[8];
     220             : } ASFStream;
     221             : 
     222             : typedef struct ASFContext {
     223             :     AVClass *av_class;
     224             :     uint32_t seqno;
     225             :     int is_streamed;
     226             :     ASFStream streams[128];              ///< it's max number and it's not that big
     227             :     const char *languages[128];
     228             :     int nb_languages;
     229             :     int64_t creation_time;
     230             :     /* non-streamed additional info */
     231             :     uint64_t nb_packets;                 ///< how many packets are there in the file, invalid if broadcasting
     232             :     int64_t duration;                    ///< in 100ns units
     233             :     /* packet filling */
     234             :     unsigned char multi_payloads_present;
     235             :     int packet_size_left;
     236             :     int64_t packet_timestamp_start;
     237             :     int64_t packet_timestamp_end;
     238             :     unsigned int packet_nb_payloads;
     239             :     uint8_t packet_buf[PACKET_SIZE_MAX];
     240             :     AVIOContext pb;
     241             :     /* only for reading */
     242             :     uint64_t data_offset;                ///< beginning of the first data packet
     243             : 
     244             :     ASFIndex *index_ptr;
     245             :     uint32_t nb_index_memory_alloc;
     246             :     uint16_t maximum_packet;
     247             :     uint32_t next_packet_number;
     248             :     uint16_t next_packet_count;
     249             :     uint64_t next_packet_offset;
     250             :     int      next_start_sec;
     251             :     int      end_sec;
     252             :     int      packet_size;
     253             : } ASFContext;
     254             : 
     255             : static const AVCodecTag codec_asf_bmp_tags[] = {
     256             :     { AV_CODEC_ID_MPEG4,     MKTAG('M', '4', 'S', '2') },
     257             :     { AV_CODEC_ID_MPEG4,     MKTAG('M', 'P', '4', 'S') },
     258             :     { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
     259             :     { AV_CODEC_ID_NONE,      0 },
     260             : };
     261             : 
     262             : #define PREROLL_TIME 3100
     263             : 
     264          12 : static void put_str16(AVIOContext *s, const char *tag)
     265             : {
     266             :     int len;
     267             :     uint8_t *pb;
     268             :     AVIOContext *dyn_buf;
     269          12 :     if (avio_open_dyn_buf(&dyn_buf) < 0)
     270           0 :         return;
     271             : 
     272          12 :     avio_put_str16le(dyn_buf, tag);
     273          12 :     len = avio_close_dyn_buf(dyn_buf, &pb);
     274          12 :     avio_wl16(s, len);
     275          12 :     avio_write(s, pb, len);
     276          12 :     av_freep(&pb);
     277             : }
     278             : 
     279          34 : static int64_t put_header(AVIOContext *pb, const ff_asf_guid *g)
     280             : {
     281             :     int64_t pos;
     282             : 
     283          34 :     pos = avio_tell(pb);
     284          34 :     ff_put_guid(pb, g);
     285          34 :     avio_wl64(pb, 24);
     286          34 :     return pos;
     287             : }
     288             : 
     289             : /* update header size */
     290          34 : static void end_header(AVIOContext *pb, int64_t pos)
     291             : {
     292             :     int64_t pos1;
     293             : 
     294          34 :     pos1 = avio_tell(pb);
     295          34 :     avio_seek(pb, pos + 16, SEEK_SET);
     296          34 :     avio_wl64(pb, pos1 - pos);
     297          34 :     avio_seek(pb, pos1, SEEK_SET);
     298          34 : }
     299             : 
     300             : /* write an asf chunk (only used in streaming case) */
     301           0 : static void put_chunk(AVFormatContext *s, int type,
     302             :                       int payload_length, int flags)
     303             : {
     304           0 :     ASFContext *asf = s->priv_data;
     305           0 :     AVIOContext *pb = s->pb;
     306             :     int length;
     307             : 
     308           0 :     length = payload_length + 8;
     309           0 :     avio_wl16(pb, type);
     310           0 :     avio_wl16(pb, length);      // size
     311           0 :     avio_wl32(pb, asf->seqno);  // sequence number
     312           0 :     avio_wl16(pb, flags);       // unknown bytes
     313           0 :     avio_wl16(pb, length);      // size_confirm
     314           0 :     asf->seqno++;
     315           0 : }
     316             : 
     317             : /* convert from av time to windows time */
     318           6 : static int64_t unix_to_file_time(int64_t ti)
     319             : {
     320             :     int64_t t;
     321             : 
     322           6 :     t  = ti * INT64_C(10);
     323           6 :     t += INT64_C(116444736000000000);
     324           6 :     return t;
     325             : }
     326             : 
     327           0 : static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset)
     328             : {
     329             :     int i;
     330           0 :     int32_t send_time = 0;
     331           0 :     *offset = asf->data_offset + DATA_HEADER_SIZE;
     332           0 :     for (i = 0; i < asf->next_start_sec; i++) {
     333           0 :         if (pres_time <= asf->index_ptr[i].send_time)
     334           0 :             break;
     335           0 :         send_time = asf->index_ptr[i].send_time;
     336           0 :         *offset   = asf->index_ptr[i].offset;
     337             :     }
     338             : 
     339           0 :     return send_time / 10000;
     340             : }
     341             : 
     342           0 : static int asf_write_markers(AVFormatContext *s)
     343             : {
     344           0 :     ASFContext *asf = s->priv_data;
     345           0 :     AVIOContext *pb = s->pb;
     346             :     int i;
     347           0 :     AVRational scale = {1, 10000000};
     348           0 :     int64_t hpos = put_header(pb, &ff_asf_marker_header);
     349             : 
     350           0 :     ff_put_guid(pb, &ff_asf_reserved_4);// ASF spec mandates this reserved value
     351           0 :     avio_wl32(pb, s->nb_chapters);     // markers count
     352           0 :     avio_wl16(pb, 0);                  // ASF spec mandates 0 for this
     353           0 :     avio_wl16(pb, 0);                  // name length 0, no name given
     354             : 
     355           0 :     for (i = 0; i < s->nb_chapters; i++) {
     356           0 :         AVChapter *c = s->chapters[i];
     357           0 :         AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0);
     358           0 :         int64_t pres_time = av_rescale_q(c->start, c->time_base, scale);
     359             :         uint64_t offset;
     360           0 :         int32_t send_time = get_send_time(asf, pres_time, &offset);
     361           0 :         int len = 0;
     362             :         uint8_t *buf;
     363             :         AVIOContext *dyn_buf;
     364           0 :         if (t) {
     365           0 :             if (avio_open_dyn_buf(&dyn_buf) < 0)
     366           0 :                 return AVERROR(ENOMEM);
     367           0 :             avio_put_str16le(dyn_buf, t->value);
     368           0 :             len = avio_close_dyn_buf(dyn_buf, &buf);
     369             :         }
     370           0 :         avio_wl64(pb, offset);            // offset of the packet with send_time
     371           0 :         avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time
     372           0 :         avio_wl16(pb, 12 + len);          // entry length
     373           0 :         avio_wl32(pb, send_time);         // send time
     374           0 :         avio_wl32(pb, 0);                 // flags, should be 0
     375           0 :         avio_wl32(pb, len / 2);           // marker desc length in WCHARS!
     376           0 :         if (t) {
     377           0 :             avio_write(pb, buf, len);     // marker desc
     378           0 :             av_freep(&buf);
     379             :         }
     380             :     }
     381           0 :     end_header(pb, hpos);
     382           0 :     return 0;
     383             : }
     384             : 
     385             : /* write the header (used two times if non streamed) */
     386           6 : static int asf_write_header1(AVFormatContext *s, int64_t file_size,
     387             :                              int64_t data_chunk_size)
     388             : {
     389           6 :     ASFContext *asf = s->priv_data;
     390           6 :     AVIOContext *pb = s->pb;
     391             :     AVDictionaryEntry *tags[5];
     392             :     int header_size, n, extra_size, extra_size2, wav_extra_size;
     393           6 :     int has_title, has_aspect_ratio = 0;
     394             :     int metadata_count;
     395             :     AVCodecParameters *par;
     396             :     int64_t header_offset, cur_pos, hpos;
     397             :     int bit_rate;
     398             :     int64_t duration;
     399           6 :     int audio_language_counts[128] = { 0 };
     400             : 
     401           6 :     ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
     402             : 
     403           6 :     tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
     404           6 :     tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
     405           6 :     tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
     406           6 :     tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
     407           6 :     tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);
     408             : 
     409           6 :     duration       = asf->duration + PREROLL_TIME * 10000;
     410           6 :     has_title      = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
     411             : 
     412           6 :     if (!file_size) {
     413           3 :         if (ff_parse_creation_time_metadata(s, &asf->creation_time, 0) != 0)
     414           0 :             av_dict_set(&s->metadata, "creation_time", NULL, 0);
     415             :     }
     416             : 
     417           6 :     metadata_count = av_dict_count(s->metadata);
     418             : 
     419           6 :     bit_rate = 0;
     420          14 :     for (n = 0; n < s->nb_streams; n++) {
     421             :         AVDictionaryEntry *entry;
     422           8 :         par = s->streams[n]->codecpar;
     423             : 
     424           8 :         avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
     425             : 
     426           8 :         bit_rate += par->bit_rate;
     427           8 :         if (   par->codec_type == AVMEDIA_TYPE_VIDEO
     428           2 :             && par->sample_aspect_ratio.num > 0
     429           0 :             && par->sample_aspect_ratio.den > 0)
     430           0 :             has_aspect_ratio++;
     431             : 
     432           8 :         entry = av_dict_get(s->streams[n]->metadata, "language", NULL, 0);
     433           8 :         if (entry) {
     434           0 :             const char *iso6391lang = ff_convert_lang_to(entry->value, AV_LANG_ISO639_1);
     435           0 :             if (iso6391lang) {
     436             :                 int i;
     437           0 :                 for (i = 0; i < asf->nb_languages; i++) {
     438           0 :                     if (!strcmp(asf->languages[i], iso6391lang)) {
     439           0 :                         asf->streams[n].stream_language_index = i;
     440           0 :                         break;
     441             :                     }
     442             :                 }
     443           0 :                 if (i >= asf->nb_languages) {
     444           0 :                     asf->languages[asf->nb_languages] = iso6391lang;
     445           0 :                     asf->streams[n].stream_language_index = asf->nb_languages;
     446           0 :                     asf->nb_languages++;
     447             :                 }
     448           0 :                 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
     449           0 :                     audio_language_counts[asf->streams[n].stream_language_index]++;
     450             :             }
     451             :         } else {
     452           8 :             asf->streams[n].stream_language_index = 128;
     453             :         }
     454             :     }
     455             : 
     456           6 :     if (asf->is_streamed) {
     457           0 :         put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
     458             :     }
     459             : 
     460           6 :     ff_put_guid(pb, &ff_asf_header);
     461           6 :     avio_wl64(pb, -1); /* header length, will be patched after */
     462           6 :     avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
     463           6 :     avio_w8(pb, 1); /* ??? */
     464           6 :     avio_w8(pb, 2); /* ??? */
     465             : 
     466             :     /* file header */
     467           6 :     header_offset = avio_tell(pb);
     468           6 :     hpos          = put_header(pb, &ff_asf_file_header);
     469           6 :     ff_put_guid(pb, &ff_asf_my_guid);
     470           6 :     avio_wl64(pb, file_size);
     471           6 :     avio_wl64(pb, unix_to_file_time(asf->creation_time));
     472           6 :     avio_wl64(pb, asf->nb_packets); /* number of packets */
     473           6 :     avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
     474           6 :     avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
     475           6 :     avio_wl64(pb, PREROLL_TIME); /* start time stamp */
     476           6 :     avio_wl32(pb, (asf->is_streamed || !(pb->seekable & AVIO_SEEKABLE_NORMAL)) ? 3 : 2);  /* ??? */
     477           6 :     avio_wl32(pb, s->packet_size); /* packet size */
     478           6 :     avio_wl32(pb, s->packet_size); /* packet size */
     479           6 :     avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
     480           6 :     end_header(pb, hpos);
     481             : 
     482             :     /* header_extension */
     483           6 :     hpos = put_header(pb, &ff_asf_head1_guid);
     484           6 :     ff_put_guid(pb, &ff_asf_head2_guid);
     485           6 :     avio_wl16(pb, 6);
     486           6 :     avio_wl32(pb, 0); /* length, to be filled later */
     487           6 :     if (asf->nb_languages) {
     488             :         int64_t hpos2;
     489             :         int i;
     490           0 :         int nb_audio_languages = 0;
     491             : 
     492           0 :         hpos2 = put_header(pb, &ff_asf_language_guid);
     493           0 :         avio_wl16(pb, asf->nb_languages);
     494           0 :         for (i = 0; i < asf->nb_languages; i++) {
     495           0 :             avio_w8(pb, 6);
     496           0 :             avio_put_str16le(pb, asf->languages[i]);
     497             :         }
     498           0 :         end_header(pb, hpos2);
     499             : 
     500           0 :         for (i = 0; i < asf->nb_languages; i++)
     501           0 :             if (audio_language_counts[i])
     502           0 :                 nb_audio_languages++;
     503             : 
     504           0 :         if (nb_audio_languages > 1) {
     505           0 :             hpos2 = put_header(pb, &ff_asf_group_mutual_exclusion_object);
     506           0 :             ff_put_guid(pb, &ff_asf_mutex_language);
     507           0 :             avio_wl16(pb, nb_audio_languages);
     508           0 :             for (i = 0; i < asf->nb_languages; i++) {
     509           0 :                 if (audio_language_counts[i]) {
     510           0 :                     avio_wl16(pb, audio_language_counts[i]);
     511           0 :                     for (n = 0; n < s->nb_streams; n++)
     512           0 :                         if (asf->streams[n].stream_language_index == i && s->streams[n]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
     513           0 :                             avio_wl16(pb, n + 1);
     514             :                 }
     515             :             }
     516           0 :             end_header(pb, hpos2);
     517             :         }
     518             : 
     519           0 :         for (n = 0; n < s->nb_streams; n++) {
     520             :             int64_t es_pos;
     521           0 :             if (asf->streams[n].stream_language_index > 127)
     522           0 :                 continue;
     523           0 :             es_pos = put_header(pb, &ff_asf_extended_stream_properties_object);
     524           0 :             avio_wl64(pb, 0); /* start time */
     525           0 :             avio_wl64(pb, 0); /* end time */
     526           0 :             avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* data bitrate bps */
     527           0 :             avio_wl32(pb, 5000); /* buffer size ms */
     528           0 :             avio_wl32(pb, 0); /* initial buffer fullness */
     529           0 :             avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* peak data bitrate */
     530           0 :             avio_wl32(pb, 5000); /* maximum buffer size ms */
     531           0 :             avio_wl32(pb, 0); /* max initial buffer fullness */
     532           0 :             avio_wl32(pb, 0); /* max object size */
     533           0 :             avio_wl32(pb, (!asf->is_streamed && (pb->seekable & AVIO_SEEKABLE_NORMAL)) << 1); /* flags - seekable */
     534           0 :             avio_wl16(pb, n + 1); /* stream number */
     535           0 :             avio_wl16(pb, asf->streams[n].stream_language_index); /* language id index */
     536           0 :             avio_wl64(pb, 0); /* avg time per frame */
     537           0 :             avio_wl16(pb, 0); /* stream name count */
     538           0 :             avio_wl16(pb, 0); /* payload extension system count */
     539           0 :             end_header(pb, es_pos);
     540             :         }
     541             :     }
     542           6 :     if (has_aspect_ratio) {
     543             :         int64_t hpos2;
     544           0 :         hpos2 = put_header(pb, &ff_asf_metadata_header);
     545           0 :         avio_wl16(pb, 2 * has_aspect_ratio);
     546           0 :         for (n = 0; n < s->nb_streams; n++) {
     547           0 :             par = s->streams[n]->codecpar;
     548           0 :             if (   par->codec_type == AVMEDIA_TYPE_VIDEO
     549           0 :                 && par->sample_aspect_ratio.num > 0
     550           0 :                 && par->sample_aspect_ratio.den > 0) {
     551           0 :                 AVRational sar = par->sample_aspect_ratio;
     552           0 :                 avio_wl16(pb, 0);
     553             :                 // the stream number is set like this below
     554           0 :                 avio_wl16(pb, n + 1);
     555           0 :                 avio_wl16(pb, 26); // name_len
     556           0 :                 avio_wl16(pb,  3); // value_type
     557           0 :                 avio_wl32(pb,  4); // value_len
     558           0 :                 avio_put_str16le(pb, "AspectRatioX");
     559           0 :                 avio_wl32(pb, sar.num);
     560           0 :                 avio_wl16(pb, 0);
     561             :                 // the stream number is set like this below
     562           0 :                 avio_wl16(pb, n + 1);
     563           0 :                 avio_wl16(pb, 26); // name_len
     564           0 :                 avio_wl16(pb,  3); // value_type
     565           0 :                 avio_wl32(pb,  4); // value_len
     566           0 :                 avio_put_str16le(pb, "AspectRatioY");
     567           0 :                 avio_wl32(pb, sar.den);
     568             :             }
     569             :         }
     570           0 :         end_header(pb, hpos2);
     571             :     }
     572             :     {
     573             :         int64_t pos1;
     574           6 :         pos1 = avio_tell(pb);
     575           6 :         avio_seek(pb, hpos + 42, SEEK_SET);
     576           6 :         avio_wl32(pb, pos1 - hpos - 46);
     577           6 :         avio_seek(pb, pos1, SEEK_SET);
     578             :     }
     579           6 :     end_header(pb, hpos);
     580             : 
     581             :     /* title and other info */
     582           6 :     if (has_title) {
     583             :         int len;
     584             :         uint8_t *buf;
     585             :         AVIOContext *dyn_buf;
     586             : 
     587           2 :         if (avio_open_dyn_buf(&dyn_buf) < 0)
     588           0 :             return AVERROR(ENOMEM);
     589             : 
     590           2 :         hpos = put_header(pb, &ff_asf_comment_header);
     591             : 
     592          12 :         for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
     593          10 :             len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
     594          10 :             avio_wl16(pb, len);
     595             :         }
     596           2 :         len = avio_close_dyn_buf(dyn_buf, &buf);
     597           2 :         avio_write(pb, buf, len);
     598           2 :         av_freep(&buf);
     599           2 :         end_header(pb, hpos);
     600             :     }
     601           6 :     if (metadata_count) {
     602           6 :         AVDictionaryEntry *tag = NULL;
     603           6 :         hpos = put_header(pb, &ff_asf_extended_content_header);
     604           6 :         avio_wl16(pb, metadata_count);
     605          18 :         while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
     606           6 :             put_str16(pb, tag->key);
     607           6 :             avio_wl16(pb, 0);
     608           6 :             put_str16(pb, tag->value);
     609             :         }
     610           6 :         end_header(pb, hpos);
     611             :     }
     612             :     /* chapters using ASF markers */
     613           6 :     if (!asf->is_streamed && s->nb_chapters) {
     614             :         int ret;
     615           0 :         if ((ret = asf_write_markers(s)) < 0)
     616           0 :             return ret;
     617             :     }
     618             :     /* stream headers */
     619          14 :     for (n = 0; n < s->nb_streams; n++) {
     620             :         int64_t es_pos;
     621             :         //        ASFStream *stream = &asf->streams[n];
     622             : 
     623           8 :         par                 = s->streams[n]->codecpar;
     624           8 :         asf->streams[n].num = n + 1;
     625           8 :         asf->streams[n].seq = 1;
     626             : 
     627           8 :         switch (par->codec_type) {
     628             :         case AVMEDIA_TYPE_AUDIO:
     629           6 :             wav_extra_size = 0;
     630           6 :             extra_size     = 18 + wav_extra_size;
     631           6 :             extra_size2    = 8;
     632           6 :             break;
     633             :         default:
     634             :         case AVMEDIA_TYPE_VIDEO:
     635           2 :             wav_extra_size = par->extradata_size;
     636           2 :             extra_size     = 0x33 + wav_extra_size;
     637           2 :             extra_size2    = 0;
     638           2 :             break;
     639             :         }
     640             : 
     641           8 :         hpos = put_header(pb, &ff_asf_stream_header);
     642           8 :         if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
     643           6 :             ff_put_guid(pb, &ff_asf_audio_stream);
     644           6 :             ff_put_guid(pb, &ff_asf_audio_conceal_spread);
     645             :         } else {
     646           2 :             ff_put_guid(pb, &ff_asf_video_stream);
     647           2 :             ff_put_guid(pb, &ff_asf_video_conceal_none);
     648             :         }
     649           8 :         avio_wl64(pb, 0); /* ??? */
     650           8 :         es_pos = avio_tell(pb);
     651           8 :         avio_wl32(pb, extra_size); /* wav header len */
     652           8 :         avio_wl32(pb, extra_size2); /* additional data len */
     653           8 :         avio_wl16(pb, n + 1); /* stream number */
     654           8 :         avio_wl32(pb, 0); /* ??? */
     655             : 
     656           8 :         if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
     657             :             /* WAVEFORMATEX header */
     658           6 :             int wavsize = ff_put_wav_header(s, pb, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
     659             : 
     660           6 :             if (wavsize < 0)
     661           0 :                 return -1;
     662           6 :             if (wavsize != extra_size) {
     663           6 :                 cur_pos = avio_tell(pb);
     664           6 :                 avio_seek(pb, es_pos, SEEK_SET);
     665           6 :                 avio_wl32(pb, wavsize); /* wav header len */
     666           6 :                 avio_seek(pb, cur_pos, SEEK_SET);
     667             :             }
     668             :             /* ERROR Correction */
     669           6 :             avio_w8(pb, 0x01);
     670           6 :             if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) {
     671           2 :                 avio_wl16(pb, 0x0190);
     672           2 :                 avio_wl16(pb, 0x0190);
     673             :             } else {
     674           4 :                 avio_wl16(pb, par->block_align);
     675           4 :                 avio_wl16(pb, par->block_align);
     676             :             }
     677           6 :             avio_wl16(pb, 0x01);
     678           6 :             avio_w8(pb, 0x00);
     679             :         } else {
     680           2 :             avio_wl32(pb, par->width);
     681           2 :             avio_wl32(pb, par->height);
     682           2 :             avio_w8(pb, 2); /* ??? */
     683           2 :             avio_wl16(pb, 40 + par->extradata_size); /* size */
     684             : 
     685             :             /* BITMAPINFOHEADER header */
     686           2 :             ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1, 0);
     687             :         }
     688           8 :         end_header(pb, hpos);
     689             :     }
     690             : 
     691             :     /* media comments */
     692             : 
     693           6 :     hpos = put_header(pb, &ff_asf_codec_comment_header);
     694           6 :     ff_put_guid(pb, &ff_asf_codec_comment1_header);
     695           6 :     avio_wl32(pb, s->nb_streams);
     696          14 :     for (n = 0; n < s->nb_streams; n++) {
     697             :         const AVCodecDescriptor *codec_desc;
     698             :         const char *desc;
     699             : 
     700           8 :         par  = s->streams[n]->codecpar;
     701           8 :         codec_desc = avcodec_descriptor_get(par->codec_id);
     702             : 
     703           8 :         if (par->codec_type == AVMEDIA_TYPE_AUDIO)
     704           6 :             avio_wl16(pb, 2);
     705           2 :         else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
     706           2 :             avio_wl16(pb, 1);
     707             :         else
     708           0 :             avio_wl16(pb, -1);
     709             : 
     710           8 :         if (par->codec_id == AV_CODEC_ID_WMAV2)
     711           2 :             desc = "Windows Media Audio V8";
     712             :         else
     713           6 :             desc = codec_desc ? codec_desc->name : NULL;
     714             : 
     715           8 :         if (desc) {
     716             :             AVIOContext *dyn_buf;
     717             :             uint8_t *buf;
     718             :             int len;
     719             : 
     720           8 :             if (avio_open_dyn_buf(&dyn_buf) < 0)
     721           0 :                 return AVERROR(ENOMEM);
     722             : 
     723           8 :             avio_put_str16le(dyn_buf, desc);
     724           8 :             len = avio_close_dyn_buf(dyn_buf, &buf);
     725           8 :             avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2
     726             : 
     727           8 :             avio_write(pb, buf, len);
     728           8 :             av_freep(&buf);
     729             :         } else
     730           0 :             avio_wl16(pb, 0);
     731             : 
     732           8 :         avio_wl16(pb, 0); /* no parameters */
     733             : 
     734             :         /* id */
     735           8 :         if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
     736           6 :             avio_wl16(pb, 2);
     737           6 :             avio_wl16(pb, par->codec_tag);
     738             :         } else {
     739           2 :             avio_wl16(pb, 4);
     740           2 :             avio_wl32(pb, par->codec_tag);
     741             :         }
     742           8 :         if (!par->codec_tag)
     743           0 :             return -1;
     744             :     }
     745           6 :     end_header(pb, hpos);
     746             : 
     747             :     /* patch the header size fields */
     748             : 
     749           6 :     cur_pos     = avio_tell(pb);
     750           6 :     header_size = cur_pos - header_offset;
     751           6 :     if (asf->is_streamed) {
     752           0 :         header_size += 8 + 30 + DATA_HEADER_SIZE;
     753             : 
     754           0 :         avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
     755           0 :         avio_wl16(pb, header_size);
     756           0 :         avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
     757           0 :         avio_wl16(pb, header_size);
     758             : 
     759           0 :         header_size -= 8 + 30 + DATA_HEADER_SIZE;
     760             :     }
     761           6 :     header_size += 24 + 6;
     762           6 :     avio_seek(pb, header_offset - 14, SEEK_SET);
     763           6 :     avio_wl64(pb, header_size);
     764           6 :     avio_seek(pb, cur_pos, SEEK_SET);
     765             : 
     766             :     /* movie chunk, followed by packets of packet_size */
     767           6 :     asf->data_offset = cur_pos;
     768           6 :     ff_put_guid(pb, &ff_asf_data_header);
     769           6 :     avio_wl64(pb, data_chunk_size);
     770           6 :     ff_put_guid(pb, &ff_asf_my_guid);
     771           6 :     avio_wl64(pb, asf->nb_packets); /* nb packets */
     772           6 :     avio_w8(pb, 1); /* ??? */
     773           6 :     avio_w8(pb, 1); /* ??? */
     774           6 :     return 0;
     775             : }
     776             : 
     777           3 : static int asf_write_header(AVFormatContext *s)
     778             : {
     779           3 :     ASFContext *asf = s->priv_data;
     780             : 
     781           3 :     s->packet_size  = asf->packet_size;
     782           3 :     s->max_interleave_delta = 0;
     783           3 :     asf->nb_packets = 0;
     784             : 
     785           3 :     if (s->nb_streams > 127) {
     786           0 :         av_log(s, AV_LOG_ERROR, "ASF can only handle 127 streams\n");
     787           0 :         return AVERROR(EINVAL);
     788             :     }
     789             : 
     790           3 :     asf->index_ptr             = av_malloc(sizeof(ASFIndex) * ASF_INDEX_BLOCK);
     791           3 :     if (!asf->index_ptr)
     792           0 :         return AVERROR(ENOMEM);
     793           3 :     asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
     794           3 :     asf->maximum_packet        = 0;
     795             : 
     796             :     /* the data-chunk-size has to be 50 (DATA_HEADER_SIZE), which is
     797             :      * data_size - asf->data_offset at the moment this function is done.
     798             :      * It is needed to use asf as a streamable format. */
     799           3 :     if (asf_write_header1(s, 0, DATA_HEADER_SIZE) < 0) {
     800             :         //av_free(asf);
     801           0 :         av_freep(&asf->index_ptr);
     802           0 :         return -1;
     803             :     }
     804             : 
     805           3 :     avio_flush(s->pb);
     806             : 
     807           3 :     asf->packet_nb_payloads     = 0;
     808           3 :     asf->packet_timestamp_start = -1;
     809           3 :     asf->packet_timestamp_end   = -1;
     810           3 :     ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
     811             :                       NULL, NULL, NULL, NULL);
     812             : 
     813           3 :     if (s->avoid_negative_ts < 0)
     814           3 :         s->avoid_negative_ts = 1;
     815             : 
     816           3 :     return 0;
     817             : }
     818             : 
     819           0 : static int asf_write_stream_header(AVFormatContext *s)
     820             : {
     821           0 :     ASFContext *asf = s->priv_data;
     822             : 
     823           0 :     asf->is_streamed = 1;
     824             : 
     825           0 :     return asf_write_header(s);
     826             : }
     827             : 
     828         208 : static int put_payload_parsing_info(AVFormatContext *s,
     829             :                                     unsigned sendtime, unsigned duration,
     830             :                                     int nb_payloads, int padsize)
     831             : {
     832         208 :     ASFContext *asf = s->priv_data;
     833         208 :     AVIOContext *pb = s->pb;
     834             :     int ppi_size, i;
     835         208 :     int64_t start = avio_tell(pb);
     836             : 
     837         208 :     int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
     838             : 
     839         208 :     padsize -= PACKET_HEADER_MIN_SIZE;
     840         208 :     if (asf->multi_payloads_present)
     841         135 :         padsize--;
     842         208 :     av_assert0(padsize >= 0);
     843             : 
     844         208 :     avio_w8(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
     845         624 :     for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++)
     846         416 :         avio_w8(pb, 0x0);
     847             : 
     848         208 :     if (asf->multi_payloads_present)
     849         135 :         iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
     850             : 
     851         208 :     if (padsize > 0) {
     852         110 :         if (padsize < 256)
     853         107 :             iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
     854             :         else
     855           3 :             iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
     856             :     }
     857         208 :     avio_w8(pb, iLengthTypeFlags);
     858             : 
     859         208 :     avio_w8(pb, ASF_PPI_PROPERTY_FLAGS);
     860             : 
     861         208 :     if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
     862           3 :         avio_wl16(pb, padsize - 2);
     863         208 :     if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
     864         107 :         avio_w8(pb, padsize - 1);
     865             : 
     866         208 :     avio_wl32(pb, sendtime);
     867         208 :     avio_wl16(pb, duration);
     868         208 :     if (asf->multi_payloads_present)
     869         135 :         avio_w8(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
     870             : 
     871         208 :     ppi_size = avio_tell(pb) - start;
     872             : 
     873         208 :     return ppi_size;
     874             : }
     875             : 
     876         208 : static void flush_packet(AVFormatContext *s)
     877             : {
     878         208 :     ASFContext *asf = s->priv_data;
     879             :     int packet_hdr_size, packet_filled_size;
     880             : 
     881         208 :     av_assert0(asf->packet_timestamp_end >= asf->packet_timestamp_start);
     882             : 
     883         208 :     if (asf->is_streamed)
     884           0 :         put_chunk(s, 0x4424, s->packet_size, 0);
     885             : 
     886        1040 :     packet_hdr_size = put_payload_parsing_info(s,
     887         208 :                                                asf->packet_timestamp_start,
     888         416 :                                                asf->packet_timestamp_end - asf->packet_timestamp_start,
     889         208 :                                                asf->packet_nb_payloads,
     890             :                                                asf->packet_size_left);
     891             : 
     892         208 :     packet_filled_size = asf->packet_size - asf->packet_size_left;
     893         208 :     av_assert0(packet_hdr_size <= asf->packet_size_left);
     894         208 :     memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
     895             : 
     896         208 :     avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size);
     897             : 
     898         208 :     avio_flush(s->pb);
     899         208 :     asf->nb_packets++;
     900         208 :     asf->packet_nb_payloads     = 0;
     901         208 :     asf->packet_timestamp_start = -1;
     902         208 :     asf->packet_timestamp_end   = -1;
     903         208 :     ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
     904             :                       NULL, NULL, NULL, NULL);
     905         208 : }
     906             : 
     907         572 : static void put_payload_header(AVFormatContext *s, ASFStream *stream,
     908             :                                int64_t presentation_time, int m_obj_size,
     909             :                                int m_obj_offset, int payload_len, int flags)
     910             : {
     911         572 :     ASFContext *asf = s->priv_data;
     912         572 :     AVIOContext *pb = &asf->pb;
     913             :     int val;
     914             : 
     915         572 :     val = stream->num;
     916         572 :     if (flags & AV_PKT_FLAG_KEY)
     917          30 :         val |= ASF_PL_FLAG_KEY_FRAME;
     918         572 :     avio_w8(pb, val);
     919             : 
     920         572 :     avio_w8(pb, stream->seq);     // Media object number
     921         572 :     avio_wl32(pb, m_obj_offset);  // Offset Into Media Object
     922             : 
     923             :     // Replicated Data shall be at least 8 bytes long.
     924             :     // The first 4 bytes of data shall contain the
     925             :     // Size of the Media Object that the payload belongs to.
     926             :     // The next 4 bytes of data shall contain the
     927             :     // Presentation Time for the media object that the payload belongs to.
     928         572 :     avio_w8(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
     929             : 
     930         572 :     avio_wl32(pb, m_obj_size);        // Replicated Data - Media Object Size
     931         572 :     avio_wl32(pb, (uint32_t) presentation_time); // Replicated Data - Presentation Time
     932             : 
     933         572 :     if (asf->multi_payloads_present) {
     934         499 :         avio_wl16(pb, payload_len);   // payload length
     935             :     }
     936         572 : }
     937             : 
     938         474 : static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
     939             :                       int64_t timestamp, const uint8_t *buf,
     940             :                       int m_obj_size, int flags)
     941             : {
     942         474 :     ASFContext *asf = s->priv_data;
     943             :     int m_obj_offset, payload_len, frag_len1;
     944             : 
     945         474 :     m_obj_offset = 0;
     946        1627 :     while (m_obj_offset < m_obj_size) {
     947         679 :         payload_len = m_obj_size - m_obj_offset;
     948         679 :         if (asf->packet_timestamp_start == -1) {
     949         208 :             const int multi_payload_constant = (asf->packet_size - MULTI_PAYLOAD_HEADERS);
     950         208 :             asf->multi_payloads_present = (payload_len < multi_payload_constant);
     951             : 
     952         208 :             asf->packet_size_left = asf->packet_size;
     953         208 :             if (asf->multi_payloads_present) {
     954         135 :                 frag_len1 = multi_payload_constant - 1;
     955             :             } else {
     956          73 :                 frag_len1 = asf->packet_size - SINGLE_PAYLOAD_HEADERS;
     957             :             }
     958         208 :             asf->packet_timestamp_start = timestamp;
     959             :         } else {
     960             :             // multi payloads
     961         471 :             frag_len1 = asf->packet_size_left -
     962             :                         PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS -
     963             :                         PACKET_HEADER_MIN_SIZE - 1;
     964             : 
     965         603 :             if (frag_len1 < payload_len &&
     966         132 :                 avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
     967         107 :                 flush_packet(s);
     968         107 :                 continue;
     969             :             }
     970         728 :             if (asf->packet_timestamp_start > INT64_MAX - UINT16_MAX ||
     971         364 :                 timestamp > asf->packet_timestamp_start + UINT16_MAX) {
     972           0 :                 flush_packet(s);
     973           0 :                 continue;
     974             :             }
     975             :         }
     976         572 :         if (frag_len1 > 0) {
     977         572 :             if (payload_len > frag_len1)
     978          98 :                 payload_len = frag_len1;
     979         474 :             else if (payload_len == (frag_len1 - 1))
     980           0 :                 payload_len = frag_len1 - 2;  // additional byte need to put padding length
     981             : 
     982         572 :             put_payload_header(s, stream, timestamp + PREROLL_TIME,
     983             :                                m_obj_size, m_obj_offset, payload_len, flags);
     984         572 :             avio_write(&asf->pb, buf, payload_len);
     985             : 
     986         572 :             if (asf->multi_payloads_present)
     987         499 :                 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
     988             :             else
     989          73 :                 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
     990         572 :             asf->packet_timestamp_end = timestamp;
     991             : 
     992         572 :             asf->packet_nb_payloads++;
     993             :         } else {
     994           0 :             payload_len = 0;
     995             :         }
     996         572 :         m_obj_offset += payload_len;
     997         572 :         buf          += payload_len;
     998             : 
     999         572 :         if (!asf->multi_payloads_present)
    1000          73 :             flush_packet(s);
    1001         499 :         else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
    1002          25 :             flush_packet(s);
    1003         474 :         else if (asf->packet_nb_payloads == ASF_PAYLOADS_PER_PACKET)
    1004           0 :             flush_packet(s);
    1005             :     }
    1006         474 :     stream->seq++;
    1007         474 : }
    1008             : 
    1009           4 : static int update_index(AVFormatContext *s, int start_sec,
    1010             :                          uint32_t packet_number, uint16_t packet_count,
    1011             :                          uint64_t packet_offset)
    1012             : {
    1013           4 :     ASFContext *asf = s->priv_data;
    1014             : 
    1015           4 :     if (start_sec > asf->next_start_sec) {
    1016             :         int i;
    1017             : 
    1018           3 :         if (!asf->next_start_sec) {
    1019           1 :             asf->next_packet_number = packet_number;
    1020           1 :             asf->next_packet_count  = packet_count;
    1021           1 :             asf->next_packet_offset = packet_offset;
    1022             :         }
    1023             : 
    1024           3 :         if (start_sec > asf->nb_index_memory_alloc) {
    1025             :             int err;
    1026           0 :             asf->nb_index_memory_alloc = (start_sec + ASF_INDEX_BLOCK) & ~(ASF_INDEX_BLOCK - 1);
    1027           0 :             if ((err = av_reallocp_array(&asf->index_ptr,
    1028           0 :                                          asf->nb_index_memory_alloc,
    1029             :                                          sizeof(*asf->index_ptr))) < 0) {
    1030           0 :                 asf->nb_index_memory_alloc = 0;
    1031           0 :                 return err;
    1032             :             }
    1033             :         }
    1034           9 :         for (i = asf->next_start_sec; i < start_sec; i++) {
    1035           6 :             asf->index_ptr[i].packet_number = asf->next_packet_number;
    1036           6 :             asf->index_ptr[i].packet_count  = asf->next_packet_count;
    1037           6 :             asf->index_ptr[i].send_time     = asf->next_start_sec * INT64_C(10000000);
    1038           6 :             asf->index_ptr[i].offset        = asf->next_packet_offset;
    1039             : 
    1040             :         }
    1041             :     }
    1042           4 :     asf->maximum_packet     = FFMAX(asf->maximum_packet, packet_count);
    1043           4 :     asf->next_packet_number = packet_number;
    1044           4 :     asf->next_packet_count  = packet_count;
    1045           4 :     asf->next_packet_offset = packet_offset;
    1046           4 :     asf->next_start_sec     = start_sec;
    1047             : 
    1048           4 :     return 0;
    1049             : }
    1050             : 
    1051         474 : static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
    1052             : {
    1053         474 :     ASFContext *asf = s->priv_data;
    1054         474 :     AVIOContext *pb = s->pb;
    1055             :     ASFStream *stream;
    1056             :     AVCodecParameters *par;
    1057             :     uint32_t packet_number;
    1058             :     int64_t pts;
    1059             :     int start_sec;
    1060         474 :     int flags = pkt->flags;
    1061             :     int ret;
    1062         474 :     uint64_t offset = avio_tell(pb);
    1063             : 
    1064         474 :     par  = s->streams[pkt->stream_index]->codecpar;
    1065         474 :     stream = &asf->streams[pkt->stream_index];
    1066             : 
    1067         474 :     if (par->codec_type == AVMEDIA_TYPE_AUDIO)
    1068         449 :         flags &= ~AV_PKT_FLAG_KEY;
    1069             : 
    1070         474 :     pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
    1071         474 :     av_assert0(pts != AV_NOPTS_VALUE);
    1072         474 :     if (   pts < - PREROLL_TIME
    1073         474 :         || pts > (INT_MAX-3)/10000LL * ASF_INDEXED_INTERVAL - PREROLL_TIME) {
    1074           0 :         av_log(s, AV_LOG_ERROR, "input pts %"PRId64" is invalid\n", pts);
    1075           0 :         return AVERROR(EINVAL);
    1076             :     }
    1077         474 :     pts *= 10000;
    1078         474 :     asf->duration = FFMAX(asf->duration, pts + pkt->duration * 10000);
    1079             : 
    1080         474 :     packet_number = asf->nb_packets;
    1081         948 :     put_frame(s, stream, s->streams[pkt->stream_index],
    1082         474 :               pkt->dts, pkt->data, pkt->size, flags);
    1083             : 
    1084         948 :     start_sec = (int)((PREROLL_TIME * 10000 + pts + ASF_INDEXED_INTERVAL - 1)
    1085         474 :               / ASF_INDEXED_INTERVAL);
    1086             : 
    1087             :     /* check index */
    1088         474 :     if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) {
    1089           3 :         uint16_t packet_count = asf->nb_packets - packet_number;
    1090           3 :         ret = update_index(s, start_sec, packet_number, packet_count, offset);
    1091           3 :         if (ret < 0)
    1092           0 :             return ret;
    1093             :     }
    1094         474 :     asf->end_sec = start_sec;
    1095             : 
    1096         474 :     return 0;
    1097             : }
    1098             : 
    1099           1 : static int asf_write_index(AVFormatContext *s, const ASFIndex *index,
    1100             :                            uint16_t max, uint32_t count)
    1101             : {
    1102           1 :     AVIOContext *pb = s->pb;
    1103             :     int i;
    1104             : 
    1105           1 :     ff_put_guid(pb, &ff_asf_simple_index_header);
    1106           1 :     avio_wl64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count);
    1107           1 :     ff_put_guid(pb, &ff_asf_my_guid);
    1108           1 :     avio_wl64(pb, ASF_INDEXED_INTERVAL);
    1109           1 :     avio_wl32(pb, max);
    1110           1 :     avio_wl32(pb, count);
    1111           7 :     for (i = 0; i < count; i++) {
    1112           6 :         avio_wl32(pb, index[i].packet_number);
    1113           6 :         avio_wl16(pb, index[i].packet_count);
    1114             :     }
    1115             : 
    1116           1 :     return 0;
    1117             : }
    1118             : 
    1119           3 : static int asf_write_trailer(AVFormatContext *s)
    1120             : {
    1121           3 :     ASFContext *asf = s->priv_data;
    1122             :     int64_t file_size, data_size;
    1123             :     int ret;
    1124             : 
    1125             :     /* flush the current packet */
    1126           3 :     if (asf->pb.buf_ptr > asf->pb.buffer)
    1127           3 :         flush_packet(s);
    1128             : 
    1129             :     /* write index */
    1130           3 :     data_size = avio_tell(s->pb);
    1131           3 :     if (!asf->is_streamed && asf->next_start_sec) {
    1132           1 :         if ((ret = update_index(s, asf->end_sec + 1, 0, 0, 0)) < 0)
    1133           0 :             return ret;
    1134           1 :         asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec);
    1135             :     }
    1136           3 :     avio_flush(s->pb);
    1137             : 
    1138           3 :     if (asf->is_streamed || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
    1139           0 :         put_chunk(s, 0x4524, 0, 0); /* end of stream */
    1140             :     } else {
    1141             :         /* rewrite an updated header */
    1142           3 :         file_size = avio_tell(s->pb);
    1143           3 :         avio_seek(s->pb, 0, SEEK_SET);
    1144           3 :         asf_write_header1(s, file_size, data_size - asf->data_offset);
    1145             :     }
    1146             : 
    1147           3 :     av_freep(&asf->index_ptr);
    1148           3 :     return 0;
    1149             : }
    1150             : 
    1151             : static const AVOption asf_options[] = {
    1152             :     { "packet_size", "Packet size", offsetof(ASFContext, packet_size), AV_OPT_TYPE_INT, {.i64 = 3200}, PACKET_SIZE_MIN, PACKET_SIZE_MAX, AV_OPT_FLAG_ENCODING_PARAM },
    1153             :     { NULL },
    1154             : };
    1155             : 
    1156             : #if CONFIG_ASF_MUXER
    1157             : static const AVClass asf_muxer_class = {
    1158             :     .class_name     = "ASF muxer",
    1159             :     .item_name      = av_default_item_name,
    1160             :     .option         = asf_options,
    1161             :     .version        = LIBAVUTIL_VERSION_INT,
    1162             : };
    1163             : 
    1164             : AVOutputFormat ff_asf_muxer = {
    1165             :     .name           = "asf",
    1166             :     .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
    1167             :     .mime_type      = "video/x-ms-asf",
    1168             :     .extensions     = "asf,wmv,wma",
    1169             :     .priv_data_size = sizeof(ASFContext),
    1170             :     .audio_codec    = AV_CODEC_ID_WMAV2,
    1171             :     .video_codec    = AV_CODEC_ID_MSMPEG4V3,
    1172             :     .write_header   = asf_write_header,
    1173             :     .write_packet   = asf_write_packet,
    1174             :     .write_trailer  = asf_write_trailer,
    1175             :     .flags          = AVFMT_GLOBALHEADER,
    1176             :     .codec_tag      = (const AVCodecTag * const []) {
    1177             :         codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    1178             :     },
    1179             :     .priv_class        = &asf_muxer_class,
    1180             : };
    1181             : #endif /* CONFIG_ASF_MUXER */
    1182             : 
    1183             : #if CONFIG_ASF_STREAM_MUXER
    1184             : static const AVClass asf_stream_muxer_class = {
    1185             :     .class_name     = "ASF stream muxer",
    1186             :     .item_name      = av_default_item_name,
    1187             :     .option         = asf_options,
    1188             :     .version        = LIBAVUTIL_VERSION_INT,
    1189             : };
    1190             : 
    1191             : AVOutputFormat ff_asf_stream_muxer = {
    1192             :     .name           = "asf_stream",
    1193             :     .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
    1194             :     .mime_type      = "video/x-ms-asf",
    1195             :     .extensions     = "asf,wmv,wma",
    1196             :     .priv_data_size = sizeof(ASFContext),
    1197             :     .audio_codec    = AV_CODEC_ID_WMAV2,
    1198             :     .video_codec    = AV_CODEC_ID_MSMPEG4V3,
    1199             :     .write_header   = asf_write_stream_header,
    1200             :     .write_packet   = asf_write_packet,
    1201             :     .write_trailer  = asf_write_trailer,
    1202             :     .flags          = AVFMT_GLOBALHEADER,
    1203             :     .codec_tag      = (const AVCodecTag * const []) {
    1204             :         codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
    1205             :     },
    1206             :     .priv_class        = &asf_stream_muxer_class,
    1207             : };
    1208             : #endif /* CONFIG_ASF_STREAM_MUXER */

Generated by: LCOV version 1.13