6734
|
1 /*
|
|
2 * Dirac encoding support via libdirac library
|
|
3 * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk>
|
|
4 * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
|
|
5 *
|
|
6 * This file is part of FFmpeg.
|
|
7 *
|
|
8 * FFmpeg is free software; you can redistribute it and/or
|
|
9 * modify it under the terms of the GNU Lesser General Public
|
|
10 * License as published by the Free Software Foundation; either
|
|
11 * version 2.1 of the License, or (at your option) any later version.
|
|
12 *
|
|
13 * FFmpeg is distributed in the hope that it will be useful,
|
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
16 * Lesser General Public License for more details.
|
|
17 *
|
|
18 * You should have received a copy of the GNU Lesser General Public
|
|
19 * License along with FFmpeg; if not, write to the Free Software
|
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21 */
|
|
22
|
|
23 /**
|
|
24 * @file libdiracenc.c
|
|
25 * Dirac encoding support via libdirac library; more details about the
|
|
26 * Dirac project can be found at http://dirac.sourceforge.net/.
|
|
27 * The libdirac_encoder library implements Dirac specification version 2.2
|
|
28 * (http://dirac.sourceforge.net/specification.html).
|
|
29 */
|
|
30
|
|
31 #include "libdirac_libschro.h"
|
|
32 #include "libdirac.h"
|
|
33
|
|
34 #undef NDEBUG
|
|
35 #include <assert.h>
|
|
36
|
|
37
|
|
38 #include <libdirac_encoder/dirac_encoder.h>
|
|
39
|
|
40 /** Dirac encoder private data */
|
|
41 typedef struct FfmpegDiracEncoderParams
|
|
42 {
|
|
43 /** Dirac encoder context */
|
|
44 dirac_encoder_context_t enc_ctx;
|
|
45
|
|
46 /** frame being encoded */
|
|
47 AVFrame picture;
|
|
48
|
|
49 /** frame size */
|
|
50 int frame_size;
|
|
51
|
|
52 /** Dirac encoder handle */
|
|
53 dirac_encoder_t* p_encoder;
|
|
54
|
|
55 /** input frame buffer */
|
|
56 unsigned char *p_in_frame_buf;
|
|
57
|
|
58 /** queue storing encoded frames */
|
|
59 FfmpegDiracSchroQueue enc_frame_queue;
|
|
60
|
|
61 /** end of sequence signalled by user, 0 - false, 1 - true */
|
|
62 int eos_signalled;
|
|
63
|
|
64 /** end of sequence returned by encoder, 0 - false, 1 - true */
|
|
65 int eos_pulled;
|
|
66 } FfmpegDiracEncoderParams;
|
|
67
|
|
68 /**
|
|
69 * Works out Dirac-compatible chroma format.
|
|
70 */
|
|
71 static dirac_chroma_t GetDiracChromaFormat(enum PixelFormat ff_pix_fmt)
|
|
72 {
|
|
73 int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) /
|
|
74 sizeof(ffmpeg_dirac_pixel_format_map[0]);
|
|
75 int idx;
|
|
76
|
|
77 for (idx = 0; idx < num_formats; ++idx) {
|
|
78 if (ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt == ff_pix_fmt) {
|
|
79 return ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt;
|
|
80 }
|
|
81 }
|
|
82 return formatNK;
|
|
83 }
|
|
84
|
|
85 /**
|
|
86 * Dirac video preset table. Ensure that this tables matches up correctly
|
|
87 * with the ff_dirac_schro_video_format_info table in libdirac_libschro.c.
|
|
88 */
|
|
89 static const VideoFormat ff_dirac_video_formats[]={
|
|
90 VIDEO_FORMAT_CUSTOM ,
|
|
91 VIDEO_FORMAT_QSIF525 ,
|
|
92 VIDEO_FORMAT_QCIF ,
|
|
93 VIDEO_FORMAT_SIF525 ,
|
|
94 VIDEO_FORMAT_CIF ,
|
|
95 VIDEO_FORMAT_4SIF525 ,
|
|
96 VIDEO_FORMAT_4CIF ,
|
|
97 VIDEO_FORMAT_SD_480I60 ,
|
|
98 VIDEO_FORMAT_SD_576I50 ,
|
|
99 VIDEO_FORMAT_HD_720P60 ,
|
|
100 VIDEO_FORMAT_HD_720P50 ,
|
|
101 VIDEO_FORMAT_HD_1080I60 ,
|
|
102 VIDEO_FORMAT_HD_1080I50 ,
|
|
103 VIDEO_FORMAT_HD_1080P60 ,
|
|
104 VIDEO_FORMAT_HD_1080P50 ,
|
|
105 VIDEO_FORMAT_DIGI_CINEMA_2K24 ,
|
|
106 VIDEO_FORMAT_DIGI_CINEMA_4K24 ,
|
|
107 };
|
|
108
|
|
109 /**
|
|
110 * Returns the video format preset matching the input video dimensions and
|
|
111 * time base.
|
|
112 */
|
|
113 static VideoFormat GetDiracVideoFormatPreset (AVCodecContext *avccontext)
|
|
114 {
|
|
115 unsigned int num_formats = sizeof(ff_dirac_video_formats) /
|
|
116 sizeof(ff_dirac_video_formats[0]);
|
|
117
|
|
118 unsigned int idx = ff_dirac_schro_get_video_format_idx (avccontext);
|
|
119
|
|
120 return (idx < num_formats) ?
|
|
121 ff_dirac_video_formats[idx] : VIDEO_FORMAT_CUSTOM;
|
|
122 }
|
|
123
|
|
124 static int libdirac_encode_init(AVCodecContext *avccontext)
|
|
125 {
|
|
126
|
|
127 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data;
|
|
128 int no_local = 1;
|
|
129 int verbose = avccontext->debug;
|
|
130 VideoFormat preset;
|
|
131
|
|
132 /* get Dirac preset */
|
|
133 preset = GetDiracVideoFormatPreset(avccontext);
|
|
134
|
|
135 /* initialize the encoder context */
|
|
136 dirac_encoder_context_init (&(p_dirac_params->enc_ctx), preset);
|
|
137
|
|
138 p_dirac_params->enc_ctx.src_params.chroma =
|
|
139 GetDiracChromaFormat(avccontext->pix_fmt);
|
|
140
|
|
141 if (p_dirac_params->enc_ctx.src_params.chroma == formatNK) {
|
|
142 av_log (avccontext, AV_LOG_ERROR,
|
|
143 "Unsupported pixel format %d. This codec supports only "
|
|
144 "Planar YUV formats (yuv420p, yuv422p, yuv444p\n",
|
|
145 avccontext->pix_fmt);
|
|
146 return -1;
|
|
147 }
|
|
148
|
|
149 p_dirac_params->enc_ctx.src_params.frame_rate.numerator =
|
|
150 avccontext->time_base.den;
|
|
151 p_dirac_params->enc_ctx.src_params.frame_rate.denominator =
|
|
152 avccontext->time_base.num;
|
|
153
|
|
154 p_dirac_params->enc_ctx.src_params.width = avccontext->width;
|
|
155 p_dirac_params->enc_ctx.src_params.height = avccontext->height;
|
|
156
|
|
157 p_dirac_params->frame_size = avpicture_get_size(avccontext->pix_fmt,
|
|
158 avccontext->width,
|
|
159 avccontext->height);
|
|
160
|
|
161 avccontext->coded_frame = &p_dirac_params->picture;
|
|
162
|
|
163 if (no_local) {
|
|
164 p_dirac_params->enc_ctx.decode_flag = 0;
|
|
165 p_dirac_params->enc_ctx.instr_flag = 0;
|
|
166 } else {
|
|
167 p_dirac_params->enc_ctx.decode_flag = 1;
|
|
168 p_dirac_params->enc_ctx.instr_flag = 1;
|
|
169 }
|
|
170
|
|
171 /* Intra-only sequence */
|
|
172 if (avccontext->gop_size == 0 )
|
|
173 p_dirac_params->enc_ctx.enc_params.num_L1 = 0;
|
|
174 else
|
|
175 avccontext->has_b_frames = 1;
|
|
176
|
|
177 if (avccontext->flags & CODEC_FLAG_QSCALE) {
|
|
178 if (avccontext->global_quality != 0) {
|
|
179 p_dirac_params->enc_ctx.enc_params.qf =
|
|
180 avccontext->global_quality / (FF_QP2LAMBDA*10.0);
|
|
181 /* if it is not default bitrate then send target rate. */
|
|
182 if (avccontext->bit_rate >= 1000 &&
|
|
183 avccontext->bit_rate != 200000) {
|
|
184 p_dirac_params->enc_ctx.enc_params.trate =
|
|
185 avccontext->bit_rate / 1000;
|
|
186 }
|
|
187 } else
|
|
188 p_dirac_params->enc_ctx.enc_params.lossless = 1;
|
|
189 } else if (avccontext->bit_rate >= 1000)
|
|
190 p_dirac_params->enc_ctx.enc_params.trate = avccontext->bit_rate / 1000;
|
|
191
|
|
192 if ((preset > VIDEO_FORMAT_QCIF || preset < VIDEO_FORMAT_QSIF525) &&
|
|
193 avccontext->bit_rate == 200000) {
|
|
194 p_dirac_params->enc_ctx.enc_params.trate = 0;
|
|
195 }
|
|
196
|
|
197 if (avccontext->flags & CODEC_FLAG_INTERLACED_ME) {
|
|
198 /* all material can be coded as interlaced or progressive
|
|
199 * irrespective of the type of source material */
|
|
200 p_dirac_params->enc_ctx.enc_params.picture_coding_mode = 1;
|
|
201 }
|
|
202
|
|
203 p_dirac_params->p_encoder = dirac_encoder_init (&(p_dirac_params->enc_ctx),
|
|
204 verbose );
|
|
205
|
|
206 if (!p_dirac_params->p_encoder) {
|
|
207 av_log(avccontext, AV_LOG_ERROR,
|
|
208 "Unrecoverable Error: dirac_encoder_init failed. ");
|
|
209 return EXIT_FAILURE;
|
|
210 }
|
|
211
|
|
212 /* allocate enough memory for the incoming data */
|
|
213 p_dirac_params->p_in_frame_buf = av_malloc(p_dirac_params->frame_size);
|
|
214
|
|
215 /* initialize the encoded frame queue */
|
|
216 ff_dirac_schro_queue_init(&p_dirac_params->enc_frame_queue);
|
|
217
|
|
218 return 0 ;
|
|
219 }
|
|
220
|
|
221 static void DiracFreeFrame (void *data)
|
|
222 {
|
|
223 FfmpegDiracSchroEncodedFrame *enc_frame = data;
|
|
224
|
|
225 av_freep (&(enc_frame->p_encbuf));
|
|
226 av_free(enc_frame);
|
|
227 }
|
|
228
|
|
229 static int libdirac_encode_frame(AVCodecContext *avccontext,
|
|
230 unsigned char *frame,
|
|
231 int buf_size, void *data)
|
|
232 {
|
|
233 int enc_size = 0;
|
|
234 dirac_encoder_state_t state;
|
|
235 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data;
|
|
236 FfmpegDiracSchroEncodedFrame* p_frame_output = NULL;
|
|
237 FfmpegDiracSchroEncodedFrame* p_next_output_frame = NULL;
|
|
238 int go = 1;
|
|
239
|
|
240 if (data == NULL) {
|
|
241 /* push end of sequence if not already signalled */
|
|
242 if (!p_dirac_params->eos_signalled) {
|
|
243 dirac_encoder_end_sequence( p_dirac_params->p_encoder );
|
|
244 p_dirac_params->eos_signalled = 1;
|
|
245 }
|
|
246 } else {
|
|
247
|
|
248 /* Allocate frame data to Dirac input buffer.
|
|
249 * Input line size may differ from what the codec supports,
|
|
250 * especially when transcoding from one format to another.
|
|
251 * So use avpicture_layout to copy the frame. */
|
|
252 avpicture_layout ((AVPicture *)data, avccontext->pix_fmt,
|
|
253 avccontext->width, avccontext->height,
|
|
254 p_dirac_params->p_in_frame_buf,
|
|
255 p_dirac_params->frame_size);
|
|
256
|
|
257 /* load next frame */
|
|
258 if (dirac_encoder_load (p_dirac_params->p_encoder,
|
|
259 p_dirac_params->p_in_frame_buf,
|
|
260 p_dirac_params->frame_size ) < 0) {
|
|
261 av_log(avccontext, AV_LOG_ERROR, "Unrecoverable Encoder Error."
|
|
262 " dirac_encoder_load failed...\n");
|
|
263 return -1;
|
|
264 }
|
|
265 }
|
|
266
|
|
267 if (p_dirac_params->eos_pulled)
|
|
268 go = 0;
|
|
269
|
|
270 while(go) {
|
|
271 p_dirac_params->p_encoder->enc_buf.buffer = frame;
|
|
272 p_dirac_params->p_encoder->enc_buf.size = buf_size;
|
|
273 /* process frame */
|
|
274 state = dirac_encoder_output ( p_dirac_params->p_encoder );
|
|
275
|
|
276 switch (state)
|
|
277 {
|
|
278 case ENC_STATE_AVAIL:
|
|
279 case ENC_STATE_EOS:
|
|
280 assert (p_dirac_params->p_encoder->enc_buf.size > 0);
|
|
281 /* create output frame */
|
|
282 p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame));
|
|
283 /* set output data */
|
|
284 p_frame_output->p_encbuf =
|
|
285 av_malloc(p_dirac_params->p_encoder->enc_buf.size);
|
|
286
|
|
287 memcpy(p_frame_output->p_encbuf,
|
|
288 p_dirac_params->p_encoder->enc_buf.buffer,
|
|
289 p_dirac_params->p_encoder->enc_buf.size);
|
|
290
|
|
291 p_frame_output->size = p_dirac_params->p_encoder->enc_buf.size;
|
|
292
|
|
293 p_frame_output->frame_num =
|
|
294 p_dirac_params->p_encoder->enc_pparams.pnum;
|
|
295
|
|
296 if (p_dirac_params->p_encoder->enc_pparams.ptype == INTRA_PICTURE &&
|
|
297 p_dirac_params->p_encoder->enc_pparams.rtype == REFERENCE_PICTURE)
|
|
298 p_frame_output->key_frame = 1;
|
|
299
|
|
300 ff_dirac_schro_queue_push_back (&p_dirac_params->enc_frame_queue,
|
|
301 p_frame_output);
|
|
302
|
|
303 if (state == ENC_STATE_EOS) {
|
|
304 p_dirac_params->eos_pulled = 1;
|
|
305 go = 0;
|
|
306 }
|
|
307 break;
|
|
308
|
|
309 case ENC_STATE_BUFFER:
|
|
310 go = 0;
|
|
311 break;
|
|
312
|
|
313 case ENC_STATE_INVALID:
|
|
314 av_log(avccontext, AV_LOG_ERROR,
|
|
315 "Unrecoverable Dirac Encoder Error. Quitting...\n");
|
|
316 return -1;
|
|
317
|
|
318 default:
|
|
319 av_log(avccontext, AV_LOG_ERROR, "Unknown Dirac Encoder state\n");
|
|
320 return -1;
|
|
321 }
|
|
322 }
|
|
323
|
|
324 /* copy 'next' frame in queue */
|
|
325 p_next_output_frame =
|
|
326 ff_dirac_schro_queue_pop(&p_dirac_params->enc_frame_queue);
|
|
327
|
|
328 if (p_next_output_frame == NULL)
|
|
329 return 0;
|
|
330
|
|
331 memcpy(frame, p_next_output_frame->p_encbuf, p_next_output_frame->size);
|
|
332 avccontext->coded_frame->key_frame = p_next_output_frame->key_frame;
|
|
333 /* Use the frame number of the encoded frame as the pts. It is OK to do
|
|
334 * so since Dirac is a constant framerate codec. It expects input to be
|
|
335 * of constant framerate. */
|
|
336 avccontext->coded_frame->pts = p_next_output_frame->frame_num;
|
|
337 enc_size = p_next_output_frame->size;
|
|
338
|
|
339 /* free frame */
|
|
340 DiracFreeFrame(p_next_output_frame);
|
|
341
|
|
342 return enc_size;
|
|
343 }
|
|
344
|
|
345 static int libdirac_encode_close(AVCodecContext *avccontext)
|
|
346 {
|
|
347 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data;
|
|
348
|
|
349 /* close the encoder */
|
|
350 dirac_encoder_close(p_dirac_params->p_encoder );
|
|
351
|
|
352 /* free data in the output frame queue */
|
|
353 ff_dirac_schro_queue_free(&p_dirac_params->enc_frame_queue,
|
|
354 DiracFreeFrame);
|
|
355
|
|
356 /* free the input frame buffer */
|
|
357 av_freep(&p_dirac_params->p_in_frame_buf);
|
|
358
|
|
359 return 0 ;
|
|
360 }
|
|
361
|
|
362
|
|
363 AVCodec libdirac_encoder = {
|
|
364 "libdirac",
|
|
365 CODEC_TYPE_VIDEO,
|
|
366 CODEC_ID_DIRAC,
|
|
367 sizeof(FfmpegDiracEncoderParams),
|
|
368 libdirac_encode_init,
|
|
369 libdirac_encode_frame,
|
|
370 libdirac_encode_close,
|
|
371 .capabilities= CODEC_CAP_DELAY,
|
|
372 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, -1},
|
|
373 } ;
|