OSDN Git Service

libhb: fix a compile warning in enctheora
[handbrake-jp/handbrake-jp-git.git] / libhb / enctheora.c
1 /* This file is part of the HandBrake source code.
2    Homepage: <http://handbrake.fr/>.
3    It may be used under the terms of the GNU General Public License. */
4
5 #include "hb.h"
6 #include "theora/codec.h"
7 #include "theora/theoraenc.h"
8
9 int  enctheoraInit( hb_work_object_t *, hb_job_t * );
10 int  enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
11 void enctheoraClose( hb_work_object_t * );
12
13 hb_work_object_t hb_enctheora =
14 {
15     WORK_ENCTHEORA,
16     "Theora encoder (libtheora)",
17     enctheoraInit,
18     enctheoraWork,
19     enctheoraClose
20 };
21
22 struct hb_work_private_s
23 {
24     hb_job_t * job;
25
26     th_enc_ctx * ctx;
27 };
28
29 int enctheoraInit( hb_work_object_t * w, hb_job_t * job )
30 {
31     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
32     w->private_data = pv;
33
34     pv->job = job;
35
36     th_info ti;
37     th_comment tc;
38     ogg_packet op;
39     th_info_init( &ti );
40
41     /* Frame width and height need to be multiples of 16 */
42     ti.pic_width = job->width;
43     ti.pic_height = job->height;
44     ti.frame_width = (job->width + 0xf) & ~0xf;
45     ti.frame_height = (job->height + 0xf) & ~0xf;
46     ti.pic_x = ti.pic_y = 0;
47
48     ti.fps_numerator = job->vrate;
49     ti.fps_denominator = job->vrate_base;
50     if( job->anamorphic.mode )
51     {
52         ti.aspect_numerator = job->anamorphic.par_width;
53         ti.aspect_denominator = job->anamorphic.par_height;
54     }
55     else
56     {
57         ti.aspect_numerator = ti.aspect_denominator = 1;
58     }
59     ti.colorspace = TH_CS_UNSPECIFIED;
60     ti.pixel_fmt = TH_PF_420;
61     if (job->vquality < 0.0)
62     {
63         ti.target_bitrate = job->vbitrate * 1000;
64         ti.quality = 0;
65     }
66     else
67     {
68         ti.target_bitrate = 0;
69         
70         if( job->vquality > 0 && job->vquality < 1 )
71         {
72             ti.quality = 63 * job->vquality;            
73         }
74         else
75         {
76             ti.quality = job->vquality;
77         }
78     }
79
80     pv->ctx = th_encode_alloc( &ti );
81
82     th_comment_init( &tc );
83
84     th_encode_flushheader( pv->ctx, &tc, &op );
85     memcpy(w->config->theora.headers[0], &op, sizeof(op));
86     memcpy(w->config->theora.headers[0] + sizeof(op), op.packet, op.bytes );
87
88     th_encode_flushheader( pv->ctx, &tc, &op );
89     memcpy(w->config->theora.headers[1], &op, sizeof(op));
90     memcpy(w->config->theora.headers[1] + sizeof(op), op.packet, op.bytes );
91
92     th_encode_flushheader( pv->ctx, &tc, &op );
93     memcpy(w->config->theora.headers[2], &op, sizeof(op));
94     memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes );
95
96     th_comment_clear( &tc );
97
98     return 0;
99 }
100
101 /***********************************************************************
102  * Close
103  ***********************************************************************
104  *
105  **********************************************************************/
106 void enctheoraClose( hb_work_object_t * w )
107 {
108     hb_work_private_t * pv = w->private_data;
109
110     th_encode_free( pv->ctx );
111
112     free( pv );
113     w->private_data = NULL;
114 }
115
116 /***********************************************************************
117  * Work
118  ***********************************************************************
119  *
120  **********************************************************************/
121 int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
122                  hb_buffer_t ** buf_out )
123 {
124     hb_work_private_t * pv = w->private_data;
125     hb_job_t * job = pv->job;
126     hb_buffer_t * in = *buf_in, * buf;
127     th_ycbcr_buffer ycbcr;
128     ogg_packet op;
129
130     int frame_width, frame_height;
131
132     if ( in->size <= 0 )
133     {
134         // EOF on input - send it downstream & say we're done.
135         // XXX may need to flush packets via a call to
136         //  th_encode_packetout( pv->ctx, 1, &op );
137         // but we don't have a timestamp to put on those packets so we
138         // drop them for now.
139         *buf_out = in;
140         *buf_in = NULL;
141        return HB_WORK_DONE;
142     }
143
144     memset(&op, 0, sizeof(op));
145     memset(&ycbcr, 0, sizeof(ycbcr));
146
147     frame_width = (job->width + 0xf) & ~0xf;
148     frame_height = (job->height + 0xf) & ~0xf;
149
150     // Y
151     ycbcr[0].width = frame_width;
152     ycbcr[0].height = frame_height;
153     ycbcr[0].stride = job->width;
154
155     // CbCr decimated by factor of 2 in both width and height
156     ycbcr[1].width  = ycbcr[2].width  = (frame_width + 1) / 2;
157     ycbcr[1].height = ycbcr[2].height = (frame_height + 1) / 2;
158     ycbcr[1].stride = ycbcr[2].stride = (job->width + 1) / 2;
159
160     ycbcr[0].data = in->data;
161     ycbcr[1].data = ycbcr[0].data + (ycbcr[0].stride * job->height);
162     ycbcr[2].data = ycbcr[1].data + (ycbcr[1].stride * ((job->height+1)/2));
163
164     th_encode_ycbcr_in( pv->ctx, ycbcr );
165
166     th_encode_packetout( pv->ctx, 0, &op );
167
168     buf = hb_buffer_init( op.bytes + sizeof(op) );
169     memcpy(buf->data, &op, sizeof(op));
170     memcpy(buf->data + sizeof(op), op.packet, op.bytes);
171     buf->frametype = ( th_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF;
172     buf->start = in->start;
173     buf->stop  = in->stop;
174
175     *buf_out = buf;
176
177     return HB_WORK_OK;
178 }
179