OSDN Git Service

Leave video tracks on the 90KHz MPEG timebase so we don't end up with constantly...
[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/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->anamorphic.mode )
46     {
47         ti.aspect_numerator = job->anamorphic.par_width;
48         ti.aspect_denominator = job->anamorphic.par_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)
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         
76         if( job->vquality > 0 && job->vquality < 1 )
77         {
78             ti.quality = 63 * job->vquality;            
79         }
80         else
81         {
82             ti.quality = job->vquality;
83         }
84     }
85
86     theora_encode_init( &pv->theora, &ti );
87     theora_info_clear( &ti );
88
89     theora_encode_header( &pv->theora, &op );
90     memcpy(w->config->theora.headers[0], &op, sizeof(op));
91     memcpy(w->config->theora.headers[0] + sizeof(op), op.packet, op.bytes );
92
93     theora_comment_init(&tc);
94     theora_encode_comment(&tc,&op);
95     memcpy(w->config->theora.headers[1], &op, sizeof(op));
96     memcpy(w->config->theora.headers[1] + sizeof(op), op.packet, op.bytes );
97     free(op.packet);
98
99     theora_encode_tables(&pv->theora, &op);
100     memcpy(w->config->theora.headers[2], &op, sizeof(op));
101     memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes );
102
103     return 0;
104 }
105
106 /***********************************************************************
107  * Close
108  ***********************************************************************
109  *
110  **********************************************************************/
111 void enctheoraClose( hb_work_object_t * w )
112 {
113     hb_work_private_t * pv = w->private_data;
114     /* TODO: Free alloc'd */
115
116     free( pv );
117     w->private_data = NULL;
118 }
119
120 /***********************************************************************
121  * Work
122  ***********************************************************************
123  *
124  **********************************************************************/
125 int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
126                  hb_buffer_t ** buf_out )
127 {
128     hb_work_private_t * pv = w->private_data;
129     hb_job_t * job = pv->job;
130     hb_buffer_t * in = *buf_in, * buf;
131     yuv_buffer yuv;
132     ogg_packet op;
133
134     if ( in->size <= 0 )
135     {
136         // EOF on input - send it downstream & say we're done.
137         // XXX may need to flush packets via a call to
138         //  theora_encode_packetout(&pv->theora, 1, &op);
139         // but we don't have a timestamp to put on those packets so we
140         // drop them for now.
141         *buf_out = in;
142         *buf_in = NULL;
143        return HB_WORK_DONE;
144     }
145
146     memset(&op, 0, sizeof(op));
147     memset(&yuv, 0, sizeof(yuv));
148
149     yuv.y_width = job->width;
150     yuv.y_height = job->height;
151     yuv.y_stride = job->width;
152
153     yuv.uv_width = (job->width + 1) / 2;
154     yuv.uv_height = (job->height + 1) / 2;
155     yuv.uv_stride = yuv.uv_width;
156
157     yuv.y = in->data;
158     yuv.u = in->data + job->width * job->height;
159     yuv.v = in->data + ( job->width * job->height ) + ( yuv.uv_width * yuv.uv_height );
160
161     theora_encode_YUVin(&pv->theora, &yuv);
162
163     theora_encode_packetout(&pv->theora, 0, &op);
164
165     buf = hb_buffer_init( op.bytes + sizeof(op) );
166     memcpy(buf->data, &op, sizeof(op));
167     memcpy(buf->data + sizeof(op), op.packet, op.bytes);
168     buf->frametype = ( theora_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF;
169     buf->start = in->start;
170     buf->stop  = in->stop;
171
172     *buf_out = buf;
173
174     return HB_WORK_OK;
175 }
176