libwebpenc_animencoder: zero initialize the WebPAnimEncoderOptions struct
[ffmpeg.git] / libavcodec / libwebpenc_animencoder.c
1 /*
2  * WebP encoding support via libwebp
3  * Copyright (c) 2015 Urvang Joshi
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  * WebP encoder using libwebp (WebPAnimEncoder API)
25  */
26
27 #include "config.h"
28 #include "libwebpenc_common.h"
29
30 #include <webp/mux.h>
31
32 typedef struct LibWebPAnimContext {
33     LibWebPContextCommon cc;
34     WebPAnimEncoder *enc;     // the main AnimEncoder object
35     int64_t prev_frame_pts;   // pts of the previously encoded frame.
36     int done;                 // If true, we have assembled the bitstream already
37 } LibWebPAnimContext;
38
39 static av_cold int libwebp_anim_encode_init(AVCodecContext *avctx)
40 {
41     int ret = ff_libwebp_encode_init_common(avctx);
42     if (!ret) {
43         LibWebPAnimContext *s = avctx->priv_data;
44         WebPAnimEncoderOptions enc_options = { 0 };
45         WebPAnimEncoderOptionsInit(&enc_options);
46         // TODO(urvang): Expose some options on command-line perhaps.
47         s->enc = WebPAnimEncoderNew(avctx->width, avctx->height, &enc_options);
48         if (!s->enc)
49             return AVERROR(EINVAL);
50         s->prev_frame_pts = -1;
51         s->done = 0;
52     }
53     return ret;
54 }
55
56 static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
57                                      const AVFrame *frame, int *got_packet) {
58     LibWebPAnimContext *s = avctx->priv_data;
59     int ret;
60
61     if (!frame) {
62         if (s->done) {  // Second flush: return empty package to denote finish.
63             *got_packet = 0;
64             return 0;
65         } else {  // First flush: assemble bitstream and return it.
66             WebPData assembled_data = { 0 };
67             ret = WebPAnimEncoderAssemble(s->enc, &assembled_data);
68             if (ret) {
69                 ret = ff_alloc_packet2(avctx, pkt, assembled_data.size, assembled_data.size);
70                 if (ret < 0)
71                     return ret;
72                 memcpy(pkt->data, assembled_data.bytes, assembled_data.size);
73                 s->done = 1;
74                 pkt->flags |= AV_PKT_FLAG_KEY;
75                 pkt->pts = pkt->dts = s->prev_frame_pts + 1;
76                 *got_packet = 1;
77                 return 0;
78             } else {
79                 av_log(s, AV_LOG_ERROR,
80                        "WebPAnimEncoderAssemble() failed with error: %d\n",
81                        VP8_ENC_ERROR_OUT_OF_MEMORY);
82                 return AVERROR(ENOMEM);
83             }
84         }
85     } else {
86         int timestamp_ms;
87         WebPPicture *pic = NULL;
88         AVFrame *alt_frame = NULL;
89         ret = ff_libwebp_get_frame(avctx, &s->cc, frame, &alt_frame, &pic);
90         if (ret < 0)
91             goto end;
92
93         timestamp_ms =
94             avctx->time_base.num * frame->pts * 1000 / avctx->time_base.den;
95         ret = WebPAnimEncoderAdd(s->enc, pic, timestamp_ms, &s->cc.config);
96         if (!ret) {
97                 av_log(avctx, AV_LOG_ERROR,
98                        "Encoding WebP frame failed with error: %d\n",
99                    pic->error_code);
100             ret = ff_libwebp_error_to_averror(pic->error_code);
101             goto end;
102         }
103
104         pkt->pts = pkt->dts = frame->pts;
105         s->prev_frame_pts = frame->pts;  // Save for next frame.
106         ret = 0;
107         *got_packet = 1;
108
109 end:
110         WebPPictureFree(pic);
111         av_freep(&pic);
112         av_frame_free(&alt_frame);
113         return ret;
114     }
115 }
116
117 static int libwebp_anim_encode_close(AVCodecContext *avctx)
118 {
119     LibWebPAnimContext *s = avctx->priv_data;
120     av_frame_free(&s->cc.ref);
121     WebPAnimEncoderDelete(s->enc);
122
123     return 0;
124 }
125
126 static const AVClass class = {
127     .class_name = "libwebp_anim",
128     .item_name  = av_default_item_name,
129     .option     = options,
130     .version    = LIBAVUTIL_VERSION_INT,
131 };
132
133 AVCodec ff_libwebp_anim_encoder = {
134     .name           = "libwebp_anim",
135     .long_name      = NULL_IF_CONFIG_SMALL("libwebp WebP image"),
136     .type           = AVMEDIA_TYPE_VIDEO,
137     .id             = AV_CODEC_ID_WEBP,
138     .priv_data_size = sizeof(LibWebPAnimContext),
139     .init           = libwebp_anim_encode_init,
140     .encode2        = libwebp_anim_encode_frame,
141     .close          = libwebp_anim_encode_close,
142     .capabilities   = AV_CODEC_CAP_DELAY,
143     .pix_fmts       = (const enum AVPixelFormat[]) {
144         AV_PIX_FMT_RGB32,
145         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
146         AV_PIX_FMT_NONE
147     },
148     .priv_class     = &class,
149     .defaults       = libwebp_defaults,
150 };