From ff4de6856e075f438d8ede1a869ef0a955d6d8db Mon Sep 17 00:00:00 2001 From: titer Date: Sun, 26 Mar 2006 19:51:36 +0000 Subject: [PATCH] Rewrote muxmp4 to use avformat - works more or less, and only with MPEG-4 yet git-svn-id: svn://svn.handbrake.fr/HandBrake/branches/avformat@50 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- Jamfile | 8 +-- configure | 1 + contrib/Jamfile | 14 +++- libhb/muxmp4.c | 186 +++++++++++++++++++++++++++--------------------- 4 files changed, 123 insertions(+), 86 deletions(-) diff --git a/Jamfile b/Jamfile index 8066a1bd9..fb1229ab2 100644 --- a/Jamfile +++ b/Jamfile @@ -8,10 +8,10 @@ SubDir TOP ; # libhb + contrib libraries HB_LIBS = libhb.a - contrib/lib/liba52.a contrib/lib/libavcodec.a - contrib/lib/libavutil.a contrib/lib/libdvdread.a - contrib/lib/libdvdcss.a contrib/lib/libfaac.a - contrib/lib/libmp3lame.a contrib/lib/libmp4v2.a + contrib/lib/liba52.a contrib/lib/libavformat.a + contrib/lib/libavcodec.a contrib/lib/libavutil.a + contrib/lib/libdvdread.a contrib/lib/libdvdcss.a + contrib/lib/libfaac.a contrib/lib/libmp3lame.a contrib/lib/libmpeg2.a contrib/lib/libvorbis.a contrib/lib/libvorbisenc.a contrib/lib/libogg.a contrib/lib/libsamplerate.a contrib/lib/libx264.a diff --git a/configure b/configure index d0c292873..abe2b1779 100755 --- a/configure +++ b/configure @@ -4,6 +4,7 @@ CC="gcc" CXX="g++" CCFLAGS="$CCFLAGS -Wall -g" OPTIM="$OPTIM -O3 -funroll-loops" +LINKLIBS="-lz" # System-specific flags SYSTEM=`uname -s` diff --git a/contrib/Jamfile b/contrib/Jamfile index 3271a46ee..fc68ae440 100644 --- a/contrib/Jamfile +++ b/contrib/Jamfile @@ -60,8 +60,9 @@ actions LibAvCodec rm -rf ffmpeg && tar xzf ffmpeg.tar.gz && cd ffmpeg && $(FFMPEG_PATCH) && ./configure --prefix=$CONTRIB $(FFMPEG_OPTIONS) --enable-gpl && - make -C libavcodec && make -C libavutil && + make -C libavcodec && make -C libavutil && make -C libavformat && make -C libavcodec installlib && make -C libavutil installlib && + make -C libavformat installlib strip -S $CONTRIB/lib/libavcodec.a } Wget $(SUBDIR)/ffmpeg.tar.gz : $(SUBDIR)/version_ffmpeg.txt ; @@ -78,6 +79,17 @@ actions LibAvUtil } LibAvUtil $(SUBDIR)/lib/libavutil.a : $(SUBDIR)/lib/libavcodec.a ; +rule LibAvFormat +{ + Depends $(<) : $(>) ; + Depends lib : $(<) ; +} +actions LibAvFormat +{ + strip -S $(<) +} +LibAvUtil $(SUBDIR)/lib/libavformat.a : $(SUBDIR)/lib/libavcodec.a ; + # libdvdcss # We need libdvdcss.so for libdvdread's configure to work... rule LibDvdCss diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index d5002fa4a..b992027e3 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -4,27 +4,28 @@ Homepage: . It may be used under the terms of the GNU General Public License. */ -/* libmp4v2 header */ -#include "mp4.h" +#include #include "hb.h" + +static inline int ff_get_fourcc(const char *s) +{ + return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24); +} + struct hb_mux_object_s { HB_MUX_COMMON; hb_job_t * job; - /* libmp4v2 handle */ - MP4FileHandle file; - - /* Cumulated durations so far, in timescale units (see MP4Mux) */ - uint64_t sum_dur; + AVFormatContext * format; }; struct hb_mux_data_s { - MP4TrackId track; + int track; }; /********************************************************************** @@ -41,107 +42,130 @@ static int MP4Init( hb_mux_object_t * m ) hb_mux_data_t * mux_data; int i; - /* Create an empty mp4 file */ - m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 ); - - /* Video track */ - mux_data = malloc( sizeof( hb_mux_data_t ) ); - job->mux_data = mux_data; + register_protocol(&file_protocol); + movenc_init(); - /* When using the standard 90000 timescale, QuickTime tends to have - synchronization issues (audio not playing at the correct speed). - To workaround this, we use the audio samplerate as the - timescale */ - MP4SetTimeScale( m->file, job->arate ); + AVFormatContext * oc = av_alloc_format_context(); - if( job->vcodec == HB_VCODEC_X264 ) + oc->oformat = guess_format( "mp4", NULL, NULL ); + if( !oc->oformat ) { - /* Stolen from mp4creator */ - MP4SetVideoProfileLevel( m->file, 0x7F ); - - mux_data->track = MP4AddH264VideoTrack( m->file, job->arate, - MP4_INVALID_DURATION, job->width, job->height, - job->config.h264.sps[1], /* AVCProfileIndication */ - job->config.h264.sps[2], /* profile_compat */ - job->config.h264.sps[3], /* AVCLevelIndication */ - 3 ); /* 4 bytes length before each NAL unit */ - - MP4AddH264SequenceParameterSet( m->file, mux_data->track, - job->config.h264.sps, job->config.h264.sps_length ); - MP4AddH264PictureParameterSet( m->file, mux_data->track, - job->config.h264.pps, job->config.h264.pps_length ); + hb_log( "guess_format failed" ); + return 1; } - else /* FFmpeg or XviD */ + snprintf( oc->filename, sizeof( oc->filename ), + "%s", job->file ); + + AVStream *st; + + st = av_new_stream( oc, oc->nb_streams ); + if( !st ) { - MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 ); - mux_data->track = MP4AddVideoTrack( m->file, job->arate, - MP4_INVALID_DURATION, job->width, job->height, - MP4_MPEG4_VIDEO_TYPE ); - - /* VOL from FFmpeg or XviD */ - MP4SetTrackESConfiguration( m->file, mux_data->track, - job->config.mpeg4.bytes, job->config.mpeg4.length ); + hb_log( "av_new_stream failed" ); + return 1; } + st->stream_copy = 1; + st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; + st->codec->codec_type = CODEC_TYPE_VIDEO; + st->codec->codec_id = CODEC_ID_MPEG4; + st->codec->bit_rate = 1000 * job->vbitrate; + st->codec->extradata= job->config.mpeg4.bytes; + st->codec->extradata_size= job->config.mpeg4.length; + st->codec->time_base = (AVRational){ job->vrate_base, job->vrate }; + + st->codec->pix_fmt = PIX_FMT_YUV420P; + st->codec->width = job->width; + st->codec->height = job->height; + st->codec->has_b_frames = 0; + + job->mux_data = malloc( sizeof( hb_mux_data_t ) ); + job->mux_data->track = 0; for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - mux_data = malloc( sizeof( hb_mux_data_t ) ); - audio->mux_data = mux_data; - - mux_data->track = MP4AddAudioTrack( m->file, - job->arate, 1024, MP4_MPEG4_AUDIO_TYPE ); - MP4SetAudioProfileLevel( m->file, 0x0F ); - MP4SetTrackESConfiguration( m->file, mux_data->track, - audio->config.aac.bytes, audio->config.aac.length ); + + audio->mux_data = malloc( sizeof( hb_mux_data_t ) ); + audio->mux_data->track = i + 1; + + st = av_new_stream( oc, oc->nb_streams ); + if( !st ) + { + hb_log( "av_new_stream failed" ); + return 1; + } + st->stream_copy = 1; + st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; + st->codec->codec_type = CODEC_TYPE_AUDIO; + st->codec->codec_id = CODEC_ID_AAC; + st->codec->bit_rate = 1000 * job->abitrate; + st->codec->extradata= audio->config.aac.bytes; + st->codec->extradata_size= audio->config.aac.length; + st->codec->time_base = (AVRational){ 1, job->arate }; + st->codec->channels = 2; + st->codec->sample_rate = job->arate; + st->codec->frame_size = 1024; + st->codec->block_align = 0; + } + + oc->timestamp = 0; + if( url_fopen( &oc->pb, job->file, URL_WRONLY ) < 0 ) + { + hb_log( "url_fopen failed (%s)", job->file ); + return 1; } + AVFormatParameters params; + memset( ¶ms, 0, sizeof( params ) ); + if( av_set_parameters( oc, ¶ms ) < 0 ) + { + hb_log( "av_set_parameters failed" ); + return 1; + } + + oc->packet_size= 0; + oc->mux_rate= 0; + oc->preload= (int)(0.5*AV_TIME_BASE); + oc->max_delay= (int)(0.7*AV_TIME_BASE); + oc->loop_output = AVFMT_NOOUTPUTLOOP; + + if( av_write_header( oc ) < 0 ) + { + hb_log( "av_write_header failed" ); + return 1; + } + + m->format = oc; + return 0; } static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, hb_buffer_t * buf ) { - hb_job_t * job = m->job; + AVPacket pkt; + av_init_packet(&pkt); - uint64_t duration; + pkt.stream_index = mux_data->track; + pkt.data = buf->data; + pkt.size = buf->size; + pkt.pts = buf->start; - if( mux_data == job->mux_data ) + if( buf->key ) { - /* Video */ - /* Because we use the audio samplerate as the timescale, - we have to use potentially variable durations so the video - doesn't go out of sync */ - duration = ( buf->stop * job->arate / 90000 ) - m->sum_dur; - m->sum_dur += duration; - } - else - { - /* Audio */ - duration = MP4_INVALID_DURATION; + pkt.flags |= PKT_FLAG_KEY; } - MP4WriteSample( m->file, mux_data->track, buf->data, buf->size, - duration, 0, buf->key ); + av_interleaved_write_frame( m->format, &pkt ); + return 0; } static int MP4End( hb_mux_object_t * m ) { -#if 0 - hb_job_t * job = m->job; -#endif - char filename[1024]; memset( filename, 0, 1024 ); - - MP4Close( m->file ); - -#if 0 - hb_log( "muxmp4: optimizing file" ); - snprintf( filename, 1024, "%s.tmp", job->file ); - MP4Optimize( job->file, filename, MP4_DETAILS_ERROR ); - remove( job->file ); - rename( filename, job->file ); -#endif + av_write_trailer( m->format ); + url_fclose( &m->format->pb ); + av_free( m->format ); return 0; } -- 2.40.0