Moves the filters' logging info to work.c, adds parameter info. I also changed the...
[HandBrake.git] / libhb / encavcodec.c
blob7bccfc7598f419e8c3675ed625dda75f84521e77
1 /* $Id: encavcodec.c,v 1.23 2005/10/13 23:47:06 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include "hb.h"
9 #include "ffmpeg/avcodec.h"
11 struct hb_work_private_s
13 hb_job_t * job;
14 AVCodecContext * context;
15 FILE * file;
18 int encavcodecInit( hb_work_object_t *, hb_job_t * );
19 int encavcodecWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
20 void encavcodecClose( hb_work_object_t * );
22 hb_work_object_t hb_encavcodec =
24 WORK_ENCAVCODEC,
25 "MPEG-4 encoder (libavcodec)",
26 encavcodecInit,
27 encavcodecWork,
28 encavcodecClose
29 };
31 int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
33 AVCodec * codec;
34 AVCodecContext * context;
36 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
37 w->private_data = pv;
39 pv->job = job;
41 codec = avcodec_find_encoder( CODEC_ID_MPEG4 );
42 if( !codec )
44 hb_log( "hb_work_encavcodec_init: avcodec_find_encoder "
45 "failed" );
47 context = avcodec_alloc_context();
48 if( job->vquality < 0.0 || job->vquality > 1.0 )
50 /* Rate control */
51 context->bit_rate = 1000 * job->vbitrate;
52 context->bit_rate_tolerance = 10 * context->bit_rate;
54 else
56 /* Constant quantizer */
57 context->qmin = 31 - job->vquality * 30;
58 context->qmax = context->qmin;
59 hb_log( "encavcodec: encoding at constant quantizer %d",
60 context->qmin );
62 context->width = job->width;
63 context->height = job->height;
64 context->time_base = (AVRational) { job->vrate_base, job->vrate };
65 context->gop_size = 10 * job->vrate / job->vrate_base;
66 context->pix_fmt = PIX_FMT_YUV420P;
68 if( job->pixel_ratio )
70 context->sample_aspect_ratio.num = job->pixel_aspect_width;
71 context->sample_aspect_ratio.den = job->pixel_aspect_height;
73 hb_log( "encavcodec: encoding with stored aspect %d/%d",
74 job->pixel_aspect_width, job->pixel_aspect_height );
77 if( job->mux & ( HB_MUX_MP4 | HB_MUX_PSP ) )
79 context->flags |= CODEC_FLAG_GLOBAL_HEADER;
81 if( job->mux & HB_MUX_PSP )
83 context->flags |= CODEC_FLAG_BITEXACT;
85 if( job->grayscale )
87 context->flags |= CODEC_FLAG_GRAY;
90 if( job->pass )
92 char filename[1024]; memset( filename, 0, 1024 );
93 hb_get_tempory_filename( job->h, filename, "ffmpeg.log" );
95 if( job->pass == 1 )
97 pv->file = fopen( filename, "wb" );
98 context->flags |= CODEC_FLAG_PASS1;
100 else
102 int size;
103 char * log;
105 pv->file = fopen( filename, "rb" );
106 fseek( pv->file, 0, SEEK_END );
107 size = ftell( pv->file );
108 fseek( pv->file, 0, SEEK_SET );
109 log = malloc( size + 1 );
110 log[size] = '\0';
111 fread( log, size, 1, pv->file );
112 fclose( pv->file );
113 pv->file = NULL;
115 context->flags |= CODEC_FLAG_PASS2;
116 context->stats_in = log;
120 if( avcodec_open( context, codec ) )
122 hb_log( "hb_work_encavcodec_init: avcodec_open failed" );
124 pv->context = context;
126 if( ( job->mux & ( HB_MUX_MP4 | HB_MUX_PSP ) ) && job->pass != 1 )
128 #if 0
129 /* Hem hem */
130 w->config->mpeg4.length = 15;
131 memcpy( w->config->mpeg4.bytes, context->extradata + 15, 15 );
132 #else
133 w->config->mpeg4.length = context->extradata_size;
134 memcpy( w->config->mpeg4.bytes, context->extradata,
135 context->extradata_size );
136 #endif
139 return 0;
142 /***********************************************************************
143 * Close
144 ***********************************************************************
146 **********************************************************************/
147 void encavcodecClose( hb_work_object_t * w )
149 hb_work_private_t * pv = w->private_data;
151 if( pv->context )
153 hb_log( "encavcodec: closing libavcodec" );
154 avcodec_flush_buffers( pv->context );
155 avcodec_close( pv->context );
157 if( pv->file )
159 fclose( pv->file );
161 free( pv );
162 w->private_data = NULL;
165 /***********************************************************************
166 * Work
167 ***********************************************************************
169 **********************************************************************/
170 int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
171 hb_buffer_t ** buf_out )
173 hb_work_private_t * pv = w->private_data;
174 hb_job_t * job = pv->job;
175 AVFrame * frame;
176 hb_buffer_t * in = *buf_in, * buf;
178 if(!in->data)
180 *buf_out = NULL;
181 return HB_WORK_DONE;
184 frame = avcodec_alloc_frame();
185 frame->data[0] = in->data;
186 frame->data[1] = frame->data[0] + job->width * job->height;
187 frame->data[2] = frame->data[1] + job->width * job->height / 4;
188 frame->linesize[0] = job->width;
189 frame->linesize[1] = job->width / 2;
190 frame->linesize[2] = job->width / 2;
192 /* Should be way too large */
193 buf = hb_buffer_init( 3 * job->width * job->height / 2 );
194 buf->size = avcodec_encode_video( pv->context, buf->data, buf->alloc,
195 frame );
196 buf->start = in->start;
197 buf->stop = in->stop;
198 buf->frametype = pv->context->coded_frame->key_frame ? HB_FRAME_KEY : HB_FRAME_REF;
200 av_free( frame );
202 if( job->pass == 1 )
204 /* Write stats */
205 fprintf( pv->file, "%s", pv->context->stats_out );
208 *buf_out = buf;
210 return HB_WORK_OK;