2 * WebP encoding support via libwebp
3 * Copyright (c) 2015 Urvang Joshi
5 * This file is part of FFmpeg.
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.
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.
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
24 * WebP encoder using libwebp (WebPAnimEncoder API)
28 #include "codec_internal.h"
30 #include "libwebpenc_common.h"
34 typedef struct LibWebPAnimContext
{
35 LibWebPContextCommon cc
;
36 WebPAnimEncoder
*enc
; // the main AnimEncoder object
37 int64_t first_frame_pts
; // pts of the first encoded frame.
38 int done
; // If true, we have assembled the bitstream already
41 static av_cold
int libwebp_anim_encode_init(AVCodecContext
*avctx
)
43 int ret
= ff_libwebp_encode_init_common(avctx
);
45 LibWebPAnimContext
*s
= avctx
->priv_data
;
46 WebPAnimEncoderOptions enc_options
= { { 0 } };
47 WebPAnimEncoderOptionsInit(&enc_options
);
48 enc_options
.verbose
= av_log_get_level() >= AV_LOG_VERBOSE
;
49 // TODO(urvang): Expose some options on command-line perhaps.
50 s
->enc
= WebPAnimEncoderNew(avctx
->width
, avctx
->height
, &enc_options
);
52 return AVERROR(EINVAL
);
53 s
->first_frame_pts
= AV_NOPTS_VALUE
;
59 static int libwebp_anim_encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
60 const AVFrame
*frame
, int *got_packet
) {
61 LibWebPAnimContext
*s
= avctx
->priv_data
;
65 if (s
->done
) { // Second flush: return empty package to denote finish.
68 } else { // First flush: assemble bitstream and return it.
69 WebPData assembled_data
= { 0 };
70 ret
= WebPAnimEncoderAssemble(s
->enc
, &assembled_data
);
72 ret
= ff_get_encode_buffer(avctx
, pkt
, assembled_data
.size
, 0);
74 WebPDataClear(&assembled_data
);
77 memcpy(pkt
->data
, assembled_data
.bytes
, assembled_data
.size
);
78 WebPDataClear(&assembled_data
);
80 pkt
->pts
= pkt
->dts
= s
->first_frame_pts
;
84 WebPDataClear(&assembled_data
);
85 av_log(s
, AV_LOG_ERROR
,
86 "WebPAnimEncoderAssemble() failed with error: %d\n",
87 VP8_ENC_ERROR_OUT_OF_MEMORY
);
88 return AVERROR(ENOMEM
);
93 WebPPicture
*pic
= NULL
;
94 AVFrame
*alt_frame
= NULL
;
95 ret
= ff_libwebp_get_frame(avctx
, &s
->cc
, frame
, &alt_frame
, &pic
);
100 avctx
->time_base
.num
* frame
->pts
* 1000 / avctx
->time_base
.den
;
101 ret
= WebPAnimEncoderAdd(s
->enc
, pic
, timestamp_ms
, &s
->cc
.config
);
103 av_log(avctx
, AV_LOG_ERROR
,
104 "Encoding WebP frame failed with error: %d\n",
106 ret
= ff_libwebp_error_to_averror(pic
->error_code
);
110 if (!avctx
->frame_number
)
111 s
->first_frame_pts
= frame
->pts
;
116 WebPPictureFree(pic
);
118 av_frame_free(&alt_frame
);
123 static int libwebp_anim_encode_close(AVCodecContext
*avctx
)
125 LibWebPAnimContext
*s
= avctx
->priv_data
;
126 av_frame_free(&s
->cc
.ref
);
127 WebPAnimEncoderDelete(s
->enc
);
132 const FFCodec ff_libwebp_anim_encoder
= {
133 .p
.name
= "libwebp_anim",
134 .p
.long_name
= NULL_IF_CONFIG_SMALL("libwebp WebP image"),
135 .p
.type
= AVMEDIA_TYPE_VIDEO
,
136 .p
.id
= AV_CODEC_ID_WEBP
,
137 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_DELAY
,
138 .p
.pix_fmts
= ff_libwebpenc_pix_fmts
,
139 .p
.priv_class
= &ff_libwebpenc_class
,
140 .p
.wrapper_name
= "libwebp",
141 .priv_data_size
= sizeof(LibWebPAnimContext
),
142 .defaults
= ff_libwebp_defaults
,
143 .init
= libwebp_anim_encode_init
,
144 FF_CODEC_ENCODE_CB(libwebp_anim_encode_frame
),
145 .close
= libwebp_anim_encode_close
,