Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * Ut Video encoder |
||
3 | * Copyright (c) 2012 Jan Ekström |
||
4 | * |
||
5 | * This file is part of FFmpeg. |
||
6 | * |
||
7 | * FFmpeg is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public |
||
9 | * License as published by the Free Software Foundation; either |
||
10 | * version 2.1 of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * FFmpeg is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
15 | * Lesser General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU Lesser General Public |
||
18 | * License along with FFmpeg; if not, write to the Free Software |
||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
20 | */ |
||
21 | |||
22 | /** |
||
23 | * @file |
||
24 | * Ut Video encoder |
||
25 | */ |
||
26 | |||
27 | #include "libavutil/imgutils.h" |
||
28 | #include "libavutil/intreadwrite.h" |
||
29 | #include "avcodec.h" |
||
30 | #include "internal.h" |
||
31 | #include "bytestream.h" |
||
32 | #include "put_bits.h" |
||
33 | #include "dsputil.h" |
||
34 | #include "mathops.h" |
||
35 | #include "utvideo.h" |
||
36 | #include "huffman.h" |
||
37 | |||
38 | /* Compare huffentry symbols */ |
||
39 | static int huff_cmp_sym(const void *a, const void *b) |
||
40 | { |
||
41 | const HuffEntry *aa = a, *bb = b; |
||
42 | return aa->sym - bb->sym; |
||
43 | } |
||
44 | |||
45 | static av_cold int utvideo_encode_close(AVCodecContext *avctx) |
||
46 | { |
||
47 | UtvideoContext *c = avctx->priv_data; |
||
48 | int i; |
||
49 | |||
50 | av_freep(&avctx->coded_frame); |
||
51 | av_freep(&c->slice_bits); |
||
52 | for (i = 0; i < 4; i++) |
||
53 | av_freep(&c->slice_buffer[i]); |
||
54 | |||
55 | return 0; |
||
56 | } |
||
57 | |||
58 | static av_cold int utvideo_encode_init(AVCodecContext *avctx) |
||
59 | { |
||
60 | UtvideoContext *c = avctx->priv_data; |
||
61 | int i; |
||
62 | uint32_t original_format; |
||
63 | |||
64 | c->avctx = avctx; |
||
65 | c->frame_info_size = 4; |
||
66 | c->slice_stride = FFALIGN(avctx->width, 32); |
||
67 | |||
68 | switch (avctx->pix_fmt) { |
||
69 | case AV_PIX_FMT_RGB24: |
||
70 | c->planes = 3; |
||
71 | avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); |
||
72 | original_format = UTVIDEO_RGB; |
||
73 | break; |
||
74 | case AV_PIX_FMT_RGBA: |
||
75 | c->planes = 4; |
||
76 | avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); |
||
77 | original_format = UTVIDEO_RGBA; |
||
78 | break; |
||
79 | case AV_PIX_FMT_YUV420P: |
||
80 | if (avctx->width & 1 || avctx->height & 1) { |
||
81 | av_log(avctx, AV_LOG_ERROR, |
||
82 | "4:2:0 video requires even width and height.\n"); |
||
83 | return AVERROR_INVALIDDATA; |
||
84 | } |
||
85 | c->planes = 3; |
||
86 | avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); |
||
87 | original_format = UTVIDEO_420; |
||
88 | break; |
||
89 | case AV_PIX_FMT_YUV422P: |
||
90 | if (avctx->width & 1) { |
||
91 | av_log(avctx, AV_LOG_ERROR, |
||
92 | "4:2:2 video requires even width.\n"); |
||
93 | return AVERROR_INVALIDDATA; |
||
94 | } |
||
95 | c->planes = 3; |
||
96 | avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); |
||
97 | original_format = UTVIDEO_422; |
||
98 | break; |
||
99 | default: |
||
100 | av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", |
||
101 | avctx->pix_fmt); |
||
102 | return AVERROR_INVALIDDATA; |
||
103 | } |
||
104 | |||
105 | ff_dsputil_init(&c->dsp, avctx); |
||
106 | |||
107 | /* Check the prediction method, and error out if unsupported */ |
||
108 | if (avctx->prediction_method < 0 || avctx->prediction_method > 4) { |
||
109 | av_log(avctx, AV_LOG_WARNING, |
||
110 | "Prediction method %d is not supported in Ut Video.\n", |
||
111 | avctx->prediction_method); |
||
112 | return AVERROR_OPTION_NOT_FOUND; |
||
113 | } |
||
114 | |||
115 | if (avctx->prediction_method == FF_PRED_PLANE) { |
||
116 | av_log(avctx, AV_LOG_ERROR, |
||
117 | "Plane prediction is not supported in Ut Video.\n"); |
||
118 | return AVERROR_OPTION_NOT_FOUND; |
||
119 | } |
||
120 | |||
121 | /* Convert from libavcodec prediction type to Ut Video's */ |
||
122 | c->frame_pred = ff_ut_pred_order[avctx->prediction_method]; |
||
123 | |||
124 | if (c->frame_pred == PRED_GRADIENT) { |
||
125 | av_log(avctx, AV_LOG_ERROR, "Gradient prediction is not supported.\n"); |
||
126 | return AVERROR_OPTION_NOT_FOUND; |
||
127 | } |
||
128 | |||
129 | avctx->coded_frame = avcodec_alloc_frame(); |
||
130 | |||
131 | if (!avctx->coded_frame) { |
||
132 | av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); |
||
133 | utvideo_encode_close(avctx); |
||
134 | return AVERROR(ENOMEM); |
||
135 | } |
||
136 | |||
137 | /* extradata size is 4 * 32bit */ |
||
138 | avctx->extradata_size = 16; |
||
139 | |||
140 | avctx->extradata = av_mallocz(avctx->extradata_size + |
||
141 | FF_INPUT_BUFFER_PADDING_SIZE); |
||
142 | |||
143 | if (!avctx->extradata) { |
||
144 | av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata.\n"); |
||
145 | utvideo_encode_close(avctx); |
||
146 | return AVERROR(ENOMEM); |
||
147 | } |
||
148 | |||
149 | for (i = 0; i < c->planes; i++) { |
||
150 | c->slice_buffer[i] = av_malloc(c->slice_stride * (avctx->height + 2) + |
||
151 | FF_INPUT_BUFFER_PADDING_SIZE); |
||
152 | if (!c->slice_buffer[i]) { |
||
153 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 1.\n"); |
||
154 | utvideo_encode_close(avctx); |
||
155 | return AVERROR(ENOMEM); |
||
156 | } |
||
157 | } |
||
158 | |||
159 | /* |
||
160 | * Set the version of the encoder. |
||
161 | * Last byte is "implementation ID", which is |
||
162 | * obtained from the creator of the format. |
||
163 | * Libavcodec has been assigned with the ID 0xF0. |
||
164 | */ |
||
165 | AV_WB32(avctx->extradata, MKTAG(1, 0, 0, 0xF0)); |
||
166 | |||
167 | /* |
||
168 | * Set the "original format" |
||
169 | * Not used for anything during decoding. |
||
170 | */ |
||
171 | AV_WL32(avctx->extradata + 4, original_format); |
||
172 | |||
173 | /* Write 4 as the 'frame info size' */ |
||
174 | AV_WL32(avctx->extradata + 8, c->frame_info_size); |
||
175 | |||
176 | /* |
||
177 | * Set how many slices are going to be used. |
||
178 | * Set one slice for now. |
||
179 | */ |
||
180 | c->slices = 1; |
||
181 | |||
182 | /* Set compression mode */ |
||
183 | c->compression = COMP_HUFF; |
||
184 | |||
185 | /* |
||
186 | * Set the encoding flags: |
||
187 | * - Slice count minus 1 |
||
188 | * - Interlaced encoding mode flag, set to zero for now. |
||
189 | * - Compression mode (none/huff) |
||
190 | * And write the flags. |
||
191 | */ |
||
192 | c->flags = (c->slices - 1) << 24; |
||
193 | c->flags |= 0 << 11; // bit field to signal interlaced encoding mode |
||
194 | c->flags |= c->compression; |
||
195 | |||
196 | AV_WL32(avctx->extradata + 12, c->flags); |
||
197 | |||
198 | return 0; |
||
199 | } |
||
200 | |||
201 | static void mangle_rgb_planes(uint8_t *dst[4], int dst_stride, uint8_t *src, |
||
202 | int step, int stride, int width, int height) |
||
203 | { |
||
204 | int i, j; |
||
205 | int k = 2 * dst_stride; |
||
206 | unsigned int g; |
||
207 | |||
208 | for (j = 0; j < height; j++) { |
||
209 | if (step == 3) { |
||
210 | for (i = 0; i < width * step; i += step) { |
||
211 | g = src[i + 1]; |
||
212 | dst[0][k] = g; |
||
213 | g += 0x80; |
||
214 | dst[1][k] = src[i + 2] - g; |
||
215 | dst[2][k] = src[i + 0] - g; |
||
216 | k++; |
||
217 | } |
||
218 | } else { |
||
219 | for (i = 0; i < width * step; i += step) { |
||
220 | g = src[i + 1]; |
||
221 | dst[0][k] = g; |
||
222 | g += 0x80; |
||
223 | dst[1][k] = src[i + 2] - g; |
||
224 | dst[2][k] = src[i + 0] - g; |
||
225 | dst[3][k] = src[i + 3]; |
||
226 | k++; |
||
227 | } |
||
228 | } |
||
229 | k += dst_stride - width; |
||
230 | src += stride; |
||
231 | } |
||
232 | } |
||
233 | |||
234 | /* Write data to a plane with left prediction */ |
||
235 | static void left_predict(uint8_t *src, uint8_t *dst, int stride, |
||
236 | int width, int height) |
||
237 | { |
||
238 | int i, j; |
||
239 | uint8_t prev; |
||
240 | |||
241 | prev = 0x80; /* Set the initial value */ |
||
242 | for (j = 0; j < height; j++) { |
||
243 | for (i = 0; i < width; i++) { |
||
244 | *dst++ = src[i] - prev; |
||
245 | prev = src[i]; |
||
246 | } |
||
247 | src += stride; |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /* Write data to a plane with median prediction */ |
||
252 | static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, int stride, |
||
253 | int width, int height) |
||
254 | { |
||
255 | int i, j; |
||
256 | int A, B; |
||
257 | uint8_t prev; |
||
258 | |||
259 | /* First line uses left neighbour prediction */ |
||
260 | prev = 0x80; /* Set the initial value */ |
||
261 | for (i = 0; i < width; i++) { |
||
262 | *dst++ = src[i] - prev; |
||
263 | prev = src[i]; |
||
264 | } |
||
265 | |||
266 | if (height == 1) |
||
267 | return; |
||
268 | |||
269 | src += stride; |
||
270 | |||
271 | /* |
||
272 | * Second line uses top prediction for the first sample, |
||
273 | * and median for the rest. |
||
274 | */ |
||
275 | A = B = 0; |
||
276 | |||
277 | /* Rest of the coded part uses median prediction */ |
||
278 | for (j = 1; j < height; j++) { |
||
279 | c->dsp.sub_hfyu_median_prediction(dst, src - stride, src, width, &A, &B); |
||
280 | dst += width; |
||
281 | src += stride; |
||
282 | } |
||
283 | } |
||
284 | |||
285 | /* Count the usage of values in a plane */ |
||
286 | static void count_usage(uint8_t *src, int width, |
||
287 | int height, uint64_t *counts) |
||
288 | { |
||
289 | int i, j; |
||
290 | |||
291 | for (j = 0; j < height; j++) { |
||
292 | for (i = 0; i < width; i++) { |
||
293 | counts[src[i]]++; |
||
294 | } |
||
295 | src += width; |
||
296 | } |
||
297 | } |
||
298 | |||
299 | /* Calculate the actual huffman codes from the code lengths */ |
||
300 | static void calculate_codes(HuffEntry *he) |
||
301 | { |
||
302 | int last, i; |
||
303 | uint32_t code; |
||
304 | |||
305 | qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len); |
||
306 | |||
307 | last = 255; |
||
308 | while (he[last].len == 255 && last) |
||
309 | last--; |
||
310 | |||
311 | code = 1; |
||
312 | for (i = last; i >= 0; i--) { |
||
313 | he[i].code = code >> (32 - he[i].len); |
||
314 | code += 0x80000000u >> (he[i].len - 1); |
||
315 | } |
||
316 | |||
317 | qsort(he, 256, sizeof(*he), huff_cmp_sym); |
||
318 | } |
||
319 | |||
320 | /* Write huffman bit codes to a memory block */ |
||
321 | static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size, |
||
322 | int width, int height, HuffEntry *he) |
||
323 | { |
||
324 | PutBitContext pb; |
||
325 | int i, j; |
||
326 | int count; |
||
327 | |||
328 | init_put_bits(&pb, dst, dst_size); |
||
329 | |||
330 | /* Write the codes */ |
||
331 | for (j = 0; j < height; j++) { |
||
332 | for (i = 0; i < width; i++) |
||
333 | put_bits(&pb, he[src[i]].len, he[src[i]].code); |
||
334 | |||
335 | src += width; |
||
336 | } |
||
337 | |||
338 | /* Pad output to a 32bit boundary */ |
||
339 | count = put_bits_count(&pb) & 0x1F; |
||
340 | |||
341 | if (count) |
||
342 | put_bits(&pb, 32 - count, 0); |
||
343 | |||
344 | /* Get the amount of bits written */ |
||
345 | count = put_bits_count(&pb); |
||
346 | |||
347 | /* Flush the rest with zeroes */ |
||
348 | flush_put_bits(&pb); |
||
349 | |||
350 | return count; |
||
351 | } |
||
352 | |||
353 | static int encode_plane(AVCodecContext *avctx, uint8_t *src, |
||
354 | uint8_t *dst, int stride, |
||
355 | int width, int height, PutByteContext *pb) |
||
356 | { |
||
357 | UtvideoContext *c = avctx->priv_data; |
||
358 | uint8_t lengths[256]; |
||
359 | uint64_t counts[256] = { 0 }; |
||
360 | |||
361 | HuffEntry he[256]; |
||
362 | |||
363 | uint32_t offset = 0, slice_len = 0; |
||
364 | int i, sstart, send = 0; |
||
365 | int symbol; |
||
366 | |||
367 | /* Do prediction / make planes */ |
||
368 | switch (c->frame_pred) { |
||
369 | case PRED_NONE: |
||
370 | for (i = 0; i < c->slices; i++) { |
||
371 | sstart = send; |
||
372 | send = height * (i + 1) / c->slices; |
||
373 | av_image_copy_plane(dst + sstart * width, width, |
||
374 | src + sstart * stride, stride, |
||
375 | width, send - sstart); |
||
376 | } |
||
377 | break; |
||
378 | case PRED_LEFT: |
||
379 | for (i = 0; i < c->slices; i++) { |
||
380 | sstart = send; |
||
381 | send = height * (i + 1) / c->slices; |
||
382 | left_predict(src + sstart * stride, dst + sstart * width, |
||
383 | stride, width, send - sstart); |
||
384 | } |
||
385 | break; |
||
386 | case PRED_MEDIAN: |
||
387 | for (i = 0; i < c->slices; i++) { |
||
388 | sstart = send; |
||
389 | send = height * (i + 1) / c->slices; |
||
390 | median_predict(c, src + sstart * stride, dst + sstart * width, |
||
391 | stride, width, send - sstart); |
||
392 | } |
||
393 | break; |
||
394 | default: |
||
395 | av_log(avctx, AV_LOG_ERROR, "Unknown prediction mode: %d\n", |
||
396 | c->frame_pred); |
||
397 | return AVERROR_OPTION_NOT_FOUND; |
||
398 | } |
||
399 | |||
400 | /* Count the usage of values */ |
||
401 | count_usage(dst, width, height, counts); |
||
402 | |||
403 | /* Check for a special case where only one symbol was used */ |
||
404 | for (symbol = 0; symbol < 256; symbol++) { |
||
405 | /* If non-zero count is found, see if it matches width * height */ |
||
406 | if (counts[symbol]) { |
||
407 | /* Special case if only one symbol was used */ |
||
408 | if (counts[symbol] == width * (int64_t)height) { |
||
409 | /* |
||
410 | * Write a zero for the single symbol |
||
411 | * used in the plane, else 0xFF. |
||
412 | */ |
||
413 | for (i = 0; i < 256; i++) { |
||
414 | if (i == symbol) |
||
415 | bytestream2_put_byte(pb, 0); |
||
416 | else |
||
417 | bytestream2_put_byte(pb, 0xFF); |
||
418 | } |
||
419 | |||
420 | /* Write zeroes for lengths */ |
||
421 | for (i = 0; i < c->slices; i++) |
||
422 | bytestream2_put_le32(pb, 0); |
||
423 | |||
424 | /* And that's all for that plane folks */ |
||
425 | return 0; |
||
426 | } |
||
427 | break; |
||
428 | } |
||
429 | } |
||
430 | |||
431 | /* Calculate huffman lengths */ |
||
432 | ff_huff_gen_len_table(lengths, counts); |
||
433 | |||
434 | /* |
||
435 | * Write the plane's header into the output packet: |
||
436 | * - huffman code lengths (256 bytes) |
||
437 | * - slice end offsets (gotten from the slice lengths) |
||
438 | */ |
||
439 | for (i = 0; i < 256; i++) { |
||
440 | bytestream2_put_byte(pb, lengths[i]); |
||
441 | |||
442 | he[i].len = lengths[i]; |
||
443 | he[i].sym = i; |
||
444 | } |
||
445 | |||
446 | /* Calculate the huffman codes themselves */ |
||
447 | calculate_codes(he); |
||
448 | |||
449 | send = 0; |
||
450 | for (i = 0; i < c->slices; i++) { |
||
451 | sstart = send; |
||
452 | send = height * (i + 1) / c->slices; |
||
453 | |||
454 | /* |
||
455 | * Write the huffman codes to a buffer, |
||
456 | * get the offset in bits and convert to bytes. |
||
457 | */ |
||
458 | offset += write_huff_codes(dst + sstart * width, c->slice_bits, |
||
459 | width * (send - sstart), width, |
||
460 | send - sstart, he) >> 3; |
||
461 | |||
462 | slice_len = offset - slice_len; |
||
463 | |||
464 | /* Byteswap the written huffman codes */ |
||
465 | c->dsp.bswap_buf((uint32_t *) c->slice_bits, |
||
466 | (uint32_t *) c->slice_bits, |
||
467 | slice_len >> 2); |
||
468 | |||
469 | /* Write the offset to the stream */ |
||
470 | bytestream2_put_le32(pb, offset); |
||
471 | |||
472 | /* Seek to the data part of the packet */ |
||
473 | bytestream2_seek_p(pb, 4 * (c->slices - i - 1) + |
||
474 | offset - slice_len, SEEK_CUR); |
||
475 | |||
476 | /* Write the slices' data into the output packet */ |
||
477 | bytestream2_put_buffer(pb, c->slice_bits, slice_len); |
||
478 | |||
479 | /* Seek back to the slice offsets */ |
||
480 | bytestream2_seek_p(pb, -4 * (c->slices - i - 1) - offset, |
||
481 | SEEK_CUR); |
||
482 | |||
483 | slice_len = offset; |
||
484 | } |
||
485 | |||
486 | /* And at the end seek to the end of written slice(s) */ |
||
487 | bytestream2_seek_p(pb, offset, SEEK_CUR); |
||
488 | |||
489 | return 0; |
||
490 | } |
||
491 | |||
492 | static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
||
493 | const AVFrame *pic, int *got_packet) |
||
494 | { |
||
495 | UtvideoContext *c = avctx->priv_data; |
||
496 | PutByteContext pb; |
||
497 | |||
498 | uint32_t frame_info; |
||
499 | |||
500 | uint8_t *dst; |
||
501 | |||
502 | int width = avctx->width, height = avctx->height; |
||
503 | int i, ret = 0; |
||
504 | |||
505 | /* Allocate a new packet if needed, and set it to the pointer dst */ |
||
506 | ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * c->slices + width * height) * |
||
507 | c->planes + 4); |
||
508 | |||
509 | if (ret < 0) |
||
510 | return ret; |
||
511 | |||
512 | dst = pkt->data; |
||
513 | |||
514 | bytestream2_init_writer(&pb, dst, pkt->size); |
||
515 | |||
516 | av_fast_malloc(&c->slice_bits, &c->slice_bits_size, |
||
517 | width * height + FF_INPUT_BUFFER_PADDING_SIZE); |
||
518 | |||
519 | if (!c->slice_bits) { |
||
520 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); |
||
521 | return AVERROR(ENOMEM); |
||
522 | } |
||
523 | |||
524 | /* In case of RGB, mangle the planes to Ut Video's format */ |
||
525 | if (avctx->pix_fmt == AV_PIX_FMT_RGBA || avctx->pix_fmt == AV_PIX_FMT_RGB24) |
||
526 | mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data[0], |
||
527 | c->planes, pic->linesize[0], width, height); |
||
528 | |||
529 | /* Deal with the planes */ |
||
530 | switch (avctx->pix_fmt) { |
||
531 | case AV_PIX_FMT_RGB24: |
||
532 | case AV_PIX_FMT_RGBA: |
||
533 | for (i = 0; i < c->planes; i++) { |
||
534 | ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride, |
||
535 | c->slice_buffer[i], c->slice_stride, |
||
536 | width, height, &pb); |
||
537 | |||
538 | if (ret) { |
||
539 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
||
540 | return ret; |
||
541 | } |
||
542 | } |
||
543 | break; |
||
544 | case AV_PIX_FMT_YUV422P: |
||
545 | for (i = 0; i < c->planes; i++) { |
||
546 | ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], |
||
547 | pic->linesize[i], width >> !!i, height, &pb); |
||
548 | |||
549 | if (ret) { |
||
550 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
||
551 | return ret; |
||
552 | } |
||
553 | } |
||
554 | break; |
||
555 | case AV_PIX_FMT_YUV420P: |
||
556 | for (i = 0; i < c->planes; i++) { |
||
557 | ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], |
||
558 | pic->linesize[i], width >> !!i, height >> !!i, |
||
559 | &pb); |
||
560 | |||
561 | if (ret) { |
||
562 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
||
563 | return ret; |
||
564 | } |
||
565 | } |
||
566 | break; |
||
567 | default: |
||
568 | av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", |
||
569 | avctx->pix_fmt); |
||
570 | return AVERROR_INVALIDDATA; |
||
571 | } |
||
572 | |||
573 | /* |
||
574 | * Write frame information (LE 32bit unsigned) |
||
575 | * into the output packet. |
||
576 | * Contains the prediction method. |
||
577 | */ |
||
578 | frame_info = c->frame_pred << 8; |
||
579 | bytestream2_put_le32(&pb, frame_info); |
||
580 | |||
581 | /* |
||
582 | * At least currently Ut Video is IDR only. |
||
583 | * Set flags accordingly. |
||
584 | */ |
||
585 | avctx->coded_frame->key_frame = 1; |
||
586 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; |
||
587 | |||
588 | pkt->size = bytestream2_tell_p(&pb); |
||
589 | pkt->flags |= AV_PKT_FLAG_KEY; |
||
590 | |||
591 | /* Packet should be done */ |
||
592 | *got_packet = 1; |
||
593 | |||
594 | return 0; |
||
595 | } |
||
596 | |||
597 | AVCodec ff_utvideo_encoder = { |
||
598 | .name = "utvideo", |
||
599 | .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), |
||
600 | .type = AVMEDIA_TYPE_VIDEO, |
||
601 | .id = AV_CODEC_ID_UTVIDEO, |
||
602 | .priv_data_size = sizeof(UtvideoContext), |
||
603 | .init = utvideo_encode_init, |
||
604 | .encode2 = utvideo_encode_frame, |
||
605 | .close = utvideo_encode_close, |
||
606 | .pix_fmts = (const enum AVPixelFormat[]) { |
||
607 | AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, |
||
608 | AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE |
||
609 | }, |
||
610 | };><>>>>>>>>>>>>>>>>>>>>>>>>><>><>>>> |