16
16
* You should have received a copy of the GNU Lesser General Public
17
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
#include "avformat.h"
25
26
#include <assert.h>
33
#define MODE_PSP 3 // example working PSP command line:
34
#define MODE_PSP 3 // example working PSP command line:
34
35
// ffmpeg -i testinput.avi -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
37
38
typedef struct MOVIentry {
38
unsigned int flags, pos, size;
39
unsigned int flags, size;
39
41
unsigned int samplesInChunk;
41
43
unsigned int entries;
73
76
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
75
const CodecTag ff_mov_obj_type[] = {
76
{ CODEC_ID_MPEG4 , 32 },
77
{ CODEC_ID_AAC , 64 },
78
{ CODEC_ID_MPEG1VIDEO, 106 },
79
{ CODEC_ID_MPEG2VIDEO, 96 },//mpeg2 profiles
80
{ CODEC_ID_MP2 , 107 },//FIXME mpeg2 mpeg audio -> 105
81
{ CODEC_ID_MP3 , 107 },//FIXME mpeg2 mpeg audio -> 105
82
{ CODEC_ID_H264 , 33 },
83
{ CODEC_ID_H263 , 242 },
84
{ CODEC_ID_H261 , 243 },
85
{ CODEC_ID_MJPEG , 108 },
86
{ CODEC_ID_PCM_S16LE , 224 },
87
{ CODEC_ID_VORBIS , 225 },
88
{ CODEC_ID_AC3 , 226 },
89
{ CODEC_ID_PCM_ALAW , 227 },
90
{ CODEC_ID_PCM_MULAW , 228 },
91
{ CODEC_ID_PCM_S16BE , 230 },
78
/* output language code from iso639 language name */
79
extern int ff_mov_iso639_to_lang(const char *lang, int mp4);
95
81
//FIXME supprt 64bit varaint with wide placeholders
96
static int updateSize (ByteIOContext *pb, int pos)
82
static offset_t updateSize (ByteIOContext *pb, offset_t pos)
98
long curpos = url_ftell(pb);
84
offset_t curpos = url_ftell(pb);
99
85
url_fseek(pb, pos, SEEK_SET);
100
86
put_be32(pb, curpos - pos); /* rewrite size */
101
87
url_fseek(pb, curpos, SEEK_SET);
107
93
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
110
int pos = url_ftell(pb);
96
int mode64 = 0; // use 32 bit size variant if possible
97
offset_t pos = url_ftell(pb);
111
98
put_be32(pb, 0); /* size */
99
if (pos > UINT32_MAX) {
113
104
put_be32(pb, 0); /* version & flags */
114
105
put_be32(pb, track->entry); /* entry count */
115
106
for (i=0; i<track->entry; i++) {
116
107
int cl = i / MOV_INDEX_CLUSTER_SIZE;
117
108
int id = i % MOV_INDEX_CLUSTER_SIZE;
118
put_be32(pb, track->cluster[cl][id].pos);
110
put_be64(pb, track->cluster[cl][id].pos);
112
put_be32(pb, track->cluster[cl][id].pos);
120
114
return updateSize (pb, pos);
126
120
int equalChunks = 1;
127
121
int i, j, entries = 0, tst = -1, oldtst = -1;
129
int pos = url_ftell(pb);
123
offset_t pos = url_ftell(pb);
130
124
put_be32(pb, 0); /* size */
131
125
put_tag(pb, "stsz");
132
126
put_be32(pb, 0); /* version & flags */
144
138
if (equalChunks) {
145
139
int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
146
put_be32(pb, sSize); // sample size
140
put_be32(pb, sSize); // sample size
147
141
put_be32(pb, entries); // sample count
150
put_be32(pb, 0); // sample size
151
put_be32(pb, entries); // sample count
144
put_be32(pb, 0); // sample size
145
put_be32(pb, entries); // sample count
152
146
for (i=0; i<track->entry; i++) {
153
147
int cl = i / MOV_INDEX_CLUSTER_SIZE;
154
148
int id = i % MOV_INDEX_CLUSTER_SIZE;
164
158
/* Sample to chunk atom */
165
159
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
167
int index = 0, oldval = -1, i, entryPos, curpos;
161
int index = 0, oldval = -1, i;
162
offset_t entryPos, curpos;
169
int pos = url_ftell(pb);
164
offset_t pos = url_ftell(pb);
170
165
put_be32(pb, 0); /* size */
171
166
put_tag(pb, "stsc");
172
put_be32(pb, 0); // version & flags
167
put_be32(pb, 0); // version & flags
173
168
entryPos = url_ftell(pb);
174
put_be32(pb, track->entry); // entry count
169
put_be32(pb, track->entry); // entry count
175
170
for (i=0; i<track->entry; i++) {
176
171
int cl = i / MOV_INDEX_CLUSTER_SIZE;
177
172
int id = i % MOV_INDEX_CLUSTER_SIZE;
178
173
if(oldval != track->cluster[cl][id].samplesInChunk)
180
put_be32(pb, i+1); // first chunk
175
put_be32(pb, i+1); // first chunk
181
176
put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
182
put_be32(pb, 0x1); // sample description index
177
put_be32(pb, 0x1); // sample description index
183
178
oldval = track->cluster[cl][id].samplesInChunk;
187
182
curpos = url_ftell(pb);
188
183
url_fseek(pb, entryPos, SEEK_SET);
189
put_be32(pb, index); // rewrite size
184
put_be32(pb, index); // rewrite size
190
185
url_fseek(pb, curpos, SEEK_SET);
192
187
return updateSize (pb, pos);
195
190
/* Sync sample atom */
196
191
static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
199
int i, index = 0, entryPos;
200
int pos = url_ftell(pb);
201
put_be32(pb, 0); // size
193
offset_t curpos, entryPos;
195
offset_t pos = url_ftell(pb);
196
put_be32(pb, 0); // size
202
197
put_tag(pb, "stss");
203
put_be32(pb, 0); // version & flags
198
put_be32(pb, 0); // version & flags
204
199
entryPos = url_ftell(pb);
205
put_be32(pb, track->entry); // entry count
200
put_be32(pb, track->entry); // entry count
206
201
for (i=0; i<track->entry; i++) {
207
202
int cl = i / MOV_INDEX_CLUSTER_SIZE;
208
203
int id = i % MOV_INDEX_CLUSTER_SIZE;
214
209
curpos = url_ftell(pb);
215
210
url_fseek(pb, entryPos, SEEK_SET);
216
put_be32(pb, index); // rewrite size
211
put_be32(pb, index); // rewrite size
217
212
url_fseek(pb, curpos, SEEK_SET);
218
213
return updateSize (pb, pos);
277
272
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
279
int pos = url_ftell(pb);
274
offset_t pos = url_ftell(pb);
282
277
put_be32(pb, 0); /* size */
284
279
tag = track->enc->codec_tag;
287
282
// if no mac fcc found, try with Microsoft tags
290
int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
285
int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
291
286
tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));
293
288
put_le32(pb, tag); // store it byteswapped
384
379
vals[3] = (uint8_t)(len & 0x7f);
386
vals[2] = (uint8_t)((len & 0x7f) | 0x80);
381
vals[2] = (uint8_t)((len & 0x7f) | 0x80);
388
vals[1] = (uint8_t)((len & 0x7f) | 0x80);
383
vals[1] = (uint8_t)((len & 0x7f) | 0x80);
390
385
vals[0] = (uint8_t)((len & 0x7f) | 0x80);
418
413
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
420
415
int decoderSpecificInfoLen;
421
int pos = url_ftell(pb);
422
void *vosDataBackup=track->vosData;
423
int vosLenBackup=track->vosLen;
425
// we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all
426
static const char PSPAACData[]={0x13,0x10};
427
static const char PSPMP4Data[]={0x00,0x00,0x01,0xB0,0x03,0x00,0x00,0x01,0xB5,0x09,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x20,0x00,0x84,0x5D,0x4C,0x28,0x50,0x20,0xF0,0xA3,0x1F };
430
if (track->mode == MODE_PSP) // fails on psp if this is not here
432
if (track->enc->codec_id == CODEC_ID_AAC)
435
track->vosData = (uint8_t *) PSPAACData;
438
if (track->enc->codec_id == CODEC_ID_MPEG4)
441
track->vosData = (uint8_t *) PSPMP4Data;
416
offset_t pos = url_ftell(pb);
445
418
decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
515
486
tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
516
487
// if no mac fcc found, try with Microsoft tags
518
tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
489
tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
519
490
put_le32(pb, tag); // store it byteswapped
521
492
put_be32(pb, 0); /* Reserved */
538
509
put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
539
510
put_be32(pb, 0); /* Data size (= 0) */
540
511
put_be16(pb, 1); /* Frame count (= 1) */
542
513
memset(compressor_name,0,32);
543
514
if (track->enc->codec && track->enc->codec->name)
544
515
strncpy(compressor_name,track->enc->codec->name,31);
545
516
put_byte(pb, strlen(compressor_name));
546
517
put_buffer(pb, compressor_name, 31);
548
519
put_be16(pb, 0x18); /* Reserved */
549
520
put_be16(pb, 0xffff); /* Reserved */
550
521
if(track->enc->codec_id == CODEC_ID_MPEG4)
552
523
else if(track->enc->codec_id == CODEC_ID_H263)
553
524
mov_write_d263_tag(pb);
554
525
else if(track->enc->codec_id == CODEC_ID_SVQ3)
555
mov_write_svq3_tag(pb);
526
mov_write_svq3_tag(pb);
557
528
return updateSize (pb, pos);
560
531
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
562
int pos = url_ftell(pb);
533
offset_t pos = url_ftell(pb);
563
534
put_be32(pb, 0); /* size */
564
535
put_tag(pb, "stsd");
565
536
put_be32(pb, 0); /* version & flags */
602
573
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
604
int pos = url_ftell(pb);
575
offset_t pos = url_ftell(pb);
605
576
put_be32(pb, 0); /* size */
606
577
put_tag(pb, "stbl");
607
578
mov_write_stsd_tag(pb, track);
646
617
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
648
619
char *descr, *hdlr, *hdlr_type;
649
int pos = url_ftell(pb);
620
offset_t pos = url_ftell(pb);
651
622
if (!track) { /* no media --> data handler */
654
descr = "DataHandler";
625
descr = "DataHandler";
656
hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
657
if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
659
descr = "VideoHandler";
662
descr = "SoundHandler";
627
hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
628
if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
630
descr = "VideoHandler";
633
descr = "SoundHandler";
666
637
put_be32(pb, 0); /* size */
667
638
put_tag(pb, "hdlr");
668
639
put_be32(pb, 0); /* Version & flags */
679
650
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
681
int pos = url_ftell(pb);
652
offset_t pos = url_ftell(pb);
682
653
put_be32(pb, 0); /* size */
683
654
put_tag(pb, "minf");
684
655
if(track->enc->codec_type == CODEC_TYPE_VIDEO)
699
670
put_be32(pb, 0); /* Version & flags */
700
671
put_be32(pb, track->time); /* creation time */
701
672
put_be32(pb, track->time); /* modification time */
702
put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
673
put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
703
674
put_be32(pb, track->trackDuration); /* duration */
704
put_be16(pb, 0); /* language, 0 = english */
675
put_be16(pb, track->language); /* language */
705
676
put_be16(pb, 0); /* reserved (quality) */
709
680
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
711
int pos = url_ftell(pb);
682
offset_t pos = url_ftell(pb);
712
683
put_be32(pb, 0); /* size */
713
684
put_tag(pb, "mdia");
714
685
mov_write_mdhd_tag(pb, track);
802
773
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
804
int pos = url_ftell(pb);
775
offset_t pos = url_ftell(pb);
805
776
put_be32(pb, 0); /* size */
806
777
put_tag(pb, "trak");
807
778
mov_write_tkhd_tag(pb, track);
808
if (track->mode == MODE_PSP)
779
if (track->mode == MODE_PSP)
809
780
mov_write_edts_tag(pb, track); // PSP Movies require edts box
810
781
mov_write_mdia_tag(pb, track);
811
if (track->mode == MODE_PSP)
782
if (track->mode == MODE_PSP)
812
783
mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box
813
784
return updateSize(pb, pos);
832
803
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
834
int maxTrackID = 1, maxTrackLen = 0, i;
835
int64_t maxTrackLenTemp;
805
int maxTrackID = 1, i;
806
int64_t maxTrackLenTemp, maxTrackLen = 0;
837
808
put_be32(pb, 0x6c); /* size (always 0x6c) */
838
809
put_tag(pb, "mvhd");
881
852
static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
882
853
AVFormatContext *s)
884
int pos = url_ftell(pb);
855
offset_t pos = url_ftell(pb);
885
856
put_be32(pb, 0); /* size */
886
857
put_tag(pb, "hdlr");
898
869
static int mov_write_string_data_tag(ByteIOContext *pb, MOVContext* mov,
899
870
AVFormatContext *s, const char *data)
901
int pos = url_ftell(pb);
872
offset_t pos = url_ftell(pb);
902
873
put_be32(pb, 0); /* size */
903
874
put_tag(pb, "data");
915
886
if ( s->title[0] ) {
916
int pos = url_ftell(pb);
887
offset_t pos = url_ftell(pb);
917
888
put_be32(pb, 0); /* size */
918
889
put_tag(pb, "\251nam");
919
890
mov_write_string_data_tag(pb, mov, s, s->title);
946
917
if ( s->author[0] ) {
947
int pos = url_ftell(pb);
918
offset_t pos = url_ftell(pb);
948
919
put_be32(pb, 0); /* size */
949
920
put_tag(pb, "\251wrt");
950
921
mov_write_string_data_tag(pb, mov, s, s->author);
961
932
if ( s->album[0] ) {
962
int pos = url_ftell(pb);
933
offset_t pos = url_ftell(pb);
963
934
put_be32(pb, 0); /* size */
964
935
put_tag(pb, "\251alb");
965
936
mov_write_string_data_tag(pb, mov, s, s->album);
978
int pos = url_ftell(pb);
949
offset_t pos = url_ftell(pb);
979
950
put_be32(pb, 0); /* size */
980
951
put_tag(pb, "\251day");
981
952
snprintf(year, 5, "%04d", s->year);
989
960
static int mov_write_too_tag(ByteIOContext *pb, MOVContext* mov,
990
961
AVFormatContext *s)
992
int pos = url_ftell(pb);
963
offset_t pos = url_ftell(pb);
993
964
put_be32(pb, 0); /* size */
994
965
put_tag(pb, "\251too");
995
966
mov_write_string_data_tag(pb, mov, s, LIBAVFORMAT_IDENT);
1004
975
if ( s->comment[0] ) {
1005
int pos = url_ftell(pb);
976
offset_t pos = url_ftell(pb);
1006
977
put_be32(pb, 0); /* size */
1007
978
put_tag(pb, "\251cmt");
1008
979
mov_write_string_data_tag(pb, mov, s, s->comment);
1019
990
if ( s->genre[0] ) {
1020
int pos = url_ftell(pb);
991
offset_t pos = url_ftell(pb);
1021
992
put_be32(pb, 0); /* size */
1022
993
put_tag(pb, "\251gen");
1023
994
mov_write_string_data_tag(pb, mov, s, s->genre);
1034
1005
if ( s->track ) {
1035
int pos = url_ftell(pb);
1006
offset_t pos = url_ftell(pb);
1036
1007
put_be32(pb, 0); /* size */
1037
1008
put_tag(pb, "trkn");
1039
int pos = url_ftell(pb);
1010
offset_t pos = url_ftell(pb);
1040
1011
put_be32(pb, 0); /* size */
1041
1012
put_tag(pb, "data");
1042
1013
put_be32(pb, 0); // 8 bytes empty
1056
1027
static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
1057
1028
AVFormatContext *s)
1059
int pos = url_ftell(pb);
1030
offset_t pos = url_ftell(pb);
1060
1031
put_be32(pb, 0); /* size */
1061
1032
put_tag(pb, "ilst");
1062
1033
mov_write_nam_tag(pb, mov, s);
1080
1051
// only save meta tag if required
1081
if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
1052
if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
1082
1053
s->comment[0] || s->genre[0] || s->track ) {
1083
int pos = url_ftell(pb);
1054
offset_t pos = url_ftell(pb);
1084
1055
put_be32(pb, 0); /* size */
1085
1056
put_tag(pb, "meta");
1086
1057
put_be32(pb, 0);
1094
1065
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
1095
1066
AVFormatContext *s)
1097
int pos = url_ftell(pb);
1068
offset_t pos = url_ftell(pb);
1100
1071
put_be32(pb, 0); /* size */
1108
1079
if(mov->tracks[i].entry <= 0) continue;
1109
1080
if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
1110
1081
mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
1111
int pos = url_ftell(pb);
1082
offset_t pos = url_ftell(pb);
1112
1083
put_be32(pb, 0); /* size */
1113
1084
put_tag(pb, "\251req");
1114
1085
put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
1124
1095
if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
1126
int pos = url_ftell(pb);
1097
offset_t pos = url_ftell(pb);
1127
1098
put_be32(pb, 0); /* size */
1128
1099
put_tag(pb, "\251enc");
1129
1100
put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
1146
1117
if( s->author[0] )
1148
int pos = url_ftell(pb);
1119
offset_t pos = url_ftell(pb);
1149
1120
put_be32(pb, 0); /* size */
1150
1121
put_tag(pb, /*"\251aut"*/ "\251day" );
1151
1122
put_be16(pb, strlen(s->author)); /* string length */
1168
1139
return updateSize(pb, pos);
1143
static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n)
1147
for (i = 0; i < n - 1; i++) {
1149
if (! (0x20 <= c && c <= 0x7f ))
1157
static uint16_t language_code (char *str)
1159
return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F));
1162
static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
1165
offset_t pos, curpos;
1169
pos = url_ftell(pb);
1170
put_be32(pb, 0); /* size placeholder*/
1171
put_tag(pb, "uuid");
1172
put_tag(pb, "USMT");
1173
put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
1174
put_be32(pb, 0xbb88695c );
1175
put_be32(pb, 0xfac9c740 );
1178
put_be32(pb, 0); /* size placeholder*/
1179
put_tag(pb, "MTDT");
1184
len = strlen(s->title)+1;
1185
put_be16(pb, len*2+10); /* size */
1186
put_be32(pb, 0x01); /* type */
1187
put_be16(pb, language_code("und")); /* language */
1188
put_be16(pb, 0x01); /* ? */
1189
ascii_to_wc (pb, s->title, len);
1193
curpos = url_ftell(pb);
1194
url_fseek(pb, pos, SEEK_SET);
1196
url_fseek(pb, pos+24, SEEK_SET);
1197
put_be32(pb, size-24);
1198
url_fseek(pb, curpos, SEEK_SET);
1171
1204
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1172
1205
AVFormatContext *s)
1175
pos = url_ftell(pb);
1208
offset_t pos = url_ftell(pb);
1176
1209
put_be32(pb, 0); /* size placeholder*/
1177
1210
put_tag(pb, "moov");
1178
1211
mov->timescale = globalTimescale;
1199
mov->tracks[i].trackDuration =
1232
mov->tracks[i].trackDuration =
1200
1233
mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
1201
1234
mov->tracks[i].time = mov->time;
1202
1235
mov->tracks[i].trackID = i+1;
1246
if (mov->mode == MODE_PSP)
1247
mov_write_uuidusmt_tag(pb, s);
1213
1249
mov_write_udta_tag(pb, mov, s);
1215
1251
return updateSize(pb, pos);
1218
1254
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
1220
mov->mdat_pos = url_ftell(pb);
1256
put_be32(pb, 8); // placeholder for extended size field (64 bit)
1257
put_tag(pb, "wide");
1259
mov->mdat_pos = url_ftell(pb);
1221
1260
put_be32(pb, 0); /* size placeholder*/
1222
1261
put_tag(pb, "mdat");
1226
1265
/* TODO: This needs to be more general */
1227
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
1266
static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
1229
1268
MOVContext *mov = s->priv_data;
1250
1289
put_tag(pb, "MSNV");
1252
1291
put_tag(pb, "mp41");
1257
1294
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1259
int AudioRate = s->streams[1]->codec->sample_rate;
1260
int FrameRate = ((s->streams[0]->codec->time_base.den) * (0x10000))/ (s->streams[0]->codec->time_base.num);
1262
//printf("audiorate = %d\n",AudioRate);
1263
//printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec->time_base.den,s->streams[0]->codec->time_base.num,FrameRate);
1296
AVCodecContext *VideoCodec = s->streams[0]->codec;
1297
AVCodecContext *AudioCodec = s->streams[1]->codec;
1298
int AudioRate = AudioCodec->sample_rate;
1299
int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
1265
1301
put_be32(pb, 0x94 ); /* size */
1266
1302
put_tag(pb, "uuid");
1282
1318
put_be32(pb, 0x2c ); /* size */
1283
1319
put_tag(pb, "APRF"); /* audio */
1284
1320
put_be32(pb, 0x0 );
1321
put_be32(pb, 0x2 ); /* TrackID */
1286
1322
put_tag(pb, "mp4a");
1287
1323
put_be32(pb, 0x20f );
1288
1324
put_be32(pb, 0x0 );
1289
put_be32(pb, 0x40 );
1290
put_be32(pb, 0x40 );
1291
put_be32(pb, AudioRate ); //24000 ... audio rate?
1325
put_be32(pb, AudioCodec->bit_rate / 1000);
1326
put_be32(pb, AudioCodec->bit_rate / 1000);
1327
put_be32(pb, AudioRate );
1328
put_be32(pb, AudioCodec->channels );
1294
1330
put_be32(pb, 0x34 ); /* size */
1295
1331
put_tag(pb, "VPRF"); /* video */
1296
1332
put_be32(pb, 0x0 );
1333
put_be32(pb, 0x1 ); /* TrackID */
1298
1334
put_tag(pb, "mp4v");
1299
1335
put_be32(pb, 0x103 );
1300
1336
put_be32(pb, 0x0 );
1301
put_be32(pb, 0xc0 );
1302
put_be32(pb, 0xc0 );
1303
put_be32(pb, FrameRate); // was 0xefc29
1304
put_be32(pb, FrameRate ); // was 0xefc29
1305
put_be16(pb, s->streams[0]->codec->width);
1306
put_be16(pb, s->streams[0]->codec->height);
1307
put_be32(pb, 0x010001 );
1337
put_be32(pb, VideoCodec->bit_rate / 1000);
1338
put_be32(pb, VideoCodec->bit_rate / 1000);
1339
put_be32(pb, FrameRate);
1340
put_be32(pb, FrameRate);
1341
put_be16(pb, VideoCodec->width);
1342
put_be16(pb, VideoCodec->height);
1343
put_be32(pb, 0x010001); /* ? */
1310
1346
static int mov_write_header(AVFormatContext *s)
1331
1367
av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
1370
/* don't know yet if mp4 or not */
1371
mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, 1);
1336
1374
/* Default mode == MP4 */
1394
1432
else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1395
1433
samplesInChunk = size/enc->channels;
1397
else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1398
samplesInChunk = size/(2*enc->channels);
1435
else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1436
samplesInChunk = size/(2*enc->channels);
1401
1439
samplesInChunk = 1;
1415
1453
id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1417
1455
if (trk->ents_allocated <= trk->entry) {
1418
trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
1456
trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
1419
1457
if (!trk->cluster)
1421
1459
trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1464
1503
j += mov->tracks[i].mdat_size;
1467
url_fseek(pb, mov->mdat_pos, SEEK_SET);
1506
if (j+8 <= UINT32_MAX) {
1507
url_fseek(pb, mov->mdat_pos, SEEK_SET);
1510
/* overwrite 'wide' placeholder atom */
1511
url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
1512
put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
1513
put_tag(pb, "mdat");
1469
1516
url_fseek(pb, moov_pos, SEEK_SET);
1471
1518
mov_write_moov_tag(pb, mov, s);