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. */
9 #include "ffmpeg/avcodec.h"
11 struct hb_work_private_s
14 AVCodecContext
* context
;
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
=
25 "MPEG-4 encoder (libavcodec)",
31 int encavcodecInit( hb_work_object_t
* w
, hb_job_t
* job
)
34 AVCodecContext
* context
;
36 hb_work_private_t
* pv
= calloc( 1, sizeof( hb_work_private_t
) );
41 codec
= avcodec_find_encoder( CODEC_ID_MPEG4
);
44 hb_log( "hb_work_encavcodec_init: avcodec_find_encoder "
47 context
= avcodec_alloc_context();
48 if( job
->vquality
< 0.0 || job
->vquality
> 1.0 )
51 context
->bit_rate
= 1000 * job
->vbitrate
;
52 context
->bit_rate_tolerance
= 10 * context
->bit_rate
;
56 /* Constant quantizer */
57 context
->qmin
= 31 - job
->vquality
* 30;
58 context
->qmax
= context
->qmin
;
59 hb_log( "encavcodec: encoding at constant quantizer %d",
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
;
87 context
->flags
|= CODEC_FLAG_GRAY
;
92 char filename
[1024]; memset( filename
, 0, 1024 );
93 hb_get_tempory_filename( job
->h
, filename
, "ffmpeg.log" );
97 pv
->file
= fopen( filename
, "wb" );
98 context
->flags
|= CODEC_FLAG_PASS1
;
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 );
111 fread( log
, size
, 1, pv
->file
);
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 )
130 w
->config
->mpeg4
.length
= 15;
131 memcpy( w
->config
->mpeg4
.bytes
, context
->extradata
+ 15, 15 );
133 w
->config
->mpeg4
.length
= context
->extradata_size
;
134 memcpy( w
->config
->mpeg4
.bytes
, context
->extradata
,
135 context
->extradata_size
);
142 /***********************************************************************
144 ***********************************************************************
146 **********************************************************************/
147 void encavcodecClose( hb_work_object_t
* w
)
149 hb_work_private_t
* pv
= w
->private_data
;
153 hb_log( "encavcodec: closing libavcodec" );
154 avcodec_flush_buffers( pv
->context
);
155 avcodec_close( pv
->context
);
162 w
->private_data
= NULL
;
165 /***********************************************************************
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
;
176 hb_buffer_t
* in
= *buf_in
, * buf
;
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
,
196 buf
->start
= in
->start
;
197 buf
->stop
= in
->stop
;
198 buf
->key
= pv
->context
->coded_frame
->key_frame
;
205 fprintf( pv
->file
, "%s", pv
->context
->stats_out
);