FFmpeg
Loading...
Searching...
No Matches
pdvenc.c
Go to the documentation of this file.
1/*
2 * PDV video encoder
3 *
4 * Copyright (c) 2026 Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.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#include "libavutil/common.h"
24#include "libavutil/imgutils.h"
25#include "libavutil/mem.h"
26#include "avcodec.h"
27#include "codec_internal.h"
28#include "encode.h"
29#include "zlib_wrapper.h"
30
31#include <limits.h>
32#include <zlib.h>
33
43
45{
46 PDVEncContext *s = avctx->priv_data;
47 int ret;
48
49 ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
50 if (ret < 0)
51 return ret;
52
53 s->row_size = (avctx->width + 7) >> 3;
54
55 s->frame_size = s->row_size * avctx->height;
56
57 s->previous_frame = av_malloc(s->frame_size);
58 s->work_frame = av_malloc(s->frame_size);
59 if (!s->previous_frame || !s->work_frame)
60 return AVERROR(ENOMEM);
61
62 avctx->bits_per_coded_sample = 1;
63
64 return ff_deflate_init(&s->zstream,
66 Z_DEFAULT_COMPRESSION :
67 av_clip(avctx->compression_level, 0, 9),
68 avctx);
69}
70
72{
73 PDVEncContext *s = avctx->priv_data;
74
75 av_freep(&s->previous_frame);
76 av_freep(&s->work_frame);
77 ff_deflate_end(&s->zstream);
78
79 return 0;
80}
81
83 const AVFrame *frame, int *got_packet)
84{
85 PDVEncContext *s = avctx->priv_data;
86 z_stream *const zstream = &s->zstream.zstream;
87 uint8_t *prev = s->previous_frame;
88 uint8_t *curr = s->work_frame;
89 uint8_t *payload;
90 const int keyframe = s->frame_number == 0 || avctx->gop_size <= 1 ||
91 s->frame_number - s->last_keyframe >= avctx->gop_size;
92 int ret;
93 int zret;
94
95 if (s->frame_number == INT_MAX) {
96 av_log(avctx, AV_LOG_ERROR, "Frame counter reached INT_MAX.\n");
97 return AVERROR(EINVAL);
98 }
99
100 {
101 const uint8_t *src = frame->data[0];
102 const ptrdiff_t src_linesize = frame->linesize[0];
103
104 for (int y = 0; y < avctx->height; y++) {
105 memcpy(curr + y * s->row_size, src, s->row_size);
106 src += src_linesize;
107 }
108 }
109
110 ret = ff_get_encode_buffer(avctx, pkt, deflateBound(zstream, s->frame_size), 0);
111 if (ret < 0)
112 return ret;
113
114 if (keyframe) {
115 payload = curr;
116 } else {
117 for (int i = 0; i < s->frame_size; i++)
118 prev[i] ^= curr[i];
119 payload = prev;
120 }
121
122 zret = deflateReset(zstream);
123 if (zret != Z_OK) {
124 av_log(avctx, AV_LOG_ERROR, "Could not reset deflate: %d.\n", zret);
125 return AVERROR_EXTERNAL;
126 }
127
128 zstream->next_in = payload;
129 zstream->avail_in = s->frame_size;
130 zstream->next_out = pkt->data;
131 zstream->avail_out = pkt->size;
132
133 zret = deflate(zstream, Z_FINISH);
134 if (zret != Z_STREAM_END) {
135 av_log(avctx, AV_LOG_ERROR, "Deflate failed with return code: %d.\n", zret);
136 return AVERROR_EXTERNAL;
137 }
138
139 pkt->size = zstream->total_out;
140 if (keyframe) {
141 pkt->flags |= AV_PKT_FLAG_KEY;
142 s->last_keyframe = s->frame_number;
143 }
144
145 FFSWAP(uint8_t*, s->previous_frame, s->work_frame);
146 s->frame_number++;
147 *got_packet = 1;
148
149 return 0;
150}
151
153 .p.name = "pdv",
154 CODEC_LONG_NAME("PDV (PlayDate Video)"),
155 .p.type = AVMEDIA_TYPE_VIDEO,
156 .p.id = AV_CODEC_ID_PDV,
159 .priv_data_size = sizeof(PDVEncContext),
160 .init = encode_init,
162 .close = encode_end,
164 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
165};
const FFCodec ff_pdv_encoder
Definition pdvenc.c:152
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
Libavcodec external API header.
#define FF_COMPRESSION_DEFAULT
Definition avcodec.h:1242
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define CODEC_PIXFMTS(...)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal and external API header
#define av_clip
Definition common.h:100
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame, AVPacket *pkt)
Definition ffmpeg_enc.c:694
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_EXPERIMENTAL
Codec is experimental and is thus avoided in favor of non experimental encoders.
Definition codec.h:90
@ AV_CODEC_ID_PDV
Definition codec_id.h:315
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition imgutils.c:318
static av_cold int encode_end(AVCodecContext *avctx)
Definition huffyuvenc.c:978
misc image utilities
static av_cold int encode_init(AVCodecContext *avctx)
Definition pdvenc.c:44
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Definition pdvenc.c:82
static av_cold int encode_end(AVCodecContext *avctx)
Definition pdvenc.c:71
#define av_cold
Definition attributes.h:117
#define FFSWAP(type, a, b)
Definition macros.h:52
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition pixfmt.h:83
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition avcodec.h:1564
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition avcodec.h:1021
int compression_level
Definition avcodec.h:1241
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int last_keyframe
Definition pdvenc.c:41
int row_size
Definition pdvenc.c:38
uint8_t * previous_frame
Definition pdvenc.c:36
int frame_size
Definition pdvenc.c:39
uint8_t * work_frame
Definition pdvenc.c:37
FFZStream zstream
Definition pdvenc.c:35
int frame_number
Definition pdvenc.c:40
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static void deflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
int ff_deflate_init(FFZStream *zstream, int level, void *logctx)
Wrapper around deflateInit().
void ff_deflate_end(FFZStream *zstream)
Wrapper around deflateEnd().