diff --git a/Changelog b/Changelog index cdb1e89d08..bc4e3b0b8c 100644 --- a/Changelog +++ b/Changelog @@ -112,6 +112,7 @@ version - AVM2 (Flash 9) SWF muxer - QT variant of IMA ADPCM encoder - VFW grabber +- Ipod/Iphone compatible mp4 muxer version 0.4.9-pre1: diff --git a/libavformat/Makefile b/libavformat/Makefile index 3edeb53b4d..8b72d2e1d9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -63,6 +63,7 @@ OBJS-$(CONFIG_H263_MUXER) += raw.o OBJS-$(CONFIG_H264_DEMUXER) += raw.o OBJS-$(CONFIG_H264_MUXER) += raw.o OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o +OBJS-$(CONFIG_IPOD_MUXER) += movenc.o riff.o isom.o avc.o OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2.o OBJS-$(CONFIG_IMAGE2_MUXER) += img2.o OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 5cafd6209d..97b9b9b1ce 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -90,6 +90,7 @@ void av_register_all(void) REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe); REGISTER_DEMUXER (INGENIENT, ingenient); REGISTER_DEMUXER (IPMOVIE, ipmovie); + REGISTER_MUXER (IPOD, ipod); REGISTER_DEMUXER (LMLM4, lmlm4); REGISTER_MUXDEMUX (M4V, m4v); REGISTER_MUXDEMUX (MATROSKA, matroska); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 7933cbb9e2..fa6687f316 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -22,7 +22,7 @@ #define FFMPEG_AVFORMAT_H #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 9 +#define LIBAVFORMAT_VERSION_MINOR 10 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 501c44ebdf..57e0f8125f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -37,6 +37,7 @@ #define MODE_PSP 3 // example working PSP command line: // ffmpeg -i testinput.avi -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4 #define MODE_3G2 4 +#define MODE_IPOD 5 typedef struct MOVIentry { unsigned int flags, size; @@ -494,7 +495,7 @@ static const AVCodecTag mov_pix_fmt_tags[] = { static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag = track->enc->codec_tag; - if (track->mode == MODE_MP4 || track->mode == MODE_PSP) { + if (track->mode == MODE_MP4 || track->mode == MODE_PSP || track->mode == MODE_IPOD) { if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id)) return 0; if (track->enc->codec_id == CODEC_ID_H264) tag = MKTAG('a','v','c','1'); @@ -541,6 +542,22 @@ static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } +/** Write uuid atom. + * Needed to make file play in iPods running newest firmware + * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1 + */ +static int mov_write_uuid_tag_ipod(ByteIOContext *pb) +{ + put_be32(pb, 28); + put_tag(pb, "uuid"); + put_be32(pb, 0x6b6840f2); + put_be32(pb, 0x5f244fc5); + put_be32(pb, 0xba39a51b); + put_be32(pb, 0xcf0323f3); + put_be32(pb, 0x0); + return 28; +} + static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track) { offset_t pos = url_ftell(pb); @@ -593,8 +610,11 @@ static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track) mov_write_d263_tag(pb); else if(track->enc->codec_id == CODEC_ID_SVQ3) mov_write_svq3_tag(pb); - else if(track->enc->codec_id == CODEC_ID_H264) + else if(track->enc->codec_id == CODEC_ID_H264) { mov_write_avcc_tag(pb, track); + if(track->mode == MODE_IPOD) + mov_write_uuid_tag_ipod(pb); + } else if(track->enc->codec_id == CODEC_ID_DNXHD) mov_write_avid_tag(pb, track); else if(track->vosLen > 0) @@ -1355,7 +1375,7 @@ static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s) put_tag(pb, "3g2a"); else if (mov->mode == MODE_PSP) put_tag(pb, "MSNV"); - else if (mov->mode == MODE_MP4) + else if (mov->mode == MODE_MP4 || mov->mode == MODE_IPOD) put_tag(pb, "isom"); else put_tag(pb, "qt "); @@ -1368,7 +1388,7 @@ static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s) put_tag(pb, "3g2a"); else if (mov->mode == MODE_PSP) put_tag(pb, "MSNV"); - else if (mov->mode == MODE_MP4) + else if (mov->mode == MODE_MP4 || mov->mode == MODE_IPOD) put_tag(pb, "mp41"); else put_tag(pb, "qt "); @@ -1454,6 +1474,7 @@ static int mov_write_header(AVFormatContext *s) else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2; else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; + else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD; mov_write_ftyp_tag(pb,s); if (mov->mode == MODE_PSP) { @@ -1710,3 +1731,19 @@ AVOutputFormat tg2_muxer = { .codec_tag = (const AVCodecTag*[]){codec_3gp_tags, 0}, }; #endif +#ifdef CONFIG_IPOD_MUXER +AVOutputFormat ipod_muxer = { + "ipod", + "iPod H.264 mp4 format", + "application/mp4", + NULL, + sizeof(MOVContext), + CODEC_ID_AAC, + CODEC_ID_H264, + mov_write_header, + mov_write_packet, + mov_write_trailer, + .flags = AVFMT_GLOBALHEADER, + .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0}, +}; +#endif