OSDN Git Service

Theora.
[handbrake-jp/handbrake-jp-git.git] / libhb / enctheora.c
1 /* This file is part of the HandBrake source code.
2    Homepage: <http://handbrake.m0k.org/>.
3    It may be used under the terms of the GNU General Public License. */
4
5 #include "hb.h"
6 #include "theora/theora.h"
7
8 int  enctheoraInit( hb_work_object_t *, hb_job_t * );
9 int  enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
10 void enctheoraClose( hb_work_object_t * );
11
12 hb_work_object_t hb_enctheora =
13 {
14     WORK_ENCTHEORA,
15     "Theora encoder (libtheora)",
16     enctheoraInit,
17     enctheoraWork,
18     enctheoraClose
19 };
20
21 struct hb_work_private_s
22 {
23     hb_job_t * job;
24
25     theora_state theora;
26 };
27
28 int enctheoraInit( hb_work_object_t * w, hb_job_t * job )
29 {
30     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
31     w->private_data = pv;
32
33     pv->job = job;
34
35     theora_info ti;
36     theora_comment tc;
37     ogg_packet op;
38     theora_info_init( &ti );
39
40     ti.width = ti.frame_width = job->width;
41     ti.height = ti.frame_height = job->height;
42     ti.offset_x = ti.offset_y = 0;
43     ti.fps_numerator = job->vrate;
44     ti.fps_denominator = job->vrate_base;
45     if (job->pixel_ratio)
46     {
47         ti.aspect_numerator = job->pixel_aspect_width;
48         ti.aspect_denominator = job->pixel_aspect_height;
49     }
50     else
51     {
52         ti.aspect_numerator = ti.aspect_denominator = 1;
53     }
54     ti.colorspace = OC_CS_UNSPECIFIED;
55     ti.pixelformat = OC_PF_420;
56     ti.keyframe_auto_p = 1;
57     ti.keyframe_frequency = (job->vrate / job->vrate_base) + 1;
58     ti.keyframe_frequency_force = (10 * job->vrate / job->vrate_base) + 1;
59     /* From encoder_example.c */
60     ti.quick_p = 1;
61     ti.dropframes_p = 0;
62     ti.keyframe_auto_threshold = 80;
63     ti.keyframe_mindistance = 8;
64     ti.noise_sensitivity = 1;
65     ti.sharpness = 0;
66     if (job->vquality < 0.0 || job->vquality > 1.0)
67     {
68         ti.target_bitrate = job->vbitrate * 1000;
69         ti.keyframe_data_target_bitrate = job->vbitrate * 1000 * 1.5;
70         ti.quality = 0;
71     }
72     else
73     {
74         ti.target_bitrate = 0;
75         ti.quality = 63 * job->vquality;
76     }
77
78     theora_encode_init( &pv->theora, &ti );
79     theora_info_clear( &ti );
80
81     theora_encode_header( &pv->theora, &op );
82     memcpy(w->config->theora.headers[0], &op, sizeof(op));
83     memcpy(w->config->theora.headers[0] + sizeof(op), op.packet, op.bytes );
84
85     theora_comment_init(&tc);
86     theora_encode_comment(&tc,&op);
87     memcpy(w->config->theora.headers[1], &op, sizeof(op));
88     memcpy(w->config->theora.headers[1] + sizeof(op), op.packet, op.bytes );
89     free(op.packet);
90
91     theora_encode_tables(&pv->theora, &op);
92     memcpy(w->config->theora.headers[2], &op, sizeof(op));
93     memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes );
94
95     return 0;
96 }
97
98 /***********************************************************************
99  * Close
100  ***********************************************************************
101  *
102  **********************************************************************/
103 void enctheoraClose( hb_work_object_t * w )
104 {
105     hb_work_private_t * pv = w->private_data;
106     /* TODO: Free alloc'd */
107
108     free( pv );
109     w->private_data = NULL;
110 }
111
112 /***********************************************************************
113  * Work
114  ***********************************************************************
115  *
116  **********************************************************************/
117 int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
118                  hb_buffer_t ** buf_out )
119 {
120     hb_work_private_t * pv = w->private_data;
121     hb_job_t * job = pv->job;
122     hb_buffer_t * in = *buf_in, * buf;
123     yuv_buffer yuv;
124     ogg_packet op;
125     static int last_p = 0;
126
127     memset(&op, 0, sizeof(op));
128     memset(&yuv, 0, sizeof(yuv));
129
130     /* If this is the last empty frame, we're done */
131     if(!in->data)
132     {
133         if (!last_p)
134         {
135             last_p++;
136             goto finish;
137         }
138        *buf_out        = NULL;
139        return HB_WORK_DONE;
140     }
141
142     yuv.y_width = job->width;
143     yuv.y_height = job->height;
144     yuv.y_stride = job->width;
145
146     yuv.uv_width = job->width / 2;
147     yuv.uv_height = job->height / 2;
148     yuv.uv_stride = job->width / 2;
149
150     yuv.y = in->data;
151     yuv.u = in->data + job->width * job->height;
152     yuv.v = in->data + job->width * job->height * 5/4;
153
154     theora_encode_YUVin(&pv->theora, &yuv);
155
156 finish:
157     theora_encode_packetout(&pv->theora, last_p, &op);
158
159     buf = hb_buffer_init( op.bytes + sizeof(op) );
160     memcpy(buf->data, &op, sizeof(op));
161     memcpy(buf->data + sizeof(op), op.packet, op.bytes);
162     buf->frametype = ( theora_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF;
163     buf->start = in->start;
164     buf->stop  = in->stop;
165
166     *buf_out = buf;
167
168     return HB_WORK_OK;
169 }
170