@@ -41,6 +41,27 @@ using namespace std;
41
41
42
42
#define SRS_MP4_BUF_SIZE 4096
43
43
44
+ srs_error_t srs_mp4_write_box (ISrsWriter* writer, ISrsCodec* box)
45
+ {
46
+ srs_error_t err = srs_success;
47
+
48
+ int nb_data = box->nb_bytes ();
49
+ std::vector<char > data (nb_data);
50
+
51
+ SrsBuffer* buffer = new SrsBuffer (&data[0 ], nb_data);
52
+ SrsAutoFree (SrsBuffer, buffer);
53
+
54
+ if ((err = box->encode (buffer)) != srs_success) {
55
+ return srs_error_wrap (err, " encode box" );
56
+ }
57
+
58
+ if ((err = writer->write (&data[0 ], nb_data, NULL )) != srs_success) {
59
+ return srs_error_wrap (err, " write box" );
60
+ }
61
+
62
+ return err;
63
+ }
64
+
44
65
stringstream& srs_padding (stringstream& ss, SrsMp4DumpContext dc, int tab = 4 )
45
66
{
46
67
for (int i = 0 ; i < (int )dc.level ; i++) {
@@ -4587,7 +4608,7 @@ SrsMp4SegmentIndexBox::~SrsMp4SegmentIndexBox()
4587
4608
4588
4609
int SrsMp4SegmentIndexBox::nb_header ()
4589
4610
{
4590
- return SrsMp4Box::nb_header () + 4 +4 +4 + (version? 4 : 8 ) + 4 + 4 + 12 *entries.size ();
4611
+ return SrsMp4Box::nb_header () + 4 +4 +4 + (! version? 8 : 16 ) + 4 + 12 *entries.size ();
4591
4612
}
4592
4613
4593
4614
srs_error_t SrsMp4SegmentIndexBox::encode_header (SrsBuffer* buf)
@@ -6041,18 +6062,24 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid)
6041
6062
srs_error_t err = srs_success;
6042
6063
6043
6064
// Write ftyp box.
6044
- SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox ();
6045
- SrsAutoFree (SrsMp4FileTypeBox, ftyp);
6046
6065
if (true ) {
6066
+ SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox ();
6067
+ SrsAutoFree (SrsMp4FileTypeBox, ftyp);
6068
+
6047
6069
ftyp->major_brand = SrsMp4BoxBrandISO5;
6048
6070
ftyp->minor_version = 512 ;
6049
6071
ftyp->set_compatible_brands (SrsMp4BoxBrandISO6, SrsMp4BoxBrandMP41);
6072
+
6073
+ if ((err = srs_mp4_write_box (writer, ftyp)) != srs_success) {
6074
+ return srs_error_wrap (err, " write ftyp" );
6075
+ }
6050
6076
}
6051
6077
6052
6078
// Write moov.
6053
- SrsMp4MovieBox* moov = new SrsMp4MovieBox ();
6054
- SrsAutoFree (SrsMp4MovieBox, moov);
6055
6079
if (true ) {
6080
+ SrsMp4MovieBox* moov = new SrsMp4MovieBox ();
6081
+ SrsAutoFree (SrsMp4MovieBox, moov);
6082
+
6056
6083
SrsMp4MovieHeaderBox* mvhd = new SrsMp4MovieHeaderBox ();
6057
6084
moov->set_mvhd (mvhd);
6058
6085
@@ -6244,24 +6271,10 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid)
6244
6271
trex->track_ID = tid;
6245
6272
trex->default_sample_description_index = 1 ;
6246
6273
}
6247
- }
6248
-
6249
- int nb_data = ftyp->nb_bytes () + moov->nb_bytes ();
6250
- uint8_t * data = new uint8_t [nb_data];
6251
- SrsAutoFreeA (uint8_t , data);
6252
-
6253
- SrsBuffer* buffer = new SrsBuffer ((char *)data, nb_data);
6254
- SrsAutoFree (SrsBuffer, buffer);
6255
-
6256
- if ((err = ftyp->encode (buffer)) != srs_success) {
6257
- return srs_error_wrap (err, " encode ftyp" );
6258
- }
6259
- if ((err = moov->encode (buffer)) != srs_success) {
6260
- return srs_error_wrap (err, " encode moov" );
6261
- }
6262
-
6263
- if ((err = writer->write (data, nb_data, NULL )) != srs_success) {
6264
- return srs_error_wrap (err, " write ftyp and moov" );
6274
+
6275
+ if ((err = srs_mp4_write_box (writer, moov)) != srs_success) {
6276
+ return srs_error_wrap (err, " write moov" );
6277
+ }
6265
6278
}
6266
6279
6267
6280
return err;
@@ -6275,6 +6288,7 @@ SrsMp4M2tsSegmentEncoder::SrsMp4M2tsSegmentEncoder()
6275
6288
buffer = new SrsBuffer ();
6276
6289
sequence_number = 0 ;
6277
6290
decode_basetime = 0 ;
6291
+ styp_bytes = 0 ;
6278
6292
mdat_bytes = 0 ;
6279
6293
}
6280
6294
@@ -6301,19 +6315,11 @@ srs_error_t SrsMp4M2tsSegmentEncoder::initialize(ISrsWriter* w, uint32_t sequenc
6301
6315
styp->major_brand = SrsMp4BoxBrandMSDH;
6302
6316
styp->minor_version = 0 ;
6303
6317
styp->set_compatible_brands (SrsMp4BoxBrandMSDH, SrsMp4BoxBrandMSIX);
6304
-
6305
- int nb_data = styp->nb_bytes ();
6306
- std::vector<char > data (nb_data);
6307
-
6308
- SrsBuffer* buffer = new SrsBuffer (&data[0 ], nb_data);
6309
- SrsAutoFree (SrsBuffer, buffer);
6310
-
6311
- if ((err = styp->encode (buffer)) != srs_success) {
6312
- return srs_error_wrap (err, " encode styp" );
6313
- }
6314
-
6315
- // TODO: FIXME: Ensure write ok.
6316
- if ((err = writer->write (&data[0 ], nb_data, NULL )) != srs_success) {
6318
+
6319
+ // Used for sidx to calcalute the referenced size.
6320
+ styp_bytes = styp->nb_bytes ();
6321
+
6322
+ if ((err = srs_mp4_write_box (writer, styp)) != srs_success) {
6317
6323
return srs_error_wrap (err, " write styp" );
6318
6324
}
6319
6325
}
@@ -6365,16 +6371,36 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
6365
6371
if (!nb_audios && !nb_videos) {
6366
6372
return srs_error_new (ERROR_MP4_ILLEGAL_MOOF, " Missing audio and video track" );
6367
6373
}
6368
-
6374
+
6375
+ // Although the sidx is not required to start play DASH, but it's required for AV sync.
6376
+ SrsMp4SegmentIndexBox* sidx = new SrsMp4SegmentIndexBox ();
6377
+ SrsAutoFree (SrsMp4SegmentIndexBox, sidx);
6378
+ if (true ) {
6379
+ sidx->version = 1 ;
6380
+ sidx->reference_id = 1 ;
6381
+ sidx->timescale = 1000 ;
6382
+ sidx->earliest_presentation_time = uint64_t (decode_basetime / sidx->timescale );
6383
+
6384
+ uint64_t duration = 0 ;
6385
+ if (samples && !samples->samples .empty ()) {
6386
+ SrsMp4Sample* first = samples->samples [0 ];
6387
+ SrsMp4Sample* last = samples->samples [samples->samples .size () - 1 ];
6388
+ duration = srs_max (0 , last->dts - first->dts );
6389
+ }
6390
+
6391
+ SrsMp4SegmentIndexEntry entry;
6392
+ memset (&entry, 0 , sizeof (entry));
6393
+ entry.subsegment_duration = duration;
6394
+ entry.starts_with_SAP = 1 ;
6395
+ sidx->entries .push_back (entry);
6396
+ }
6397
+
6369
6398
// Create a mdat box.
6370
6399
// its payload will be writen by samples,
6371
6400
// and we will update its header(size) when flush.
6372
6401
SrsMp4MediaDataBox* mdat = new SrsMp4MediaDataBox ();
6373
6402
SrsAutoFree (SrsMp4MediaDataBox, mdat);
6374
6403
6375
- // Although the sidx is not required to start play DASH, but it's required for AV sync.
6376
- // TODO: FIXME: Insert a sidx box.
6377
-
6378
6404
// Write moof.
6379
6405
if (true ) {
6380
6406
SrsMp4MovieFragmentBox* moof = new SrsMp4MovieFragmentBox ();
@@ -6407,30 +6433,25 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
6407
6433
return srs_error_wrap (err, " write samples" );
6408
6434
}
6409
6435
6410
- int nb_data = moof->nb_bytes ();
6411
6436
// @remark Remember the data_offset of turn is size(moof)+header(mdat), not including styp or sidx.
6412
- trun->data_offset = (int32_t )(nb_data + mdat->sz_header ());
6413
-
6414
- uint8_t * data = new uint8_t [nb_data];
6415
- SrsAutoFreeA (uint8_t , data);
6416
-
6417
- SrsBuffer* buffer = new SrsBuffer ((char *)data, nb_data);
6418
- SrsAutoFree (SrsBuffer, buffer);
6419
-
6420
- if ((err = moof->encode (buffer)) != srs_success) {
6421
- return srs_error_wrap (err, " encode moof" );
6437
+ int moof_bytes = moof->nb_bytes ();
6438
+ trun->data_offset = (int32_t )(moof_bytes + mdat->sz_header ());
6439
+ mdat->nb_data = (int )mdat_bytes;
6440
+
6441
+ // Update the size of sidx.
6442
+ SrsMp4SegmentIndexEntry* entry = &sidx->entries [0 ];
6443
+ entry->referenced_size = moof_bytes + mdat->nb_bytes ();
6444
+ if ((err = srs_mp4_write_box (writer, sidx)) != srs_success) {
6445
+ return srs_error_wrap (err, " write sidx" );
6422
6446
}
6423
-
6424
- // TODO: FIXME: Ensure all bytes are writen.
6425
- if ((err = writer->write (data, nb_data, NULL )) != srs_success) {
6447
+
6448
+ if ((err = srs_mp4_write_box (writer, moof)) != srs_success) {
6426
6449
return srs_error_wrap (err, " write moof" );
6427
6450
}
6428
6451
}
6429
6452
6430
6453
// Write mdat.
6431
6454
if (true ) {
6432
- mdat->nb_data = (int )mdat_bytes;
6433
-
6434
6455
int nb_data = mdat->sz_header ();
6435
6456
uint8_t * data = new uint8_t [nb_data];
6436
6457
SrsAutoFreeA (uint8_t , data);
0 commit comments