📄 movenc.c.svn-base
字号:
put_be32(pb, track->time); /* creation time */ put_be32(pb, track->time); /* modification time */ } put_be32(pb, track->trackID); /* track-id */ put_be32(pb, 0); /* reserved */ (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration); put_be32(pb, 0); /* reserved */ put_be32(pb, 0); /* reserved */ put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */ /* Volume, only for audio */ if(track->enc->codec_type == CODEC_TYPE_AUDIO) put_be16(pb, 0x0100); else put_be16(pb, 0); put_be16(pb, 0); /* reserved */ /* Matrix structure */ put_be32(pb, 0x00010000); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x00010000); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x40000000); /* reserved */ /* Track width and height, for visual only */ if(track->enc->codec_type == CODEC_TYPE_VIDEO) { double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio); if(!sample_aspect_ratio) sample_aspect_ratio = 1; put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000); put_be32(pb, track->enc->height*0x10000); } else { put_be32(pb, 0); put_be32(pb, 0); } return 0x5c;}// This box seems important for the psp playback ... without it the movie seems to hangstatic int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track){ put_be32(pb, 0x24); /* size */ put_tag(pb, "edts"); put_be32(pb, 0x1c); /* size */ put_tag(pb, "elst"); put_be32(pb, 0x0); put_be32(pb, 0x1); put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration ... doesn't seem to effect psp */ put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */ put_be32(pb, 0x00010000); return 0x24;}// goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov){ put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */ put_tag(pb, "uuid"); put_tag(pb, "USMT"); put_be32(pb, 0x21d24fce); put_be32(pb, 0xbb88695c); put_be32(pb, 0xfac9c740); put_be32(pb, 0x1c); // another size here! put_tag(pb, "MTDT"); put_be32(pb, 0x00010012); put_be32(pb, 0x0a); put_be32(pb, 0x55c40000); put_be32(pb, 0x1); put_be32(pb, 0x0); return 0x34;}static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track){ offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "trak"); mov_write_tkhd_tag(pb, track); if (track->mode == MODE_PSP || track->hasBframes) mov_write_edts_tag(pb, track); // PSP Movies require edts box mov_write_mdia_tag(pb, track); if (track->mode == MODE_PSP) mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box return updateSize(pb, pos);}#if 0/* TODO: Not sorted out, but not necessary either */static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov){ put_be32(pb, 0x15); /* size */ put_tag(pb, "iods"); put_be32(pb, 0); /* version & flags */ put_be16(pb, 0x1007); put_byte(pb, 0); put_be16(pb, 0x4fff); put_be16(pb, 0xfffe); put_be16(pb, 0x01ff); return 0x15;}#endifstatic int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov){ int maxTrackID = 1, i; int64_t maxTrackLenTemp, maxTrackLen = 0; int version; for (i=0; i<mov->nb_streams; i++) { if(mov->tracks[i].entry > 0) { maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP); if(maxTrackLen < maxTrackLenTemp) maxTrackLen = maxTrackLenTemp; if(maxTrackID < mov->tracks[i].trackID) maxTrackID = mov->tracks[i].trackID; } } version = maxTrackLen < UINT32_MAX ? 0 : 1; (version == 1) ? put_be32(pb, 120) : put_be32(pb, 108); /* size */ put_tag(pb, "mvhd"); put_byte(pb, version); put_be24(pb, 0); /* flags */ if (version == 1) { put_be64(pb, mov->time); put_be64(pb, mov->time); } else { put_be32(pb, mov->time); /* creation time */ put_be32(pb, mov->time); /* modification time */ } put_be32(pb, mov->timescale); /* timescale */ (version == 1) ? put_be64(pb, maxTrackLen) : put_be32(pb, maxTrackLen); /* duration of longest track */ put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */ put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */ put_be16(pb, 0); /* reserved */ put_be32(pb, 0); /* reserved */ put_be32(pb, 0); /* reserved */ /* Matrix structure */ put_be32(pb, 0x00010000); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x00010000); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x0); /* reserved */ put_be32(pb, 0x40000000); /* reserved */ put_be32(pb, 0); /* reserved (preview time) */ put_be32(pb, 0); /* reserved (preview duration) */ put_be32(pb, 0); /* reserved (poster time) */ put_be32(pb, 0); /* reserved (selection time) */ put_be32(pb, 0); /* reserved (selection duration) */ put_be32(pb, 0); /* reserved (current time) */ put_be32(pb, maxTrackID+1); /* Next track id */ return 0x6c;}static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov, AVFormatContext *s){ offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "hdlr"); put_be32(pb, 0); put_be32(pb, 0); put_tag(pb, "mdir"); put_tag(pb, "appl"); put_be32(pb, 0); put_be32(pb, 0); put_be16(pb, 0); return updateSize(pb, pos);}/* helper function to write a data tag with the specified string as data */static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int long_style){ if(long_style){ offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "data"); put_be32(pb, 1); put_be32(pb, 0); put_buffer(pb, data, strlen(data)); return updateSize(pb, pos); }else{ put_be16(pb, strlen(data)); /* string length */ put_be16(pb, 0); put_buffer(pb, data, strlen(data)); return strlen(data) + 4; }}static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int long_style){ int size = 0; if (value && value[0]) { offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, name); mov_write_string_data_tag(pb, value, long_style); size= updateSize(pb, pos); } return size;}/* iTunes year */static int mov_write_day_tag(ByteIOContext *pb, int year, int long_style){ if(year){ char year_str[5]; snprintf(year_str, sizeof(year_str), "%04d", year); return mov_write_string_tag(pb, "\251day", year_str, long_style); }else return 0;}/* iTunes track number */static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov, AVFormatContext *s){ int size = 0; if (s->track) { offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "trkn"); { offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "data"); put_be32(pb, 0); // 8 bytes empty put_be32(pb, 0); put_be16(pb, 0); // empty put_be16(pb, s->track); // track number put_be16(pb, 0); // total track number put_be16(pb, 0); // empty updateSize(pb, pos); } size = updateSize(pb, pos); } return size;}/* iTunes meta data list */static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov, AVFormatContext *s){ offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "ilst"); mov_write_string_tag(pb, "\251nam", s->title , 1); mov_write_string_tag(pb, "\251ART", s->author , 1); mov_write_string_tag(pb, "\251wrt", s->author , 1); mov_write_string_tag(pb, "\251alb", s->album , 1); mov_write_day_tag(pb, s->year ,1); if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT)) mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 1); mov_write_string_tag(pb, "\251cmt", s->comment , 1); mov_write_string_tag(pb, "\251gen", s->genre , 1); mov_write_trkn_tag(pb, mov, s); return updateSize(pb, pos);}/* iTunes meta data tag */static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov, AVFormatContext *s){ int size = 0; // only save meta tag if required if (s->title[0] || s->author[0] || s->album[0] || s->year || s->comment[0] || s->genre[0] || s->track) { offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "meta"); put_be32(pb, 0); mov_write_itunes_hdlr_tag(pb, mov, s); mov_write_ilst_tag(pb, mov, s); size = updateSize(pb, pos); } return size;}static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov, AVFormatContext *s){ int i, req = 0; /* Requirements */ for (i=0; i<mov->nb_streams; i++) { if(mov->tracks[i].entry <= 0) continue; if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC || mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) { req = 1; break; } } if (s->title[0] || s->author[0] || s->album[0] || s->year || s->comment[0] || s->genre[0] || s->track || (mov->mode == MODE_MOV && ((mov->tracks[0].enc && !mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT) || req))) { offset_t pos = url_ftell(pb); put_be32(pb, 0); /* size */ put_tag(pb, "udta"); /* iTunes meta data */ mov_write_meta_tag(pb, mov, s); if(mov->mode == MODE_MOV){ // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4 /* Requirements */ if (req) mov_write_string_tag(pb, "\251req", "QuickTime 6.0 or greater", 0); mov_write_string_tag(pb, "\251nam", s->title , 0); mov_write_string_tag(pb, "\251aut", s->author , 0); mov_write_string_tag(pb, "\251alb", s->album , 0); mov_write_day_tag(pb, s->year, 0); if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT)) mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0); mov_write_string_tag(pb, "\251des", s->comment , 0); mov_write_string_tag(pb, "\251gen", s->genre , 0); } return updateSize(pb, pos); } return 0;}static int utf8len(const uint8_t *b){ int len=0; int val; while(*b){ GET_UTF8(val, *b++, return -1;) len++; } return len;}static int ascii_to_wc (ByteIOContext *pb, const uint8_t *b){ int val; while(*b){ GET_UTF8(val, *b++, return -1;) put_be16(pb, val); } put_be16(pb, 0x00); return 0;}static uint16_t language_code (const char *str){ return ((((str[0]-0x60) & 0x1F)<<10) + (((str[1]-0x60) & 0x1F)<<5) + ((str[2]-0x60) & 0x1F));}static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s){ size_t len, size; offset_t pos, curpos; size = 0; if (s->title[0]) { pos = url_ftell(pb); put_be32(pb, 0); /* size placeholder*/ put_tag(pb, "uuid"); put_tag(pb, "USMT"); put_be32(pb, 0x21d24fce); /* 96 bit UUID */ put_be32(pb, 0xbb88695c); put_be32(pb, 0xfac9c740); size += 24; put_be32(pb, 0); /* size placeholder*/ put_tag(pb, "MTDT"); put_be16(pb, 4); size += 10; // ? put_be16(pb, 0x0C); /* size */ put_be32(pb, 0x0B); /* type */ put_be16(pb, language_code("und")); /* language */ put_be16(pb, 0x0); /* ? */ put_be16(pb, 0x021C); /* data */ size += 12; // Encoder len = utf8len(LIBAVCODEC_IDENT)+1; if(len<=0) goto not_utf8; put_be16(pb, len*2+10); /* size */ put_be32(pb, 0x04); /* type */ put_be16(pb, language_code("eng")); /* language */ put_be16(pb, 0x01); /* ? */ ascii_to_wc(pb, LIBAVCODEC_IDENT); size += len*2+10; // Title len = utf8len(s->title)+1; if(len<=0) goto not_utf8; put_be16(pb, len*2+10); /* size */ put_be32(pb, 0x01); /* type */ put_be16(pb, language_code("eng")); /* language */ put_be16(pb, 0x01); /* ? */ ascii_to_wc (pb, s->title); size += len*2+10; // Date// snprintf(dt,32,"%04d/%02d/%02d %02d:%02d:%02d",t_st->tm_year+1900,t_st->tm_mon+1,t_st->tm_mday,t_st->tm_hour,t_st->tm_min,t_st->tm_sec); len = utf8len("2006/04/01 11:11:11")+1; if(len<=0) goto not_utf8; put_be16(pb, len*2+10); /* size */ put_be32(pb, 0x03); /* type */ put_be16(pb, language_code("und")); /* language */ put_be16(pb, 0x01); /* ? */ ascii_to_wc (pb, "2006/04/01 11:11:11"); size += len*2+10; // size curpos = url_ftell(pb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -