3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
11 #include "audio_remap.h"
13 #include "vorbis/vorbisenc.h"
15 #define OGGVORBIS_FRAME_SIZE 1024
17 int encvorbisInit( hb_work_object_t
*, hb_job_t
* );
18 int encvorbisWork( hb_work_object_t
*, hb_buffer_t
**, hb_buffer_t
** );
19 void encvorbisClose( hb_work_object_t
* );
21 hb_work_object_t hb_encvorbis
=
24 "Vorbis encoder (libvorbis)",
30 struct hb_work_private_s
41 unsigned input_samples
;
43 int64_t prev_blocksize
;
44 int out_discrete_channels
;
49 int encvorbisInit(hb_work_object_t
*w
, hb_job_t
*job
)
51 hb_work_private_t
*pv
= calloc(1, sizeof(hb_work_private_t
));
52 hb_audio_t
*audio
= w
->audio
;
59 hb_log("encvorbis: opening libvorbis");
62 for (i
= 0; i
< 3; i
++)
64 // Zero vorbis headers so that we don't crash in mk_laceXiph
65 // when vorbis_encode_setup_managed fails.
66 memset(w
->config
->vorbis
.headers
[i
], 0, sizeof(ogg_packet
));
68 vorbis_info_init(&pv
->vi
);
70 pv
->out_discrete_channels
=
71 hb_mixdown_get_discrete_channel_count(audio
->config
.out
.mixdown
);
73 if (audio
->config
.out
.bitrate
> 0)
75 if (vorbis_encode_setup_managed(&pv
->vi
, pv
->out_discrete_channels
,
76 audio
->config
.out
.samplerate
, -1,
77 audio
->config
.out
.bitrate
* 1000, -1))
79 hb_error("encvorbis: vorbis_encode_setup_managed() failed");
80 *job
->done_error
= HB_ERROR_INIT
;
85 else if (audio
->config
.out
.quality
!= HB_INVALID_AUDIO_QUALITY
)
87 // map VBR quality to Vorbis API (divide by 10)
88 if (vorbis_encode_setup_vbr(&pv
->vi
, pv
->out_discrete_channels
,
89 audio
->config
.out
.samplerate
,
90 audio
->config
.out
.quality
/ 10))
92 hb_error("encvorbis: vorbis_encode_setup_vbr() failed");
93 *job
->done_error
= HB_ERROR_INIT
;
99 if (vorbis_encode_ctl(&pv
->vi
, OV_ECTL_RATEMANAGE2_SET
, NULL
) ||
100 vorbis_encode_setup_init(&pv
->vi
))
102 hb_error("encvorbis: vorbis_encode_ctl(ratemanage2_set) OR vorbis_encode_setup_init() failed");
103 *job
->done_error
= HB_ERROR_INIT
;
109 vorbis_comment_init(&pv
->vc
);
110 vorbis_comment_add_tag(&pv
->vc
, "Encoder", "HandBrake");
111 vorbis_comment_add_tag(&pv
->vc
, "LANGUAGE", w
->config
->vorbis
.language
);
113 /* set up the analysis state and auxiliary encoding storage */
114 vorbis_analysis_init(&pv
->vd
, &pv
->vi
);
115 vorbis_block_init(&pv
->vd
, &pv
->vb
);
117 /* get the 3 headers */
118 vorbis_analysis_headerout(&pv
->vd
, &pv
->vc
,
119 &header
[0], &header
[1], &header
[2]);
121 for (i
= 0; i
< 3; i
++)
123 pheader
= (ogg_packet
*)w
->config
->theora
.headers
[i
];
124 memcpy(pheader
, &header
[i
], sizeof(ogg_packet
));
125 pheader
->packet
= w
->config
->theora
.headers
[i
] + sizeof(ogg_packet
);
126 memcpy(pheader
->packet
, header
[i
].packet
, header
[i
].bytes
);
129 pv
->input_samples
= pv
->out_discrete_channels
* OGGVORBIS_FRAME_SIZE
;
130 audio
->config
.out
.samples_per_frame
= OGGVORBIS_FRAME_SIZE
;
131 pv
->buf
= malloc(pv
->input_samples
* sizeof(float));
133 pv
->list
= hb_list_init();
136 uint64_t layout
= hb_ff_mixdown_xlat(audio
->config
.out
.mixdown
, NULL
);
137 hb_audio_remap_build_table(&hb_vorbis_chan_map
,
138 audio
->config
.in
.channel_map
, layout
,
144 /***********************************************************************
146 ***********************************************************************
148 **********************************************************************/
149 void encvorbisClose(hb_work_object_t
* w
)
151 hb_work_private_t
*pv
= w
->private_data
;
153 vorbis_comment_clear(&pv
->vc
);
154 vorbis_block_clear(&pv
->vb
);
155 vorbis_info_clear(&pv
->vi
);
156 vorbis_dsp_clear(&pv
->vd
);
160 hb_list_empty(&pv
->list
);
165 w
->private_data
= NULL
;
168 /***********************************************************************
170 ***********************************************************************
172 **********************************************************************/
173 static hb_buffer_t
* Flush( hb_work_object_t
* w
)
175 hb_work_private_t
* pv
= w
->private_data
;
177 int64_t blocksize
= 0;
179 if( vorbis_analysis_blockout( &pv
->vd
, &pv
->vb
) == 1 )
183 vorbis_analysis( &pv
->vb
, NULL
);
184 vorbis_bitrate_addblock( &pv
->vb
);
186 if( vorbis_bitrate_flushpacket( &pv
->vd
, &op
) )
188 buf
= hb_buffer_init( op
.bytes
);
189 memcpy( buf
->data
, op
.packet
, op
.bytes
);
190 blocksize
= vorbis_packet_blocksize(&pv
->vi
, &op
);
192 buf
->s
.type
= AUDIO_BUF
;
193 buf
->s
.frametype
= HB_FRAME_AUDIO
;
195 buf
->s
.start
= (int64_t)(vorbis_granule_time(&pv
->vd
, op
.granulepos
) * 90000);
196 buf
->s
.stop
= (int64_t)(vorbis_granule_time(&pv
->vd
, (pv
->prev_blocksize
+ blocksize
)/4 + op
.granulepos
) * 90000);
197 buf
->s
.duration
= buf
->s
.stop
- buf
->s
.start
;
198 /* The stop time isn't accurate for the first ~3 packets, as the actual blocksize depends on the previous _and_ current packets. */
199 pv
->prev_blocksize
= blocksize
;
207 /***********************************************************************
209 ***********************************************************************
211 **********************************************************************/
212 static hb_buffer_t
* Encode(hb_work_object_t
*w
)
214 hb_work_private_t
*pv
= w
->private_data
;
219 /* Try to extract more data */
220 if ((buf
= Flush(w
)) != NULL
)
225 /* Check if we need more data */
226 if (hb_list_bytes(pv
->list
) < pv
->input_samples
* sizeof(float))
231 /* Process more samples */
232 hb_list_getbytes(pv
->list
, pv
->buf
, pv
->input_samples
* sizeof(float),
234 buffer
= vorbis_analysis_buffer(&pv
->vd
, OGGVORBIS_FRAME_SIZE
);
235 for (i
= 0; i
< OGGVORBIS_FRAME_SIZE
; i
++)
237 for (j
= 0; j
< pv
->out_discrete_channels
; j
++)
239 buffer
[j
][i
] = ((float*)pv
->buf
)[(pv
->out_discrete_channels
* i
+
240 pv
->remap_table
[j
])];
244 vorbis_analysis_wrote(&pv
->vd
, OGGVORBIS_FRAME_SIZE
);
246 /* Try to extract again */
250 /***********************************************************************
252 ***********************************************************************
254 **********************************************************************/
255 int encvorbisWork( hb_work_object_t
* w
, hb_buffer_t
** buf_in
,
256 hb_buffer_t
** buf_out
)
258 hb_work_private_t
* pv
= w
->private_data
;
259 hb_buffer_t
* in
= *buf_in
;
263 if (in
->s
.flags
& HB_BUF_FLAG_EOF
)
265 /* EOF on input - send it downstream & say we're done */
270 hb_list_add( pv
->list
, in
);
272 *buf_out
= buf
= Encode( w
);
275 buf
->next
= Encode( w
);