libbpg-0.9.5

This commit is contained in:
King_DuckZ 2015-01-16 13:48:11 +01:00
parent 6e56352f86
commit 357f186837
35 changed files with 3022 additions and 2134 deletions

View file

@ -1,3 +1,11 @@
version 0.9.5:
- Added animation support.
- added bpgview utility.
- bpgenc: fixed support of some JPEG parameter combinations
- fixed JS 8 bit only decoder and renamed it to bpgdec8.js
- libbpg: added CMYK output format
version 0.9.4:
- Modified alpha plane encoding to allow progressive display and

View file

@ -8,6 +8,8 @@
#USE_X265=y
# Enable the JCTVC code (best quality but slow) for the encoder
USE_JCTVC=y
# Compile bpgview (SDL and SDL_image libraries needed)
USE_BPGVIEW=y
# Enable it to use bit depths > 12 (need more tests to validate encoder)
#USE_JCTVC_HIGH_BIT_DEPTH=y
# Enable the cross compilation for Windows
@ -45,7 +47,7 @@ CFLAGS+=-DRExt__HIGH_BIT_DEPTH_SUPPORT
endif
# Emscriptem config
EMLDFLAGS:=-s "EXPORTED_FUNCTIONS=['_bpg_decoder_open','_bpg_decoder_decode','_bpg_decoder_get_info','_bpg_decoder_start','_bpg_decoder_get_line','_bpg_decoder_close','_malloc','_free']"
EMLDFLAGS:=-s "EXPORTED_FUNCTIONS=['_bpg_decoder_open','_bpg_decoder_decode','_bpg_decoder_get_info','_bpg_decoder_start','_bpg_decoder_get_frame_duration','_bpg_decoder_get_line','_bpg_decoder_close','_malloc','_free']"
EMLDFLAGS+=-s NO_FILESYSTEM=1 -s NO_BROWSER=1
#EMLDFLAGS+=-O1 --post-js post.js
EMLDFLAGS+=-O3 --memory-init-file 0 --closure 1 --post-js post.js
@ -61,8 +63,11 @@ CFLAGS+=-g
CXXFLAGS=$(CFLAGS)
PROGS=bpgdec$(EXE) bpgenc$(EXE)
ifdef USE_BPGVIEW
PROGS+=bpgview$(EXE)
endif
ifdef USE_EMCC
PROGS+=bpgdec.js bpgdec8b.js
PROGS+=bpgdec.js bpgdec8.js bpgdec8a.js
endif
all: $(PROGS)
@ -70,7 +75,7 @@ all: $(PROGS)
LIBBPG_OBJS:=$(addprefix libavcodec/, \
hevc_cabac.o hevc_filter.o hevc.o hevcpred.o hevc_refs.o\
hevcdsp.o hevc_mvs.o hevc_ps.o hevc_sei.o\
utils.o cabac.o golomb.o )
utils.o cabac.o golomb.o videodsp.o )
LIBBPG_OBJS+=$(addprefix libavutil/, mem.o buffer.o log2_tab.o frame.o pixdesc.o md5.o )
LIBBPG_OBJS+=libbpg.o
@ -78,12 +83,16 @@ LIBBPG_JS_OBJS:=$(patsubst %.o, %.js.o, $(LIBBPG_OBJS)) tmalloc.js.o
LIBBPG_JS8_OBJS:=$(patsubst %.o, %.js8.o, $(LIBBPG_OBJS)) tmalloc.js8.o
$(LIBBPG_OBJS): CFLAGS+=-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -DHAVE_AV_CONFIG_H -std=c99 -D_GNU_SOURCE=1 -DUSE_VAR_BIT_DEPTH
LIBBPG_JS8A_OBJS:=$(patsubst %.o, %.js8a.o, $(LIBBPG_OBJS)) tmalloc.js8a.o
$(LIBBPG_OBJS): CFLAGS+=-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -DHAVE_AV_CONFIG_H -std=c99 -D_GNU_SOURCE=1 -DUSE_VAR_BIT_DEPTH -DUSE_PRED
$(LIBBPG_JS_OBJS): EMCFLAGS+=-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -DHAVE_AV_CONFIG_H -std=c99 -D_GNU_SOURCE=1 -DUSE_VAR_BIT_DEPTH
$(LIBBPG_JS8_OBJS): EMCFLAGS+=-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -DHAVE_AV_CONFIG_H -std=c99 -D_GNU_SOURCE=1
$(LIBBPG_JS8A_OBJS): EMCFLAGS+=-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -DHAVE_AV_CONFIG_H -std=c99 -D_GNU_SOURCE=1 -DUSE_PRED
BPGENC_OBJS:=bpgenc.o
BPGENC_LIBS:=
@ -121,19 +130,28 @@ BPGENC_OBJS+=jctvc_glue.o jctvc/libjctvc.a
bpgenc.o: CFLAGS+=-DUSE_JCTVC
endif # USE_JCTVC
ifdef CONFIG_WIN32
LIBS:=-lz
LDFLAGS+=-static
BPGDEC_LIBS:=-Wl,-dy -lpng -lz -Wl,-dn
BPGENC_LIBS+=-Wl,-dy -lpng -ljpeg -lz -Wl,-dn
BPGVIEW_LIBS:=-lmingw32 -lSDLmain -Wl,-dy -lSDL_image -lSDL -Wl,-dn -mwindows
else
ifdef CONFIG_APPLE
LIBS:=
else
LIBS:=-lrt
endif # !CONFIG_APPLE
LIBS+=-lm -lpthread
endif # !CONFIG_WIN32
BPGDEC_LIBS:=-lpng $(LIBS)
BPGENC_LIBS+=-lpng -ljpeg $(LIBS)
BPGVIEW_LIBS:=-lSDL_image -lSDL $(LIBS)
endif #!CONFIG_WIN32
bpgenc.o: CFLAGS+=-Wno-unused-but-set-variable
@ -141,17 +159,23 @@ libbpg.a: $(LIBBPG_OBJS)
$(AR) rcs $@ $^
bpgdec$(EXE): bpgdec.o libbpg.a
$(CC) $(LDFLAGS) -o $@ $^ -lpng $(LIBS)
$(CC) $(LDFLAGS) -o $@ $^ $(BPGDEC_LIBS)
bpgenc$(EXE): $(BPGENC_OBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(BPGENC_LIBS)
bpgview$(EXE): bpgview.o libbpg.a
$(CC) $(LDFLAGS) -o $@ $^ $(BPGVIEW_LIBS)
bpgdec.js: $(LIBBPG_JS_OBJS) post.js
$(EMCC) $(EMLDFLAGS) -s TOTAL_MEMORY=33554432 -o $@ $(LIBBPG_JS_OBJS)
bpgdec8b.js: $(LIBBPG_JS8_OBJS) post.js
bpgdec8.js: $(LIBBPG_JS8_OBJS) post.js
$(EMCC) $(EMLDFLAGS) -s TOTAL_MEMORY=16777216 -o $@ $(LIBBPG_JS8_OBJS)
bpgdec8a.js: $(LIBBPG_JS8A_OBJS) post.js
$(EMCC) $(EMLDFLAGS) -s TOTAL_MEMORY=16777216 -o $@ $(LIBBPG_JS8A_OBJS)
size:
strip bpgdec
size bpgdec libbpg.o libavcodec/*.o libavutil/*.o | sort -n
@ -180,6 +204,9 @@ clean:
%.js8.o: %.c
$(EMCC) $(EMCFLAGS) -c -o $@ $<
%.js8a.o: %.c
$(EMCC) $(EMCFLAGS) -c -o $@ $<
-include $(wildcard *.d)
-include $(wildcard libavcodec/*.d)
-include $(wildcard libavutil/*.d)

80
README
View file

@ -1,5 +1,5 @@
BPG Image Encoder and Decoder
-----------------------------
BPG Image library and utilities
-------------------------------
1) Quick introduction
---------------------
@ -14,6 +14,9 @@ BPG Image Encoder and Decoder
and does not support monochrome encoding yet (hence no alpha nor
grayscale images can be encoded with it).
- bpgview: in order to compile it you need to install the SDL and
SDL_image libraries.
- Emscripten usage: in order to generate the Javascript decoder, you
must install Emscripten and enable its use in the Makefile.
@ -72,8 +75,7 @@ as input.
* For JPEG input, the color space of the input image is not
modified (it is YCbCr, RGB, YCbCrK or CMYK). The chroma is
subsampled according to the preferred chroma format ('-f'
option). Images with vertically subsampled chroma are currently
not supported.
option).
* For PNG input, the input image is converted to the preferred
color space ('-c' option). Its chroma is then subsampled
@ -87,6 +89,38 @@ as input.
of a loss in the color components. This loss is not an issue if the
image is not edited.
- Animations: with the '-a' option, animations can be encoded from a
sequence of PNG or JPEG images, indexed from 1 or 0. For example:
./bpgenc -a anim%2d.png -fps 25 -loop 0 -o anim.bpg
generates an animation from anim01.png, anim02.png, etc... The frame
rate is specified with '-fps' and the number of loops with '-loop'
(0 = infinite). If a different delay per image is needed as in some
animated GIFs, a text file can be specified with the '-delayfile'
option. It contains one number per image giving its duration in
centiseconds. All durations are rounded to a multiple of '1/fps', so
it is important to set a consistent frame rate.
The necessary frames and delay file can be generated from animated
GIFs with the ImageMagick tools:
convert -coalesce anim.gif anim%d.png
identify -format "%T\n" anim.gif > anim.txt
In order to reduce the file size, the frame rate can be choosen so
that most frames have a frame period of 1 (hence if anim.txt
contains only frame durations of 5 centiseconds, then choose a frame
rate of 20 frames/s).
As GIFs use paletted colors and 1 bit transparency, it is always
better to start from the source material (e.g. PNG files) to have
the best quality.
A BPG decoder not supporting animations only displays the first
frame.
- By default, bpgenc does not copy the metadata. You can copy them
with the '-keepmetadata' option. For JPEG input, EXIF, ICCP and XMP
are copied. For PNG input, ICCP is copied.
@ -107,7 +141,15 @@ no decoded image is output).
- The '-b' option selects the bit depth (8 or 16) of the PNG
output. It is independent of the internal BPG bit depth.
4) BPG decoding library
4) BPG viewer
-------------
The BPG image viewer uses the SDL library to display BPG images and
other image formats supported by the SDL_image library. The available
keys are displayed by launching bpgview without parameters. bpgview
supports BPG animations.
5) BPG decoding library
-----------------------
BPG images can be decoded in any program with the libbpg
@ -119,13 +161,19 @@ provided as a static one.
Currently there is no similar library for encoding so you should
invoke the bpgenc utility.
5) Javascript decoder
6) Javascript decoder
---------------------
bpgdec.js is a Javascript decoder supporting the BPG file
format. bpgdec8b.js is a specialized version limited to BPG images
using 8 bits per component. It is a little faster and consumes less
memory (16 MB instead of 32 MB by default, you can change the memory
The following Javascript decoders are available, sorted by increasing size:
> 8 bits animations
bpgdec8.js no no
bpgdec.js yes no
bpgdec8a.js no yes
The 8 bit only decoders are a little faster and consumes less memory
(16 MB instead of 32 MB by default, you can change the memory
configuration in the Makefile if you want to handle larger images).
The Javascript decoder substitutes all the <img> tags with a source
@ -138,10 +186,14 @@ The image data is downloaded with the XMLHttpRequest object. So the
BPG images and the BPG Javascript decoder must be in the same domain
unless Cross-Origin Resource Sharing is used.
When animations are displayed, all the frames are stored in memory, so
animations with a large number of frames and large resolutions should
be avoided, as with animated GIFs.
asm.js gives an interesting speed boost, so we hope that more browsers
will support this Javascript subset.
6) FFmpeg modifications
7) FFmpeg modifications
-----------------------
- Completed support of chroma_format_idc = 0 (monochrome mode).
@ -156,7 +208,7 @@ will support this Javascript subset.
14 are supported without code duplication but slower decoding.
- Added a modified SPS header to reduce the size of the BPG decoder
(the solution instead is to generate standard VPS and SPS headers
(an alternate solution is to generate standard VPS and SPS headers
from the BPG header).
- Added defines to keep only the HEVC intra code and suppress the
@ -165,10 +217,10 @@ will support this Javascript subset.
- Stripped FFmpeg from all codecs except HEVC and the necessary
support code.
7) Licensing
8) Licensing
------------
- libbpg and bpgenc are released under the LGPL license (the FFmpeg
- libbpg and bpgdec are released under the LGPL license (the FFmpeg
part is under the LGPL, the BPG specific part is released under the
BSD license).

View file

@ -1 +1 @@
0.9.4
0.9.5

View file

@ -51,7 +51,7 @@ static void ppm_save(BPGDecoderContext *img, const char *filename)
rgb_line = malloc(3 * w);
f = fopen(filename,"w");
f = fopen(filename,"wb");
if (!f) {
fprintf(stderr, "%s: I/O error\n", filename);
exit(1);
@ -195,6 +195,7 @@ static void bpg_show_info(const char *filename, int show_extensions)
"ICC profile",
"XMP",
"Thumbnail",
"Animation control",
};
f = fopen(filename, "rb");
@ -232,16 +233,17 @@ static void bpg_show_info(const char *filename, int show_extensions)
printf(" alpha=%d premul=%d",
p->has_alpha, p->premultiplied_alpha);
}
printf(" format=%s limited_range=%d bit_depth=%d\n",
printf(" format=%s limited_range=%d bit_depth=%d animation=%d\n",
format_str[p->format],
p->limited_range,
p->bit_depth);
p->bit_depth,
p->has_animation);
if (first_md) {
const char *tag_name;
printf("Extension data:\n");
for(md = first_md; md != NULL; md = md->next) {
if (md->tag <= 4)
if (md->tag <= 5)
tag_name = extension_tag_str[md->tag];
else
tag_name = extension_tag_str[0];

1214
bpgenc.c

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,9 @@ extern "C" {
typedef struct {
int w, h;
BPGImageFormatEnum format;
BPGImageFormatEnum format; /* x_VIDEO values are forbidden here */
uint8_t c_h_phase; /* 4:2:2 or 4:2:0 : give the horizontal chroma
position. 0=MPEG2, 1=JPEG. */
uint8_t has_alpha;
uint8_t has_w_plane;
uint8_t limited_range;
@ -42,6 +44,12 @@ typedef struct {
} Image;
typedef struct {
int width;
int height;
int chroma_format; /* 0-3 */
int bit_depth; /* 8-14 */
int intra_only; /* 0-1 */
int qp; /* quantizer 0-51 */
int lossless; /* 0-1 lossless mode */
int sei_decoded_picture_hash; /* 0=no hash, 1=MD5 hash */
@ -49,10 +57,20 @@ typedef struct {
int verbose;
} HEVCEncodeParams;
typedef struct HEVCEncoderContext HEVCEncoderContext;
typedef struct {
HEVCEncoderContext *(*open)(const HEVCEncodeParams *params);
int (*encode)(HEVCEncoderContext *s, Image *img);
int (*close)(HEVCEncoderContext *s, uint8_t **pbuf);
} HEVCEncoder;
extern HEVCEncoder jctvc_encoder;
extern HEVCEncoder x265_hevc_encoder;
int x265_encode_picture(uint8_t **pbuf, Image *img,
const HEVCEncodeParams *params);
int jctvc_encode_picture(uint8_t **pbuf, Image *img,
const HEVCEncodeParams *params);
void save_yuv1(Image *img, FILE *f);
void save_yuv(Image *img, const char *filename);
#ifdef __cplusplus

538
bpgview.c Normal file
View file

@ -0,0 +1,538 @@
/*
* BPG viewer
*
* Copyright (c) 2014-2015 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <getopt.h>
#include <inttypes.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "libbpg.h"
typedef enum {
BG_BLACK,
BG_TILED,
} BackgroundTypeEnum;
typedef struct {
SDL_Surface *img;
int delay; /* in ms */
} Frame;
typedef struct {
int screen_w, screen_h;
int win_w, win_h;
SDL_Surface *screen;
int img_w, img_h;
int frame_count;
Frame *frames;
int frame_index; /* index of the current frame */
int loop_counter;
int loop_count;
SDL_TimerID frame_timer_id;
int is_full_screen;
int pos_x, pos_y;
BackgroundTypeEnum background_type;
} DispContext;
static uint32_t timer_cb(uint32_t interval, void *param);
static inline int clamp_int(int val, int min_val, int max_val)
{
if (val < min_val)
return min_val;
else if (val > max_val)
return max_val;
else
return val;
}
Frame *bpg_load(FILE *f, int *pframe_count, int *ploop_count)
{
BPGDecoderContext *s;
BPGImageInfo bi_s, *bi = &bi_s;
uint8_t *buf;
int len, y;
SDL_Surface *img;
Frame *frames;
uint32_t rmask, gmask, bmask, amask;
int frame_count, i, delay_num, delay_den;
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
if (len < 0)
return NULL;
buf = malloc(len);
if (!buf)
return NULL;
if (fread(buf, 1, len, f) != len)
return NULL;
frames = NULL;
frame_count = 0;
s = bpg_decoder_open();
if (bpg_decoder_decode(s, buf, len) < 0)
goto fail;
bpg_decoder_get_info(s, bi);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
for(;;) {
if (bpg_decoder_start(s, BPG_OUTPUT_FORMAT_RGBA32) < 0)
break;
bpg_decoder_get_frame_duration(s, &delay_num, &delay_den);
frames = realloc(frames, sizeof(frames[0]) * (frame_count + 1));
img = SDL_CreateRGBSurface(SDL_HWSURFACE, bi->width, bi->height, 32,
rmask, gmask, bmask, amask);
if (!img)
goto fail;
SDL_LockSurface(img);
for(y = 0; y < bi->height; y++) {
bpg_decoder_get_line(s, (uint8_t *)img->pixels + y * img->pitch);
}
SDL_UnlockSurface(img);
frames[frame_count].img = img;
frames[frame_count].delay = (delay_num * 1000) / delay_den;
frame_count++;
}
bpg_decoder_close(s);
*pframe_count = frame_count;
*ploop_count = bi->loop_count;
return frames;
fail:
bpg_decoder_close(s);
for(i = 0; i < frame_count; i++) {
SDL_FreeSurface(frames[i].img);
}
free(frames);
*pframe_count = 0;
return NULL;
}
static void restart_frame_timer(DispContext *dc)
{
if (dc->frame_timer_id) {
/* XXX: the SDL timer API is not safe, so we remove the timer even if it already expired */
SDL_RemoveTimer(dc->frame_timer_id);
dc->frame_timer_id = 0;
}
dc->frame_timer_id =
SDL_AddTimer(dc->frames[dc->frame_index].delay, timer_cb, NULL);
}
int load_image(DispContext *dc, const char *filename)
{
SDL_Surface *img;
Frame *frames;
FILE *f;
uint8_t buf[BPG_DECODER_INFO_BUF_SIZE];
int len, i, frame_count, loop_count;
BPGImageInfo bi;
f = fopen(filename, "rb");
if (!f)
goto fail;
len = fread(buf, 1, sizeof(buf), f);
if (bpg_decoder_get_info_from_buf(&bi, NULL, buf, len) >= 0) {
fseek(f, 0, SEEK_SET);
frames = bpg_load(f, &frame_count, &loop_count);
if (!frames)
goto fail;
fclose(f);
} else {
/* use SDL image loader */
img = IMG_Load(filename);
if (!img) {
fail:
fprintf(stderr, "Could not load '%s'\n", filename);
return -1;
}
frame_count = 1;
frames = malloc(sizeof(dc->frames[0]) * frame_count);
frames[0].img = img;
frames[0].delay = 0;
loop_count = 1;
}
for(i = 0; i < dc->frame_count; i++) {
SDL_FreeSurface(dc->frames[i].img);
}
free(dc->frames);
if (dc->frame_timer_id) {
SDL_RemoveTimer(dc->frame_timer_id);
dc->frame_timer_id = 0;
}
dc->frame_count = frame_count;
dc->frames = frames;
dc->frame_index = 0;
dc->loop_counter = 0;
dc->loop_count = loop_count;
dc->img_w = dc->frames[0].img->w;
dc->img_h = dc->frames[0].img->h;
/* start the animation timer if needed */
if (dc->frame_count > 1) {
restart_frame_timer(dc);
}
return 0;
}
void center_image(DispContext *dc)
{
dc->pos_x = clamp_int((dc->screen->w - dc->img_w) / 2, -32767, 32768);
dc->pos_y = clamp_int((dc->screen->h - dc->img_h) / 2, -32767, 32768);
}
void draw_image(DispContext *dc)
{
SDL_Rect r;
r.x = 0;
r.y = 0;
r.w = dc->screen->w;
r.h = dc->screen->h;
SDL_FillRect(dc->screen, &r, SDL_MapRGB(dc->screen->format, 0x00, 0x00, 0x00));
if (dc->background_type == BG_TILED) {
int x, y, tw, w, h, x2, y2, w1, h1, x1, y1;
uint32_t bgcolors[2];
tw = 16;
w = dc->img_w;
h = dc->img_h;
w1 = (w + tw - 1) / tw;
h1 = (h + tw - 1) / tw;
bgcolors[0] = SDL_MapRGB(dc->screen->format, 100, 100, 100);
bgcolors[1] = SDL_MapRGB(dc->screen->format, 150, 150, 150);
for(y = 0; y < h1; y++) {
for(x = 0; x < w1; x++) {
x1 = x * tw;
y1 = y * tw;
x2 = x1 + tw;
y2 = y1 + tw;
if (x2 > w)
x2 = w;
if (y2 > h)
y2 = h;
r.x = x1 + dc->pos_x;
r.y = y1 + dc->pos_y;
r.w = x2 - x1;
r.h = y2 - y1;
SDL_FillRect(dc->screen, &r, bgcolors[(x ^ y) & 1]);
}
}
}
r.x = dc->pos_x;
r.y = dc->pos_y;
r.w = 0;
r.h = 0;
SDL_BlitSurface (dc->frames[dc->frame_index].img, NULL, dc->screen, &r);
SDL_Flip(dc->screen);
}
void pan_image(DispContext *dc, int dx, int dy)
{
int dw, dh;
dw = dc->img_w - dc->screen->w;
dh = dc->img_h - dc->screen->h;
if (dw > 0) {
dc->pos_x += dx;
if (dc->pos_x < -dw)
dc->pos_x = -dw;
else if (dc->pos_x > 0)
dc->pos_x = 0;
}
if (dh > 0) {
dc->pos_y += dy;
if (dc->pos_y < -dh)
dc->pos_y = -dh;
else if (dc->pos_y > 0)
dc->pos_y = 0;
}
draw_image(dc);
}
static void set_caption(DispContext *dc, char **argv,
int image_index, int image_count)
{
char buf[1024];
const char *filename;
filename = argv[image_index];
snprintf(buf, sizeof(buf), "bpgview [%d of %d] - %s",
image_index + 1, image_count, filename);
SDL_WM_SetCaption(buf, buf);
}
static void open_window(DispContext *dc, int w, int h, int is_full_screen)
{
int flags;
flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL;
if (is_full_screen)
flags |= SDL_FULLSCREEN;
else
flags |= SDL_RESIZABLE;
dc->screen = SDL_SetVideoMode(w, h, 32, flags);
if (!dc->screen) {
fprintf(stderr, "Could not init screen\n");
exit(1);
}
}
static uint32_t timer_cb(uint32_t interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
return 0;
}
#define DEFAULT_W 640
#define DEFAULT_H 480
static void help(void)
{
const char *str;
str = "BPG Image Viewer version " CONFIG_BPG_VERSION "\n"
"usage: bpgview infile...\n"
"\n"
"Keys:\n"
"q, ESC quit\n"
"n, SPACE next image\n"
"p previous image\n"
"arrows pan\n"
"c center\n"
"b toggle background type\n";
#ifdef WIN32
MessageBox(NULL, str, "Error", MB_ICONERROR | MB_OK);
exit(1);
#else
printf("%s", str);
exit(1);
#endif
}
int main(int argc, char **argv)
{
int c, image_index, image_count, incr, i;
SDL_Event event;
DispContext dc_s, *dc = &dc_s;
const SDL_VideoInfo *vi;
for(;;) {
c = getopt(argc, argv, "h");
if (c == -1)
break;
switch(c) {
case 'h':
show_help:
help();
break;
default:
exit(1);
}
}
if (optind >= argc)
goto show_help;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
fprintf(stderr, "Could not init SDL\n");
exit(1);
}
memset(dc, 0, sizeof(*dc));
vi = SDL_GetVideoInfo();
dc->screen_w = vi->current_w;
dc->screen_h = vi->current_h;
dc->is_full_screen = 0;
image_count = argc - optind;
image_index = 0;
if (load_image(dc, argv[optind + image_index]) < 0)
exit(1);
dc->background_type = BG_TILED;
{
int w, h;
if (image_count > 1 || (dc->img_w < 256 || dc->img_h < 256)) {
w = DEFAULT_W;
h = DEFAULT_H;
} else {
w = clamp_int(dc->img_w, 32, dc->screen_w);
h = clamp_int(dc->img_h, 32, dc->screen_h);
}
open_window(dc, w, h, 0);
set_caption(dc, argv + optind, image_index, image_count);
}
center_image(dc);
draw_image(dc);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
for(;;) {
if (!SDL_WaitEvent(&event))
continue;
switch(event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
goto done;
case SDLK_SPACE: /* next image */
case SDLK_n:
incr = 1;
goto prev_next;
case SDLK_p: /* previous image */
incr = -1;
prev_next:
if (image_count > 1) {
for(i = 0; i < image_count; i++) {
image_index += incr;
if (image_index < 0)
image_index = image_count - 1;
else if (image_index >= image_count)
image_index = 0;
if (load_image(dc, argv[optind + image_index]) == 0)
break;
}
if (i == image_count)
exit(1);
set_caption(dc, argv + optind, image_index, image_count);
center_image(dc);
draw_image(dc);
}
break;
case SDLK_LEFT:
pan_image(dc, 32, 0);
break;
case SDLK_RIGHT:
pan_image(dc, -32, 0);
break;
case SDLK_UP:
pan_image(dc, 0, 32);
break;
case SDLK_DOWN:
pan_image(dc, 0, -32);
break;
case SDLK_c:
center_image(dc);
draw_image(dc);
break;
case SDLK_b:
dc->background_type ^= 1;
draw_image(dc);
break;
case SDLK_f:
dc->is_full_screen ^= 1;
if (dc->is_full_screen) {
/* save old windows size */
dc->win_w = dc->screen->w;
dc->win_h = dc->screen->h;
open_window(dc, dc->screen_w, dc->screen_h, 1);
} else {
open_window(dc, dc->win_w, dc->win_h, 0);
}
center_image(dc);
draw_image(dc);
break;
default:
break;
}
break;
case SDL_VIDEORESIZE:
{
open_window(dc, event.resize.w, event.resize.h, 0);
center_image(dc);
draw_image(dc);
}
break;
case SDL_QUIT:
goto done;
case SDL_MOUSEMOTION:
if (event.motion.state) {
pan_image(dc, event.motion.xrel, event.motion.yrel);
}
break;
case SDL_USEREVENT:
if (dc->frame_count > 1) {
/* show next frame */
if (dc->frame_index == (dc->frame_count - 1)) {
if (dc->loop_count == 0 ||
dc->loop_counter < (dc->loop_count - 1)) {
dc->frame_index = 0;
dc->loop_counter++;
} else {
break;
}
} else {
dc->frame_index++;
}
draw_image(dc);
restart_frame_timer(dc);
}
break;
default:
break;
}
}
done:
SDL_FreeSurface(dc->screen);
return 0;
}

View file

@ -1828,5 +1828,7 @@
//#define USE_FULL /* include HEVC code not relevant for BPG decoding */
//#define USE_FUNC_PTR /* use function pointers for dsp */
//#define USE_AV_LOG /* include av_log() */
#define USE_FRAME_DURATION_SEI /* for animations */
//#define USE_BIPRED /* allow bi-prediction */
#endif /* FFMPEG_CONFIG_H */

View file

@ -1,8 +1,8 @@
BPG Specification
version 0.9.4
version 0.9.5
Copyright (c) 2014 Fabrice Bellard
Copyright (c) 2014-2015 Fabrice Bellard
1) Introduction
---------------
@ -26,6 +26,9 @@ alpha and color data.
Arbitrary metadata (such as EXIF, ICC profile, XMP) are supported.
Animations are supported as an optional feature. Decoders not
supporting animation display the first frame of the animation.
2) Bitstream conventions
------------------------
@ -69,7 +72,7 @@ heic_file() {
extension_present_flag u(1)
alpha2_flag u(1)
limited_range_flag u(1)
reserved_zero u(1)
animation_flag u(1)
picture_width ue7(32)
picture_height ue7(32)
@ -90,12 +93,26 @@ extension_data()
while (more_bytes()) {
extension_tag ue7(32)
extension_tag_length ue7(32)
for(j = 0; j < extension_tag_length; j++) {
extension_tag_data_byte b(8)
if (extension_tag == 5) {
animation_control_extension(extension_tag_length)
} else {
for(j = 0; j < extension_tag_length; j++) {
extension_tag_data_byte b(8)
}
}
}
}
animation_control_extension(payload_length)
{
loop_count ue7(16)
frame_period_num ue7(16)
frame_period_den ue7(16)
while (more_bytes()) {
dummy_byte b(8)
}
}
hevc_header_and_data()
{
if (alpha1_flag || alpha2_flag) {
@ -148,7 +165,11 @@ hevc_data()
hevc_data_byte b(8)
}
}
frame_duration_sei(payloadSize)
{
frame_duration u(16)
}
3.2) Semantics
--------------
@ -166,9 +187,6 @@ hevc_data()
The other values are reserved.
The chroma samples in the 4:2:0 and 4:2:2 formats are sampled
at the same position as JPEG [2].
'alpha1_flag' and 'alpha2_flag' give information about the alpha plane:
alpha1_flag=0 alpha2_flag=0: no alpha plane.
@ -243,7 +261,11 @@ hevc_data()
The alpha (or W) plane always uses the full range.
'reserved_zero' must be 0 in this version.
'animation_flag'. The value '1' indicates that more than one
frame are encoded in the hevc data. The animation control
extension must be present. If the decoder does not support
animations, it shall decode the first frame only and ignore the
animation information.
'picture_width' is the picture width in pixels. The value 0 is
not allowed.
@ -270,10 +292,20 @@ hevc_data()
4: Thumbnail (the thumbnail shall be a lower resolution version
of the image and stored in BPG format).
5: Animation control data.
The decoder shall ignore the tags it does not support.
'extension_tag_length' is the length in bytes of the extension tag.
'loop_count' gives the number of times the animation shall be
played. The value of 0 means infinite.
'frame_period_num' and 'frame_period_den' encode the default
delay between each frame as frame_period_num/frame_period_den
seconds. The value of 0 for 'frame_period_num' or
'frame_period_den' is forbidden.
'hevc_header_length' is the length in bytes of the following data
up to and including 'trailing_bits'.
@ -324,7 +356,12 @@ hevc_data()
with cb_size = 1 << log2_min_luma_coding_block_size
- bit_depth_luma_minus8 = bit_depth_minus_8
- bit_depth_chroma_minus8 = bit_depth_minus_8
- max_transform_hierarchy_depth_inter = max_transform_hierarchy_depth_intra
- scaling_list_enabled_flag = 0
- log2_max_pic_order_cnt_lsb_minus4 = 4
- amp_enabled_flag = 1
- sps_temporal_mvp_enabled_flag = 1
Alpha data encoding:
@ -338,6 +375,16 @@ hevc_data()
slices and should be interleaved with color slices. alpha NALs
shall come before the corresponding color NALs.
Animation encoding:
- The optional prefix SEI with payloadType = 257 (defined in
frame_duration_sei()) specifies that the image must be repeated
'frame_duration' times. 'frame_duration' shall not be zero. If
the frame duration SEI is not present for a given frame,
frame_duration = 1 shall be assumed by the decoder. If alpha
data is present, the frame duration SEI shall be present only
for the color data.
3.3) HEVC Profile
-----------------
@ -366,6 +413,14 @@ two is done for the chroma and that the width (resp. height) is n
pixels, ceil(n/2) pixels must be kept as the resulting chroma
information.
When animations are present, the next frames shall be encoded with the
following changes:
- P slices are allowed (but B slices are not allowed).
- Only the previous picture can be used as reference (hence a DPB size
of 2 pictures).
4) Design choices
-----------------
@ -434,6 +489,20 @@ information.
easily skip all the metadata because their length is explicitly
stored in the image header.
- Animations: they are interesting compared to WebM or MP4 short
videos for the following reasons:
* transparency is supported
* lossless encoding is supported
* the decoding resources are smaller than with a generic video
player because only two frames need to be stored (DPB size = 2).
* the animations are expected to be small so the decoder can cache
all the decoded frames in memory.
* the animation can be decoded as a still image if the decoder
does not support animations.
Compared to the other animated image formats (GIF, APNG, WebP), the
compression ratio is usually much higher because of the HEVC inter
frame prediction.
5) References
-------------

File diff suppressed because one or more lines are too long

92
html/bpgdec8.js Normal file

File diff suppressed because one or more lines are too long

99
html/bpgdec8a.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
html/clock.bpg Normal file

Binary file not shown.

View file

@ -1,13 +1,21 @@
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="bpgdec8b.js"></script>
<!-- The following scripts are available (sorted by increasing size):
bpgdec8.js : 8 bit only, no animation
bpgdec.js : up to 14 bits, no animation
bpgdec8a.js : 8 bit only, animations
-->
<script type="text/javascript" src="bpgdec8a.js"></script>
</head>
<body>
<h1>BPG Decoding Demo</h1>
IMG tag:<br>
<img src="lena512color.bpg">
<p>
IMG tag with animated image:<br>
<img src="clock.bpg">
<p>
Dynamic loading in a canvas:<br>
<canvas id="mycanvas" width="512" height="512"></canvas>
<script>

View file

@ -1022,7 +1022,7 @@ Bool TAppEncCfg::parseCfg( Int argc, Char* argv[] )
("SEIMasteringDisplayMinLuminance", m_masteringDisplay.minLuminance, 0u, "Specifies the mastering display minimum luminance value in units of 1/10000 candela per square metre (32-bit code value)")
("SEIMasteringDisplayPrimaries", cfg_DisplayPrimariesCode, cfg_DisplayPrimariesCode, "Mastering display primaries for all three colour planes in CIE xy coordinates in increments of 1/50000 (results in the ranges 0 to 50000 inclusive)")
("SEIMasteringDisplayWhitePoint", cfg_DisplayWhitePointCode, cfg_DisplayWhitePointCode, "Mastering display white point CIE xy coordinates in normalised increments of 1/50000 (e.g. 0.333 = 16667)")
("Verbose", m_verboseLevel, 1, "verboseLeveL")
("Verbose", m_verboseLevel, 1, "verbose level")
;
@ -1476,7 +1476,7 @@ Void TAppEncCfg::xCheckParameter()
{
xConfirmPara(bUsingGeneralRExtTools, "Combination of tools and profiles are not possible in the specified RExt profile.");
}
if (!m_intraConstraintFlag && m_bitDepthConstraint==16 && m_chromaFormatConstraint==CHROMA_444)
if (!m_intraConstraintFlag && m_bitDepthConstraint==16 && m_chromaFormatConstraint==CHROMA_444 && 0)
{
fprintf(stderr, "********************************************************************************************************\n");
fprintf(stderr, "** WARNING: The RExt constraint flags describe a non standard combination (used for development only) **\n");

View file

@ -42,6 +42,8 @@
//! \ingroup TLibEncoder
//! \{
#define SRPS_IN_SLICE 1
#if ENC_DEC_TRACE
Void xTraceSPSHeader (TComSPS *pSPS)
@ -545,16 +547,16 @@ Void TEncCavlc::codeSPS( TComSPS* pcSPS )
TComRPSList* rpsList = pcSPS->getRPSList();
TComReferencePictureSet* rps;
if (1) {
#if SRPS_IN_SLICE
WRITE_UVLC(0, "num_short_term_ref_pic_sets" );
} else {
#else
WRITE_UVLC(rpsList->getNumberOfReferencePictureSets(), "num_short_term_ref_pic_sets" );
for(Int i=0; i < rpsList->getNumberOfReferencePictureSets(); i++)
{
rps = rpsList->getReferencePictureSet(i);
codeShortTermRefPicSet(pcSPS,rps,false, i);
}
}
#endif
WRITE_FLAG( pcSPS->getLongTermRefsPresent() ? 1 : 0, "long_term_ref_pics_present_flag" );
if (pcSPS->getLongTermRefsPresent())
{
@ -776,6 +778,12 @@ Void TEncCavlc::codeSliceHeader ( TComSlice* pcSlice )
}
}
#if SRPS_IN_SLICE
{
WRITE_FLAG( 0, "short_term_ref_pic_set_sps_flag");
codeShortTermRefPicSet(pcSlice->getSPS(), rps, true, 0);
}
#else
if(pcSlice->getRPSidx() < 0)
{
WRITE_FLAG( 0, "short_term_ref_pic_set_sps_flag");
@ -794,6 +802,7 @@ Void TEncCavlc::codeSliceHeader ( TComSlice* pcSlice )
WRITE_CODE( pcSlice->getRPSidx(), numBits, "short_term_ref_pic_set_idx" );
}
}
#endif
if(pcSlice->getSPS()->getLongTermRefsPresent())
{
Int numLtrpInSH = rps->getNumberOfLongtermPictures();

View file

@ -9,7 +9,15 @@
#include "bpgenc.h"
#define ARGV_MAX 128
struct HEVCEncoderContext {
HEVCEncodeParams params;
char infilename[1024];
char outfilename[1024];
FILE *yuv_file;
int frame_count;
};
#define ARGV_MAX 256
static void add_opt(int *pargc, char **argv,
const char *str)
@ -22,31 +30,59 @@ static void add_opt(int *pargc, char **argv,
*pargc = argc;
}
/* return the encoded data in *pbuf and the size. Return < 0 if error */
int jctvc_encode_picture(uint8_t **pbuf, Image *img,
const HEVCEncodeParams *params)
static HEVCEncoderContext *jctvc_open(const HEVCEncodeParams *params)
{
TAppEncTop cTAppEncTop;
HEVCEncoderContext *s;
char buf[1024];
static int tmp_idx = 1;
s = (HEVCEncoderContext *)malloc(sizeof(HEVCEncoderContext));
memset(s, 0, sizeof(*s));
s->params = *params;
#ifdef WIN32
if (GetTempPath(sizeof(buf), buf) > sizeof(buf) - 1) {
fprintf(stderr, "Temporary path too long\n");
free(s);
return NULL;
}
#else
strcpy(buf, "/tmp/");
#endif
snprintf(s->infilename, sizeof(s->infilename), "%sout%d-%d.yuv", buf, getpid(), tmp_idx);
snprintf(s->outfilename, sizeof(s->outfilename), "%sout%d-%d.bin", buf, getpid(), tmp_idx);
tmp_idx++;
s->yuv_file = fopen(s->infilename, "wb");
if (!s->yuv_file) {
fprintf(stderr, "Could not open '%s'\n", s->infilename);
free(s);
return NULL;
}
return s;
}
static int jctvc_encode(HEVCEncoderContext *s, Image *img)
{
save_yuv1(img, s->yuv_file);
s->frame_count++;
return 0;
}
/* return the encoded data in *pbuf and the size. Return < 0 if error */
static int jctvc_close(HEVCEncoderContext *s, uint8_t **pbuf)
{
TAppEncTop cTAppEncTop;
int argc;
char *argv[ARGV_MAX + 1];
char buf[1024], infilename[1024], outfilename[1024];
char buf[1024];
const char *str;
FILE *f;
uint8_t *out_buf;
int out_buf_len, i;
#ifdef WIN32
if (GetTempPath(sizeof(buf), buf) > sizeof(buf) - 1) {
fprintf(stderr, "Temporary path too long\n");
return -1;
}
#else
strcpy(buf, "/tmp/");
#endif
snprintf(infilename, sizeof(infilename), "%sout%d.yuv", buf, getpid());
snprintf(outfilename, sizeof(outfilename), "%sout%d.bin", buf, getpid());
save_yuv(img, infilename);
fclose(s->yuv_file);
s->yuv_file = NULL;
m_gcAnalyzeAll.clear();
m_gcAnalyzeI.clear();
@ -59,22 +95,19 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
argc = 0;
add_opt(&argc, argv, "jctvc"); /* dummy executable name */
snprintf(buf, sizeof(buf),"--InputFile=%s", infilename);
snprintf(buf, sizeof(buf),"--InputFile=%s", s->infilename);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--BitstreamFile=%s", outfilename);
snprintf(buf, sizeof(buf),"--BitstreamFile=%s", s->outfilename);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--SourceWidth=%d", img->w);
snprintf(buf, sizeof(buf),"--SourceWidth=%d", s->params.width);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--SourceHeight=%d", s->params.height);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--InputBitDepth=%d", s->params.bit_depth);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--SourceWidth=%d", img->w);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--SourceHeight=%d", img->h);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--InputBitDepth=%d", img->bit_depth);
add_opt(&argc, argv, buf);
switch(img->format) {
switch(s->params.chroma_format) {
case BPG_FORMAT_GRAY:
str = "400";
break;
@ -93,18 +126,19 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
snprintf(buf, sizeof(buf),"--InputChromaFormat=%s", str);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--QP=%d", params->qp);
snprintf(buf, sizeof(buf),"--QP=%d", s->params.qp);
add_opt(&argc, argv, buf);
snprintf(buf, sizeof(buf),"--SEIDecodedPictureHash=%d",
params->sei_decoded_picture_hash);
s->params.sei_decoded_picture_hash);
add_opt(&argc, argv, buf);
if (!params->verbose)
if (!s->params.verbose)
add_opt(&argc, argv, "--Verbose=0");
/* single frame */
add_opt(&argc, argv, "--FramesToBeEncoded=1");
snprintf(buf, sizeof(buf),"--FramesToBeEncoded=%d", s->frame_count);
add_opt(&argc, argv, buf);
/* no padding necessary (it is done before) */
add_opt(&argc, argv, "--ConformanceWindowMode=0");
@ -113,22 +147,43 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
add_opt(&argc, argv, "--FrameRate=25");
/* general config */
add_opt(&argc, argv, "--Profile=main_444_16_intra");
add_opt(&argc, argv, "--QuadtreeTULog2MaxSize=5");
add_opt(&argc, argv, "--QuadtreeTUMaxDepthIntra=3");
if (s->params.compress_level == 9) {
add_opt(&argc, argv, "--QuadtreeTUMaxDepthIntra=4");
add_opt(&argc, argv, "--QuadtreeTUMaxDepthInter=4");
} else {
add_opt(&argc, argv, "--QuadtreeTUMaxDepthIntra=3");
add_opt(&argc, argv, "--QuadtreeTUMaxDepthInter=3");
}
add_opt(&argc, argv, "--IntraPeriod=1");
add_opt(&argc, argv, "--GOPSize=1");
if (s->params.intra_only) {
add_opt(&argc, argv, "--Profile=main_444_16_intra");
add_opt(&argc, argv, "--IntraPeriod=1");
add_opt(&argc, argv, "--GOPSize=1");
} else {
int gop_size;
add_opt(&argc, argv, "--Profile=main_444_16");
add_opt(&argc, argv, "--IntraPeriod=250");
gop_size = 1;
snprintf(buf, sizeof(buf), "--GOPSize=%d", gop_size);
add_opt(&argc, argv, buf);
for(i = 0; i < gop_size; i++) {
snprintf(buf, sizeof(buf), "--Frame%d=P 1 3 0.4624 0 0 0 1 1 -1 0", i + 1);
add_opt(&argc, argv, buf);
}
}
add_opt(&argc, argv, "--TransformSkip=1");
add_opt(&argc, argv, "--TransformSkipFast=1");
/* Note: Format Range extension */
if (img->format == BPG_FORMAT_444) {
if (s->params.chroma_format == BPG_FORMAT_444) {
add_opt(&argc, argv, "--CrossComponentPrediction=1");
}
if (params->lossless) {
if (s->params.lossless) {
add_opt(&argc, argv, "--CostMode=lossless");
add_opt(&argc, argv, "--SAO=0");
add_opt(&argc, argv, "--LoopFilterDisable");
@ -148,7 +203,7 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
/* trailing NULL */
argv[argc] = NULL;
if (params->verbose >= 2) {
if (s->params.verbose >= 2) {
int i;
printf("Encode options:");
for(i = 0; i < argc; i++) {
@ -169,12 +224,12 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
for(i = 0; i < argc; i++)
free(argv[i]);
unlink(infilename);
unlink(s->infilename);
/* read output bitstream */
f = fopen(outfilename, "rb");
f = fopen(s->outfilename, "rb");
if (!f) {
fprintf(stderr, "Could not open '%s'\n", outfilename);
fprintf(stderr, "Could not open '%s'\n", s->outfilename);
return -1;
}
@ -189,7 +244,14 @@ int jctvc_encode_picture(uint8_t **pbuf, Image *img,
return -1;
}
fclose(f);
unlink(outfilename);
unlink(s->outfilename);
*pbuf = out_buf;
free(s);
return out_buf_len;
}
HEVCEncoder jctvc_encoder = {
.open = jctvc_open,
.encode = jctvc_encode,
.close = jctvc_close,
};

View file

@ -1,592 +0,0 @@
/*
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
* Copyright (c) 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
*/
#include "config.h"
#include "avcodec.h"
#include "version.h"
#define REGISTER_HWACCEL(X, x) \
{ \
extern AVHWAccel ff_##x##_hwaccel; \
if (CONFIG_##X##_HWACCEL) \
av_register_hwaccel(&ff_##x##_hwaccel); \
}
#define REGISTER_ENCODER(X, x) \
{ \
extern AVCodec ff_##x##_encoder; \
if (CONFIG_##X##_ENCODER) \
avcodec_register(&ff_##x##_encoder); \
}
#define REGISTER_DECODER(X, x) \
{ \
extern AVCodec ff_##x##_decoder; \
if (CONFIG_##X##_DECODER) \
avcodec_register(&ff_##x##_decoder); \
}
#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x)
#define REGISTER_PARSER(X, x) \
{ \
extern AVCodecParser ff_##x##_parser; \
if (CONFIG_##X##_PARSER) \
av_register_codec_parser(&ff_##x##_parser); \
}
#define REGISTER_BSF(X, x) \
{ \
extern AVBitStreamFilter ff_##x##_bsf; \
if (CONFIG_##X##_BSF) \
av_register_bitstream_filter(&ff_##x##_bsf); \
}
void avcodec_register_all(void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
/* hardware accelerators */
REGISTER_HWACCEL(H263_VAAPI, h263_vaapi);
REGISTER_HWACCEL(H263_VDPAU, h263_vdpau);
REGISTER_HWACCEL(H264_DXVA2, h264_dxva2);
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi);
REGISTER_HWACCEL(H264_VDA, h264_vda);
REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old);
REGISTER_HWACCEL(H264_VDPAU, h264_vdpau);
REGISTER_HWACCEL(MPEG1_XVMC, mpeg1_xvmc);
REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_HWACCEL(MPEG2_XVMC, mpeg2_xvmc);
REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2);
REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi);
REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau);
REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi);
REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2);
REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi);
REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau);
/* video codecs */
REGISTER_ENCODER(A64MULTI, a64multi);
REGISTER_ENCODER(A64MULTI5, a64multi5);
REGISTER_DECODER(AASC, aasc);
REGISTER_DECODER(AIC, aic);
REGISTER_ENCDEC (ALIAS_PIX, alias_pix);
REGISTER_ENCDEC (AMV, amv);
REGISTER_DECODER(ANM, anm);
REGISTER_DECODER(ANSI, ansi);
REGISTER_ENCDEC (ASV1, asv1);
REGISTER_ENCDEC (ASV2, asv2);
REGISTER_DECODER(AURA, aura);
REGISTER_DECODER(AURA2, aura2);
REGISTER_ENCDEC (AVRP, avrp);
REGISTER_DECODER(AVRN, avrn);
REGISTER_DECODER(AVS, avs);
REGISTER_ENCDEC (AVUI, avui);
REGISTER_ENCDEC (AYUV, ayuv);
REGISTER_DECODER(BETHSOFTVID, bethsoftvid);
REGISTER_DECODER(BFI, bfi);
REGISTER_DECODER(BINK, bink);
REGISTER_ENCDEC (BMP, bmp);
REGISTER_DECODER(BMV_VIDEO, bmv_video);
REGISTER_DECODER(BRENDER_PIX, brender_pix);
REGISTER_DECODER(C93, c93);
REGISTER_DECODER(CAVS, cavs);
REGISTER_DECODER(CDGRAPHICS, cdgraphics);
REGISTER_DECODER(CDXL, cdxl);
REGISTER_ENCDEC (CINEPAK, cinepak);
REGISTER_ENCDEC (CLJR, cljr);
REGISTER_DECODER(CLLC, cllc);
REGISTER_ENCDEC (COMFORTNOISE, comfortnoise);
REGISTER_DECODER(CPIA, cpia);
REGISTER_DECODER(CSCD, cscd);
REGISTER_DECODER(CYUV, cyuv);
REGISTER_DECODER(DFA, dfa);
REGISTER_DECODER(DIRAC, dirac);
REGISTER_ENCDEC (DNXHD, dnxhd);
REGISTER_ENCDEC (DPX, dpx);
REGISTER_DECODER(DSICINVIDEO, dsicinvideo);
REGISTER_ENCDEC (DVVIDEO, dvvideo);
REGISTER_DECODER(DXA, dxa);
REGISTER_DECODER(DXTORY, dxtory);
REGISTER_DECODER(EACMV, eacmv);
REGISTER_DECODER(EAMAD, eamad);
REGISTER_DECODER(EATGQ, eatgq);
REGISTER_DECODER(EATGV, eatgv);
REGISTER_DECODER(EATQI, eatqi);
REGISTER_DECODER(EIGHTBPS, eightbps);
REGISTER_DECODER(EIGHTSVX_EXP, eightsvx_exp);
REGISTER_DECODER(EIGHTSVX_FIB, eightsvx_fib);
REGISTER_DECODER(ESCAPE124, escape124);
REGISTER_DECODER(ESCAPE130, escape130);
REGISTER_DECODER(EXR, exr);
REGISTER_ENCDEC (FFV1, ffv1);
REGISTER_ENCDEC (FFVHUFF, ffvhuff);
REGISTER_DECODER(FIC, fic);
REGISTER_ENCDEC (FLASHSV, flashsv);
REGISTER_ENCDEC (FLASHSV2, flashsv2);
REGISTER_DECODER(FLIC, flic);
REGISTER_ENCDEC (FLV, flv);
REGISTER_DECODER(FOURXM, fourxm);
REGISTER_DECODER(FRAPS, fraps);
REGISTER_DECODER(FRWU, frwu);
REGISTER_DECODER(G2M, g2m);
REGISTER_ENCDEC (GIF, gif);
REGISTER_ENCDEC (H261, h261);
REGISTER_ENCDEC (H263, h263);
REGISTER_DECODER(H263I, h263i);
REGISTER_ENCDEC (H263P, h263p);
REGISTER_DECODER(H264, h264);
REGISTER_DECODER(H264_CRYSTALHD, h264_crystalhd);
REGISTER_DECODER(H264_VDA, h264_vda);
REGISTER_DECODER(H264_VDPAU, h264_vdpau);
REGISTER_DECODER(HEVC, hevc);
REGISTER_DECODER(HNM4_VIDEO, hnm4_video);
REGISTER_ENCDEC (HUFFYUV, huffyuv);
REGISTER_DECODER(IDCIN, idcin);
REGISTER_DECODER(IFF_BYTERUN1, iff_byterun1);
REGISTER_DECODER(IFF_ILBM, iff_ilbm);
REGISTER_DECODER(INDEO2, indeo2);
REGISTER_DECODER(INDEO3, indeo3);
REGISTER_DECODER(INDEO4, indeo4);
REGISTER_DECODER(INDEO5, indeo5);
REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video);
REGISTER_ENCDEC (JPEG2000, jpeg2000);
REGISTER_ENCDEC (JPEGLS, jpegls);
REGISTER_DECODER(JV, jv);
REGISTER_DECODER(KGV1, kgv1);
REGISTER_DECODER(KMVC, kmvc);
REGISTER_DECODER(LAGARITH, lagarith);
REGISTER_ENCODER(LJPEG, ljpeg);
REGISTER_DECODER(LOCO, loco);
REGISTER_DECODER(MDEC, mdec);
REGISTER_DECODER(MIMIC, mimic);
REGISTER_ENCDEC (MJPEG, mjpeg);
REGISTER_DECODER(MJPEGB, mjpegb);
REGISTER_DECODER(MMVIDEO, mmvideo);
REGISTER_DECODER(MOTIONPIXELS, motionpixels);
#if FF_API_XVMC
REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc);
#endif /* FF_API_XVMC */
REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video);
REGISTER_ENCDEC (MPEG4, mpeg4);
REGISTER_DECODER(MPEG4_CRYSTALHD, mpeg4_crystalhd);
REGISTER_DECODER(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_DECODER(MPEGVIDEO, mpegvideo);
REGISTER_DECODER(MPEG_VDPAU, mpeg_vdpau);
REGISTER_DECODER(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_DECODER(MPEG2_CRYSTALHD, mpeg2_crystalhd);
REGISTER_DECODER(MSA1, msa1);
REGISTER_DECODER(MSMPEG4_CRYSTALHD, msmpeg4_crystalhd);
REGISTER_DECODER(MSMPEG4V1, msmpeg4v1);
REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2);
REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3);
REGISTER_DECODER(MSRLE, msrle);
REGISTER_DECODER(MSS1, mss1);
REGISTER_DECODER(MSS2, mss2);
REGISTER_ENCDEC (MSVIDEO1, msvideo1);
REGISTER_DECODER(MSZH, mszh);
REGISTER_DECODER(MTS2, mts2);
REGISTER_DECODER(MVC1, mvc1);
REGISTER_DECODER(MVC2, mvc2);
REGISTER_DECODER(MXPEG, mxpeg);
REGISTER_DECODER(NUV, nuv);
REGISTER_DECODER(PAF_VIDEO, paf_video);
REGISTER_ENCDEC (PAM, pam);
REGISTER_ENCDEC (PBM, pbm);
REGISTER_ENCDEC (PCX, pcx);
REGISTER_ENCDEC (PGM, pgm);
REGISTER_ENCDEC (PGMYUV, pgmyuv);
REGISTER_DECODER(PICTOR, pictor);
REGISTER_ENCDEC (PNG, png);
REGISTER_ENCDEC (PPM, ppm);
REGISTER_ENCDEC (PRORES, prores);
REGISTER_ENCODER(PRORES_AW, prores_aw);
REGISTER_ENCODER(PRORES_KS, prores_ks);
REGISTER_DECODER(PRORES_LGPL, prores_lgpl);
REGISTER_DECODER(PTX, ptx);
REGISTER_DECODER(QDRAW, qdraw);
REGISTER_DECODER(QPEG, qpeg);
REGISTER_ENCDEC (QTRLE, qtrle);
REGISTER_ENCDEC (R10K, r10k);
REGISTER_ENCDEC (R210, r210);
REGISTER_ENCDEC (RAWVIDEO, rawvideo);
REGISTER_DECODER(RL2, rl2);
REGISTER_ENCDEC (ROQ, roq);
REGISTER_DECODER(RPZA, rpza);
REGISTER_ENCDEC (RV10, rv10);
REGISTER_ENCDEC (RV20, rv20);
REGISTER_DECODER(RV30, rv30);
REGISTER_DECODER(RV40, rv40);
REGISTER_ENCDEC (S302M, s302m);
REGISTER_DECODER(SANM, sanm);
REGISTER_ENCDEC (SGI, sgi);
REGISTER_DECODER(SGIRLE, sgirle);
REGISTER_DECODER(SMACKER, smacker);
REGISTER_DECODER(SMC, smc);
REGISTER_DECODER(SMVJPEG, smvjpeg);
REGISTER_ENCDEC (SNOW, snow);
REGISTER_DECODER(SP5X, sp5x);
REGISTER_ENCDEC (SUNRAST, sunrast);
REGISTER_ENCDEC (SVQ1, svq1);
REGISTER_DECODER(SVQ3, svq3);
REGISTER_ENCDEC (TARGA, targa);
REGISTER_DECODER(TARGA_Y216, targa_y216);
REGISTER_DECODER(THEORA, theora);
REGISTER_DECODER(THP, thp);
REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo);
REGISTER_ENCDEC (TIFF, tiff);
REGISTER_DECODER(TMV, tmv);
REGISTER_DECODER(TRUEMOTION1, truemotion1);
REGISTER_DECODER(TRUEMOTION2, truemotion2);
REGISTER_DECODER(TSCC, tscc);
REGISTER_DECODER(TSCC2, tscc2);
REGISTER_DECODER(TXD, txd);
REGISTER_DECODER(ULTI, ulti);
REGISTER_ENCDEC (UTVIDEO, utvideo);
REGISTER_ENCDEC (V210, v210);
REGISTER_DECODER(V210X, v210x);
REGISTER_ENCDEC (V308, v308);
REGISTER_ENCDEC (V408, v408);
REGISTER_ENCDEC (V410, v410);
REGISTER_DECODER(VB, vb);
REGISTER_DECODER(VBLE, vble);
REGISTER_DECODER(VC1, vc1);
REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd);
REGISTER_DECODER(VC1_VDPAU, vc1_vdpau);
REGISTER_DECODER(VC1IMAGE, vc1image);
REGISTER_DECODER(VCR1, vcr1);
REGISTER_DECODER(VMDVIDEO, vmdvideo);
REGISTER_DECODER(VMNC, vmnc);
REGISTER_DECODER(VP3, vp3);
REGISTER_DECODER(VP5, vp5);
REGISTER_DECODER(VP6, vp6);
REGISTER_DECODER(VP6A, vp6a);
REGISTER_DECODER(VP6F, vp6f);
REGISTER_DECODER(VP7, vp7);
REGISTER_DECODER(VP8, vp8);
REGISTER_DECODER(VP9, vp9);
REGISTER_DECODER(VQA, vqa);
REGISTER_DECODER(WEBP, webp);
REGISTER_ENCDEC (WMV1, wmv1);
REGISTER_ENCDEC (WMV2, wmv2);
REGISTER_DECODER(WMV3, wmv3);
REGISTER_DECODER(WMV3_CRYSTALHD, wmv3_crystalhd);
REGISTER_DECODER(WMV3_VDPAU, wmv3_vdpau);
REGISTER_DECODER(WMV3IMAGE, wmv3image);
REGISTER_DECODER(WNV1, wnv1);
REGISTER_DECODER(XAN_WC3, xan_wc3);
REGISTER_DECODER(XAN_WC4, xan_wc4);
REGISTER_ENCDEC (XBM, xbm);
REGISTER_ENCDEC (XFACE, xface);
REGISTER_DECODER(XL, xl);
REGISTER_ENCDEC (XWD, xwd);
REGISTER_ENCDEC (Y41P, y41p);
REGISTER_DECODER(YOP, yop);
REGISTER_ENCDEC (YUV4, yuv4);
REGISTER_DECODER(ZERO12V, zero12v);
REGISTER_DECODER(ZEROCODEC, zerocodec);
REGISTER_ENCDEC (ZLIB, zlib);
REGISTER_ENCDEC (ZMBV, zmbv);
/* audio codecs */
REGISTER_ENCDEC (AAC, aac);
REGISTER_DECODER(AAC_LATM, aac_latm);
REGISTER_ENCDEC (AC3, ac3);
REGISTER_ENCDEC (AC3_FIXED, ac3_fixed);
REGISTER_ENCDEC (ALAC, alac);
REGISTER_DECODER(ALS, als);
REGISTER_DECODER(AMRNB, amrnb);
REGISTER_DECODER(AMRWB, amrwb);
REGISTER_DECODER(APE, ape);
REGISTER_DECODER(ATRAC1, atrac1);
REGISTER_DECODER(ATRAC3, atrac3);
REGISTER_DECODER(ATRAC3P, atrac3p);
REGISTER_DECODER(BINKAUDIO_DCT, binkaudio_dct);
REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft);
REGISTER_DECODER(BMV_AUDIO, bmv_audio);
REGISTER_DECODER(COOK, cook);
REGISTER_ENCDEC (DCA, dca);
REGISTER_DECODER(DSD_LSBF, dsd_lsbf);
REGISTER_DECODER(DSD_MSBF, dsd_msbf);
REGISTER_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar);
REGISTER_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar);
REGISTER_DECODER(DSICINAUDIO, dsicinaudio);
REGISTER_ENCDEC (EAC3, eac3);
REGISTER_DECODER(EVRC, evrc);
REGISTER_DECODER(FFWAVESYNTH, ffwavesynth);
REGISTER_ENCDEC (FLAC, flac);
REGISTER_ENCDEC (G723_1, g723_1);
REGISTER_DECODER(G729, g729);
REGISTER_DECODER(GSM, gsm);
REGISTER_DECODER(GSM_MS, gsm_ms);
REGISTER_DECODER(IAC, iac);
REGISTER_DECODER(IMC, imc);
REGISTER_DECODER(MACE3, mace3);
REGISTER_DECODER(MACE6, mace6);
REGISTER_DECODER(METASOUND, metasound);
REGISTER_DECODER(MLP, mlp);
REGISTER_DECODER(MP1, mp1);
REGISTER_DECODER(MP1FLOAT, mp1float);
REGISTER_ENCDEC (MP2, mp2);
REGISTER_DECODER(MP2FLOAT, mp2float);
REGISTER_ENCODER(MP2FIXED, mp2fixed);
REGISTER_DECODER(MP3, mp3);
REGISTER_DECODER(MP3FLOAT, mp3float);
REGISTER_DECODER(MP3ADU, mp3adu);
REGISTER_DECODER(MP3ADUFLOAT, mp3adufloat);
REGISTER_DECODER(MP3ON4, mp3on4);
REGISTER_DECODER(MP3ON4FLOAT, mp3on4float);
REGISTER_DECODER(MPC7, mpc7);
REGISTER_DECODER(MPC8, mpc8);
REGISTER_ENCDEC (NELLYMOSER, nellymoser);
REGISTER_DECODER(ON2AVC, on2avc);
REGISTER_DECODER(OPUS, opus);
REGISTER_DECODER(PAF_AUDIO, paf_audio);
REGISTER_DECODER(QCELP, qcelp);
REGISTER_DECODER(QDM2, qdm2);
REGISTER_ENCDEC (RA_144, ra_144);
REGISTER_DECODER(RA_288, ra_288);
REGISTER_DECODER(RALF, ralf);
REGISTER_DECODER(SHORTEN, shorten);
REGISTER_DECODER(SIPR, sipr);
REGISTER_DECODER(SMACKAUD, smackaud);
REGISTER_ENCDEC (SONIC, sonic);
REGISTER_ENCODER(SONIC_LS, sonic_ls);
REGISTER_DECODER(TAK, tak);
REGISTER_DECODER(TRUEHD, truehd);
REGISTER_DECODER(TRUESPEECH, truespeech);
REGISTER_ENCDEC (TTA, tta);
REGISTER_DECODER(TWINVQ, twinvq);
REGISTER_DECODER(VMDAUDIO, vmdaudio);
REGISTER_ENCDEC (VORBIS, vorbis);
REGISTER_ENCDEC (WAVPACK, wavpack);
REGISTER_DECODER(WMALOSSLESS, wmalossless);
REGISTER_DECODER(WMAPRO, wmapro);
REGISTER_ENCDEC (WMAV1, wmav1);
REGISTER_ENCDEC (WMAV2, wmav2);
REGISTER_DECODER(WMAVOICE, wmavoice);
REGISTER_DECODER(WS_SND1, ws_snd1);
/* PCM codecs */
REGISTER_ENCDEC (PCM_ALAW, pcm_alaw);
REGISTER_DECODER(PCM_BLURAY, pcm_bluray);
REGISTER_DECODER(PCM_DVD, pcm_dvd);
REGISTER_ENCDEC (PCM_F32BE, pcm_f32be);
REGISTER_ENCDEC (PCM_F32LE, pcm_f32le);
REGISTER_ENCDEC (PCM_F64BE, pcm_f64be);
REGISTER_ENCDEC (PCM_F64LE, pcm_f64le);
REGISTER_DECODER(PCM_LXF, pcm_lxf);
REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
REGISTER_ENCDEC (PCM_S8, pcm_s8);
REGISTER_ENCDEC (PCM_S8_PLANAR, pcm_s8_planar);
REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
REGISTER_ENCDEC (PCM_S16BE_PLANAR, pcm_s16be_planar);
REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
REGISTER_ENCDEC (PCM_S16LE_PLANAR, pcm_s16le_planar);
REGISTER_ENCDEC (PCM_S24BE, pcm_s24be);
REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud);
REGISTER_ENCDEC (PCM_S24LE, pcm_s24le);
REGISTER_ENCDEC (PCM_S24LE_PLANAR, pcm_s24le_planar);
REGISTER_ENCDEC (PCM_S32BE, pcm_s32be);
REGISTER_ENCDEC (PCM_S32LE, pcm_s32le);
REGISTER_ENCDEC (PCM_S32LE_PLANAR, pcm_s32le_planar);
REGISTER_ENCDEC (PCM_U8, pcm_u8);
REGISTER_ENCDEC (PCM_U16BE, pcm_u16be);
REGISTER_ENCDEC (PCM_U16LE, pcm_u16le);
REGISTER_ENCDEC (PCM_U24BE, pcm_u24be);
REGISTER_ENCDEC (PCM_U24LE, pcm_u24le);
REGISTER_ENCDEC (PCM_U32BE, pcm_u32be);
REGISTER_ENCDEC (PCM_U32LE, pcm_u32le);
REGISTER_DECODER(PCM_ZORK, pcm_zork);
/* DPCM codecs */
REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm);
REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm);
REGISTER_DECODER(SOL_DPCM, sol_dpcm);
REGISTER_DECODER(XAN_DPCM, xan_dpcm);
/* ADPCM codecs */
REGISTER_DECODER(ADPCM_4XM, adpcm_4xm);
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
REGISTER_DECODER(ADPCM_AFC, adpcm_afc);
REGISTER_DECODER(ADPCM_CT, adpcm_ct);
REGISTER_DECODER(ADPCM_DTK, adpcm_dtk);
REGISTER_DECODER(ADPCM_EA, adpcm_ea);
REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa);
REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1);
REGISTER_DECODER(ADPCM_EA_R2, adpcm_ea_r2);
REGISTER_DECODER(ADPCM_EA_R3, adpcm_ea_r3);
REGISTER_DECODER(ADPCM_EA_XAS, adpcm_ea_xas);
REGISTER_ENCDEC (ADPCM_G722, adpcm_g722);
REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
REGISTER_DECODER(ADPCM_G726LE, adpcm_g726le);
REGISTER_DECODER(ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_DECODER(ADPCM_IMA_APC, adpcm_ima_apc);
REGISTER_DECODER(ADPCM_IMA_DK3, adpcm_ima_dk3);
REGISTER_DECODER(ADPCM_IMA_DK4, adpcm_ima_dk4);
REGISTER_DECODER(ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
REGISTER_DECODER(ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
REGISTER_DECODER(ADPCM_IMA_ISS, adpcm_ima_iss);
REGISTER_DECODER(ADPCM_IMA_OKI, adpcm_ima_oki);
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
REGISTER_DECODER(ADPCM_IMA_RAD, adpcm_ima_rad);
REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
REGISTER_DECODER(ADPCM_IMA_WS, adpcm_ima_ws);
REGISTER_ENCDEC (ADPCM_MS, adpcm_ms);
REGISTER_DECODER(ADPCM_SBPRO_2, adpcm_sbpro_2);
REGISTER_DECODER(ADPCM_SBPRO_3, adpcm_sbpro_3);
REGISTER_DECODER(ADPCM_SBPRO_4, adpcm_sbpro_4);
REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
REGISTER_DECODER(ADPCM_THP, adpcm_thp);
REGISTER_DECODER(ADPCM_VIMA, adpcm_vima);
REGISTER_DECODER(ADPCM_XA, adpcm_xa);
REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha);
REGISTER_DECODER(VIMA, vima);
/* subtitles */
REGISTER_ENCDEC (SSA, ssa);
REGISTER_ENCDEC (ASS, ass);
REGISTER_ENCDEC (DVBSUB, dvbsub);
REGISTER_ENCDEC (DVDSUB, dvdsub);
REGISTER_DECODER(JACOSUB, jacosub);
REGISTER_DECODER(MICRODVD, microdvd);
REGISTER_ENCDEC (MOVTEXT, movtext);
REGISTER_DECODER(MPL2, mpl2);
REGISTER_DECODER(PGSSUB, pgssub);
REGISTER_DECODER(PJS, pjs);
REGISTER_DECODER(REALTEXT, realtext);
REGISTER_DECODER(SAMI, sami);
REGISTER_ENCDEC (SRT, srt);
REGISTER_DECODER(STL, stl);
REGISTER_ENCDEC (SUBRIP, subrip);
REGISTER_DECODER(SUBVIEWER, subviewer);
REGISTER_DECODER(SUBVIEWER1, subviewer1);
REGISTER_DECODER(TEXT, text);
REGISTER_DECODER(VPLAYER, vplayer);
REGISTER_ENCDEC (WEBVTT, webvtt);
REGISTER_ENCDEC (XSUB, xsub);
/* external libraries */
REGISTER_DECODER(LIBCELT, libcelt);
REGISTER_ENCODER(LIBFAAC, libfaac);
REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac);
REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCDEC (LIBILBC, libilbc);
REGISTER_ENCODER(LIBMP3LAME, libmp3lame);
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb);
REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb);
REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg);
REGISTER_ENCDEC (LIBOPUS, libopus);
REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger);
REGISTER_ENCODER(LIBSHINE, libshine);
REGISTER_ENCDEC (LIBSPEEX, libspeex);
REGISTER_DECODER(LIBSTAGEFRIGHT_H264, libstagefright_h264);
REGISTER_ENCODER(LIBTHEORA, libtheora);
REGISTER_ENCODER(LIBTWOLAME, libtwolame);
REGISTER_ENCDEC (LIBUTVIDEO, libutvideo);
REGISTER_ENCODER(LIBVO_AACENC, libvo_aacenc);
REGISTER_ENCODER(LIBVO_AMRWBENC, libvo_amrwbenc);
REGISTER_ENCDEC (LIBVORBIS, libvorbis);
REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8);
REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9);
REGISTER_ENCODER(LIBWAVPACK, libwavpack);
REGISTER_ENCODER(LIBWEBP, libwebp);
REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
REGISTER_ENCODER(LIBX265, libx265);
REGISTER_ENCODER(LIBXAVS, libxavs);
REGISTER_ENCODER(LIBXVID, libxvid);
REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext);
REGISTER_ENCODER(LIBAACPLUS, libaacplus);
/* text */
REGISTER_DECODER(BINTEXT, bintext);
REGISTER_DECODER(XBIN, xbin);
REGISTER_DECODER(IDF, idf);
/* parsers */
REGISTER_PARSER(AAC, aac);
REGISTER_PARSER(AAC_LATM, aac_latm);
REGISTER_PARSER(AC3, ac3);
REGISTER_PARSER(ADX, adx);
REGISTER_PARSER(BMP, bmp);
REGISTER_PARSER(CAVSVIDEO, cavsvideo);
REGISTER_PARSER(COOK, cook);
REGISTER_PARSER(DCA, dca);
REGISTER_PARSER(DIRAC, dirac);
REGISTER_PARSER(DNXHD, dnxhd);
REGISTER_PARSER(DPX, dpx);
REGISTER_PARSER(DVBSUB, dvbsub);
REGISTER_PARSER(DVDSUB, dvdsub);
REGISTER_PARSER(DVD_NAV, dvd_nav);
REGISTER_PARSER(FLAC, flac);
REGISTER_PARSER(GSM, gsm);
REGISTER_PARSER(H261, h261);
REGISTER_PARSER(H263, h263);
REGISTER_PARSER(H264, h264);
REGISTER_PARSER(HEVC, hevc);
REGISTER_PARSER(MJPEG, mjpeg);
REGISTER_PARSER(MLP, mlp);
REGISTER_PARSER(MPEG4VIDEO, mpeg4video);
REGISTER_PARSER(MPEGAUDIO, mpegaudio);
REGISTER_PARSER(MPEGVIDEO, mpegvideo);
REGISTER_PARSER(OPUS, opus);
REGISTER_PARSER(PNG, png);
REGISTER_PARSER(PNM, pnm);
REGISTER_PARSER(RV30, rv30);
REGISTER_PARSER(RV40, rv40);
REGISTER_PARSER(TAK, tak);
REGISTER_PARSER(VC1, vc1);
REGISTER_PARSER(VORBIS, vorbis);
REGISTER_PARSER(VP3, vp3);
REGISTER_PARSER(VP8, vp8);
REGISTER_PARSER(VP9, vp9);
/* bitstream filters */
REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc);
REGISTER_BSF(CHOMP, chomp);
REGISTER_BSF(DUMP_EXTRADATA, dump_extradata);
REGISTER_BSF(H264_MP4TOANNEXB, h264_mp4toannexb);
REGISTER_BSF(IMX_DUMP_HEADER, imx_dump_header);
REGISTER_BSF(MJPEG2JPEG, mjpeg2jpeg);
REGISTER_BSF(MJPEGA_DUMP_HEADER, mjpega_dump_header);
REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress);
REGISTER_BSF(MOV2TEXTSUB, mov2textsub);
REGISTER_BSF(NOISE, noise);
REGISTER_BSF(REMOVE_EXTRADATA, remove_extradata);
REGISTER_BSF(TEXT2MOVSUB, text2movsub);
}

View file

@ -188,6 +188,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb)
s->sh.chroma_offset_l0[i][1] = 0;
}
}
#ifdef USE_BIPRED
if (s->sh.slice_type == B_SLICE) {
for (i = 0; i < s->sh.nb_refs[L1]; i++) {
luma_weight_l1_flag[i] = get_bits1(gb);
@ -225,6 +226,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb)
}
}
}
#endif
}
static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb)
@ -1355,13 +1357,14 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
if (!weight_flag)
s->hevcdsp.put_hevc_qpel_uni[idx][!!my][!!mx](dst, dststride, src, srcstride,
block_h, mx, my, block_w);
block_h, mx, my, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
else
s->hevcdsp.put_hevc_qpel_uni_w[idx][!!my][!!mx](dst, dststride, src, srcstride,
block_h, s->sh.luma_log2_weight_denom,
luma_weight, luma_offset, mx, my, block_w);
luma_weight, luma_offset, mx, my, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
}
#ifdef USE_BIPRED
/**
* 8.5.3.2.2.1 Luma sample bidirectional interpolation process
*
@ -1437,10 +1440,10 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
}
s->hevcdsp.put_hevc_qpel[idx][!!my0][!!mx0](lc->tmp, src0, src0stride,
block_h, mx0, my0, block_w);
block_h, mx0, my0, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
if (!weight_flag)
s->hevcdsp.put_hevc_qpel_bi[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, lc->tmp,
block_h, mx1, my1, block_w);
block_h, mx1, my1, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
else
s->hevcdsp.put_hevc_qpel_bi_w[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, lc->tmp,
block_h, s->sh.luma_log2_weight_denom,
@ -1448,9 +1451,10 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
s->sh.luma_weight_l1[current_mv->ref_idx[1]],
s->sh.luma_offset_l0[current_mv->ref_idx[0]],
s->sh.luma_offset_l1[current_mv->ref_idx[1]],
mx1, my1, block_w);
mx1, my1, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
}
#endif
/**
* 8.5.3.2.2.2 Chroma sample uniprediction interpolation process
@ -1510,13 +1514,14 @@ static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0,
}
if (!weight_flag)
s->hevcdsp.put_hevc_epel_uni[idx][!!my][!!mx](dst0, dststride, src0, srcstride,
block_h, _mx, _my, block_w);
block_h, _mx, _my, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
else
s->hevcdsp.put_hevc_epel_uni_w[idx][!!my][!!mx](dst0, dststride, src0, srcstride,
block_h, s->sh.chroma_log2_weight_denom,
chroma_weight, chroma_offset, _mx, _my, block_w);
chroma_weight, chroma_offset, _mx, _my, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
}
#ifdef USE_BIPRED
/**
* 8.5.3.2.2.2 Chroma sample bidirectional interpolation process
*
@ -1607,11 +1612,11 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF
}
s->hevcdsp.put_hevc_epel[idx][!!my0][!!mx0](lc->tmp, src1, src1stride,
block_h, _mx0, _my0, block_w);
block_h, _mx0, _my0, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
if (!weight_flag)
s->hevcdsp.put_hevc_epel_bi[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1],
src2, src2stride, lc->tmp,
block_h, _mx1, _my1, block_w);
block_h, _mx1, _my1, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
else
s->hevcdsp.put_hevc_epel_bi_w[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1],
src2, src2stride, lc->tmp,
@ -1621,9 +1626,10 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF
s->sh.chroma_weight_l1[current_mv->ref_idx[1]][cidx],
s->sh.chroma_offset_l0[current_mv->ref_idx[0]][cidx],
s->sh.chroma_offset_l1[current_mv->ref_idx[1]][cidx],
_mx1, _my1, block_w);
_mx1, _my1, block_w BIT_DEPTH_ARG2(s->sps->bit_depth));
}
#endif
#endif /* USE_BIPRED */
#endif /* USE_PRED */
#ifdef USE_FULL
static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref,
@ -1754,65 +1760,78 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
ref0 = refPicList[0].ref[current_mv.ref_idx[0]];
if (!ref0)
return;
#ifdef USE_FULL
hevc_await_progress(s, ref0, &current_mv.mv[0], y0, nPbH);
#endif
}
if (current_mv.pred_flag & PF_L1) {
ref1 = refPicList[1].ref[current_mv.ref_idx[1]];
if (!ref1)
return;
#ifdef USE_FULL
hevc_await_progress(s, ref1, &current_mv.mv[1], y0, nPbH);
#endif
}
if (current_mv.pred_flag == PF_L0) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
luma_mc_uni(s, dst0, s->frame->linesize[0], ref0->frame,
&current_mv.mv[0], x0, y0, nPbW, nPbH,
s->sh.luma_weight_l0[current_mv.ref_idx[0]],
s->sh.luma_offset_l0[current_mv.ref_idx[0]]);
chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1],
0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]);
chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2],
0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]);
if (s->sps->chroma_format_idc != 0) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1],
0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]);
chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2],
0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]);
}
} else if (current_mv.pred_flag == PF_L1) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
luma_mc_uni(s, dst0, s->frame->linesize[0], ref1->frame,
&current_mv.mv[1], x0, y0, nPbW, nPbH,
s->sh.luma_weight_l1[current_mv.ref_idx[1]],
s->sh.luma_offset_l1[current_mv.ref_idx[1]]);
chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1],
1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]);
if (s->sps->chroma_format_idc != 0) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2],
1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]);
chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1],
1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]);
chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2],
1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]);
}
} else if (current_mv.pred_flag == PF_BI) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
#ifdef USE_BIPRED
luma_mc_bi(s, dst0, s->frame->linesize[0], ref0->frame,
&current_mv.mv[0], x0, y0, nPbW, nPbH,
ref1->frame, &current_mv.mv[1], &current_mv);
chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame,
x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 0);
chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame,
x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 1);
if (s->sps->chroma_format_idc != 0) {
int x0_c = x0 >> s->sps->hshift[1];
int y0_c = y0 >> s->sps->vshift[1];
int nPbW_c = nPbW >> s->sps->hshift[1];
int nPbH_c = nPbH >> s->sps->vshift[1];
chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame,
x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 0);
chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame,
x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 1);
}
#else
abort();
#endif
}
}
#endif
@ -2894,7 +2913,7 @@ int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
return length;
}
av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
av_fast_malloc(&nal->rbsp_buffer, (unsigned int *)&nal->rbsp_buffer_size,
length + FF_INPUT_BUFFER_PADDING_SIZE);
if (!nal->rbsp_buffer)
return AVERROR(ENOMEM);
@ -3168,6 +3187,9 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output,
}
s->ref = NULL;
#ifdef USE_FRAME_DURATION_SEI
s->frame_duration = 1;
#endif
ret = decode_nal_units(s, avpkt->data, avpkt->size);
if (ret < 0)
return ret;
@ -3191,6 +3213,9 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output,
}
if (s->output_frame->buf[0]) {
#ifdef USE_FRAME_DURATION_SEI
s->output_frame->pts = s->frame_duration;
#endif
av_frame_move_ref(data, s->output_frame);
*got_output = 1;
}

View file

@ -49,7 +49,11 @@
#ifdef USE_MSPS
#define MAX_VPS_COUNT 16
#define MAX_SPS_COUNT 32
#ifdef USE_PRED
#define MAX_DPB_COUNT 32
#else
#define MAX_DPB_COUNT 1
#endif
#else
#define MAX_VPS_COUNT 1
#define MAX_SPS_COUNT 1
@ -944,6 +948,9 @@ typedef struct HEVCContext {
int sei_hflip, sei_vflip;
int picture_struct;
#ifdef USE_FRAME_DURATION_SEI
uint16_t frame_duration;
#endif
} HEVCContext;
int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps,

View file

@ -1,350 +0,0 @@
/*
* HEVC Annex B format parser
*
* Copyright (C) 2012 - 2013 Guillaume Martres
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/common.h"
#include "parser.h"
#include "hevc.h"
#include "golomb.h"
#define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
typedef struct HEVCParseContext {
HEVCContext h;
ParseContext pc;
} HEVCParseContext;
/**
* Find the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or END_NOT_FOUND
*/
static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
int buf_size)
{
int i;
ParseContext *pc = &((HEVCParseContext *)s->priv_data)->pc;
for (i = 0; i < buf_size; i++) {
int nut;
pc->state64 = (pc->state64 << 8) | buf[i];
if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE)
continue;
nut = (pc->state64 >> 2 * 8 + 1) & 0x3F;
// Beginning of access unit
if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX ||
(nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) {
if (pc->frame_start_found) {
pc->frame_start_found = 0;
return i - 5;
}
} else if (nut <= NAL_RASL_R ||
(nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) {
int first_slice_segment_in_pic_flag = buf[i] >> 7;
if (first_slice_segment_in_pic_flag) {
if (!pc->frame_start_found) {
pc->frame_start_found = 1;
} else { // First slice of next frame found
pc->frame_start_found = 0;
return i - 5;
}
}
}
}
return END_NOT_FOUND;
}
/**
* Parse NAL units of found picture and decode some basic information.
*
* @param s parser context.
* @param avctx codec context.
* @param buf buffer with field/frame data.
* @param buf_size size of the buffer.
*/
static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
HEVCContext *h = &((HEVCParseContext *)s->priv_data)->h;
GetBitContext *gb = &h->HEVClc->gb;
SliceHeader *sh = &h->sh;
const uint8_t *buf_end = buf + buf_size;
int state = -1, i;
HEVCNAL *nal;
/* set some sane default values */
s->pict_type = AV_PICTURE_TYPE_I;
s->key_frame = 0;
s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
h->avctx = avctx;
if (!buf_size)
return 0;
if (h->nals_allocated < 1) {
HEVCNAL *tmp = av_realloc_array(h->nals, 1, sizeof(*tmp));
if (!tmp)
return AVERROR(ENOMEM);
h->nals = tmp;
memset(h->nals, 0, sizeof(*tmp));
h->nals_allocated = 1;
}
nal = &h->nals[0];
for (;;) {
int src_length, consumed;
buf = avpriv_find_start_code(buf, buf_end, &state);
if (--buf + 2 >= buf_end)
break;
src_length = buf_end - buf;
h->nal_unit_type = (*buf >> 1) & 0x3f;
h->temporal_id = (*(buf + 1) & 0x07) - 1;
if (h->nal_unit_type <= NAL_CRA_NUT) {
// Do not walk the whole buffer just to decode slice segment header
if (src_length > 20)
src_length = 20;
}
consumed = ff_hevc_extract_rbsp(h, buf, src_length, nal);
if (consumed < 0)
return consumed;
init_get_bits8(gb, nal->data + 2, nal->size);
switch (h->nal_unit_type) {
case NAL_VPS:
ff_hevc_decode_nal_vps(h);
break;
case NAL_SPS:
ff_hevc_decode_nal_sps(h);
break;
case NAL_PPS:
ff_hevc_decode_nal_pps(h);
break;
case NAL_SEI_PREFIX:
case NAL_SEI_SUFFIX:
ff_hevc_decode_nal_sei(h);
break;
case NAL_TRAIL_N:
case NAL_TRAIL_R:
case NAL_TSA_N:
case NAL_TSA_R:
case NAL_STSA_N:
case NAL_STSA_R:
case NAL_RADL_N:
case NAL_RADL_R:
case NAL_RASL_N:
case NAL_RASL_R:
case NAL_BLA_W_LP:
case NAL_BLA_W_RADL:
case NAL_BLA_N_LP:
case NAL_IDR_W_RADL:
case NAL_IDR_N_LP:
case NAL_CRA_NUT:
sh->first_slice_in_pic_flag = get_bits1(gb);
s->picture_structure = h->picture_struct;
s->field_order = h->picture_struct;
if (IS_IRAP(h)) {
s->key_frame = 1;
sh->no_output_of_prior_pics_flag = get_bits1(gb);
}
sh->pps_id = get_ue_golomb(gb);
if (sh->pps_id >= MAX_PPS_COUNT || !h->pps_list[sh->pps_id]) {
av_log(h->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id);
return AVERROR_INVALIDDATA;
}
h->pps = (HEVCPPS*)h->pps_list[sh->pps_id]->data;
if (h->pps->sps_id >= MAX_SPS_COUNT || !h->sps_list[h->pps->sps_id]) {
av_log(h->avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", h->pps->sps_id);
return AVERROR_INVALIDDATA;
}
if (h->sps != (HEVCSPS*)h->sps_list[h->pps->sps_id]->data) {
h->sps = (HEVCSPS*)h->sps_list[h->pps->sps_id]->data;
h->vps = (HEVCVPS*)h->vps_list[h->sps->vps_id]->data;
}
if (!sh->first_slice_in_pic_flag) {
int slice_address_length;
if (h->pps->dependent_slice_segments_enabled_flag)
sh->dependent_slice_segment_flag = get_bits1(gb);
else
sh->dependent_slice_segment_flag = 0;
slice_address_length = av_ceil_log2_c(h->sps->ctb_width *
h->sps->ctb_height);
sh->slice_segment_addr = get_bits(gb, slice_address_length);
if (sh->slice_segment_addr >= h->sps->ctb_width * h->sps->ctb_height) {
av_log(h->avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n",
sh->slice_segment_addr);
return AVERROR_INVALIDDATA;
}
} else
sh->dependent_slice_segment_flag = 0;
if (sh->dependent_slice_segment_flag)
break;
for (i = 0; i < h->pps->num_extra_slice_header_bits; i++)
skip_bits(gb, 1); // slice_reserved_undetermined_flag[]
sh->slice_type = get_ue_golomb(gb);
if (!(sh->slice_type == I_SLICE || sh->slice_type == P_SLICE ||
sh->slice_type == B_SLICE)) {
av_log(h->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n",
sh->slice_type);
return AVERROR_INVALIDDATA;
}
s->pict_type = sh->slice_type == B_SLICE ? AV_PICTURE_TYPE_B :
sh->slice_type == P_SLICE ? AV_PICTURE_TYPE_P :
AV_PICTURE_TYPE_I;
if (h->pps->output_flag_present_flag)
sh->pic_output_flag = get_bits1(gb);
if (h->sps->separate_colour_plane_flag)
sh->colour_plane_id = get_bits(gb, 2);
if (!IS_IDR(h)) {
sh->pic_order_cnt_lsb = get_bits(gb, h->sps->log2_max_poc_lsb);
s->output_picture_number = h->poc = ff_hevc_compute_poc(h, sh->pic_order_cnt_lsb);
} else
s->output_picture_number = h->poc = 0;
if (h->temporal_id == 0 &&
h->nal_unit_type != NAL_TRAIL_N &&
h->nal_unit_type != NAL_TSA_N &&
h->nal_unit_type != NAL_STSA_N &&
h->nal_unit_type != NAL_RADL_N &&
h->nal_unit_type != NAL_RASL_N &&
h->nal_unit_type != NAL_RADL_R &&
h->nal_unit_type != NAL_RASL_R)
h->pocTid0 = h->poc;
return 0; /* no need to evaluate the rest */
}
buf += consumed;
}
/* didn't find a picture! */
av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n");
return -1;
}
static int hevc_parse(AVCodecParserContext *s,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
int next;
ParseContext *pc = &((HEVCParseContext *)s->priv_data)->pc;
if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
next = buf_size;
} else {
next = hevc_find_frame_end(s, buf, buf_size);
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
}
}
parse_nal_units(s, avctx, buf, buf_size);
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
}
// Split after the parameter sets at the beginning of the stream if they exist.
static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
{
int i;
uint32_t state = -1;
int has_ps = 0;
for (i = 0; i < buf_size; i++) {
state = (state << 8) | buf[i];
if (((state >> 8) & 0xFFFFFF) == START_CODE) {
int nut = (state >> 1) & 0x3F;
if (nut >= NAL_VPS && nut <= NAL_PPS)
has_ps = 1;
else if (has_ps)
return i - 3;
else // no parameter set at the beginning of the stream
return 0;
}
}
return 0;
}
static int hevc_init(AVCodecParserContext *s)
{
HEVCContext *h = &((HEVCParseContext *)s->priv_data)->h;
h->HEVClc = av_mallocz(sizeof(HEVCLocalContext));
h->skipped_bytes_pos_size = INT_MAX;
return 0;
}
static void hevc_close(AVCodecParserContext *s)
{
int i;
HEVCContext *h = &((HEVCParseContext *)s->priv_data)->h;
ParseContext *pc = &((HEVCParseContext *)s->priv_data)->pc;
av_freep(&h->skipped_bytes_pos);
av_freep(&h->HEVClc);
av_freep(&pc->buffer);
for (i = 0; i < FF_ARRAY_ELEMS(h->vps_list); i++)
av_buffer_unref(&h->vps_list[i]);
for (i = 0; i < FF_ARRAY_ELEMS(h->sps_list); i++)
av_buffer_unref(&h->sps_list[i]);
for (i = 0; i < FF_ARRAY_ELEMS(h->pps_list); i++)
av_buffer_unref(&h->pps_list[i]);
av_buffer_unref(&h->current_sps);
h->sps = NULL;
for (i = 0; i < h->nals_allocated; i++)
av_freep(&h->nals[i].rbsp_buffer);
av_freep(&h->nals);
h->nals_allocated = 0;
}
AVCodecParser ff_hevc_parser = {
.codec_ids = { AV_CODEC_ID_HEVC },
.priv_data_size = sizeof(HEVCParseContext),
.parser_init = hevc_init,
.parser_parse = hevc_parse,
.parser_close = hevc_close,
.split = hevc_split,
};

View file

@ -49,27 +49,7 @@ static const uint8_t default_scaling_list_inter[] = {
24, 25, 28, 33, 41, 54, 71, 91
};
#ifndef USE_MSPS
static const AVRational vui_sar[] = {
{ 0, 1 },
{ 1, 1 },
{ 12, 11 },
{ 10, 11 },
{ 16, 11 },
{ 40, 33 },
{ 24, 11 },
{ 20, 11 },
{ 32, 11 },
{ 80, 33 },
{ 18, 11 },
{ 15, 11 },
{ 64, 33 },
{ 160, 99 },
{ 4, 3 },
{ 3, 2 },
{ 2, 1 },
};
#ifdef USE_PRED
int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps,
const HEVCSPS *sps, int is_slice_header)
{
@ -198,6 +178,28 @@ int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps,
}
return 0;
}
#endif
#ifndef USE_MSPS
static const AVRational vui_sar[] = {
{ 0, 1 },
{ 1, 1 },
{ 12, 11 },
{ 10, 11 },
{ 16, 11 },
{ 40, 33 },
{ 24, 11 },
{ 20, 11 },
{ 32, 11 },
{ 80, 33 },
{ 18, 11 },
{ 15, 11 },
{ 64, 33 },
{ 160, 99 },
{ 4, 3 },
{ 3, 2 },
{ 2, 1 },
};
static int decode_profile_tier_level(HEVCContext *s, PTLCommon *ptl)
{
@ -978,7 +980,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s)
#ifdef USE_MSPS
sps->log2_max_poc_lsb = 8; /* not used */
sps->log2_max_poc_lsb = 8; /* not used for intra */
for (i = 0; i < sps->max_sub_layers; i++) {
sps->temporal_layer[i].max_dec_pic_buffering = 1;
sps->temporal_layer[i].num_reorder_pics = 0;
@ -1045,13 +1047,14 @@ int ff_hevc_decode_nal_sps(HEVCContext *s)
goto err;
}
#ifdef USE_MSPS
sps->max_transform_hierarchy_depth_inter = 0; /* not used for intra */
sps->max_transform_hierarchy_depth_intra = get_ue_golomb_long(gb);
sps->max_transform_hierarchy_depth_inter =
sps->max_transform_hierarchy_depth_intra; /* not used for intra */
sps->amp_enabled_flag = 1; /* not used for intra */
#else
sps->max_transform_hierarchy_depth_inter = get_ue_golomb_long(gb);
#endif
sps->max_transform_hierarchy_depth_intra = get_ue_golomb_long(gb);
#ifndef USE_MSPS
sps->scaling_list_enable_flag = get_bits1(gb);
if (sps->scaling_list_enable_flag) {
#ifdef USE_FULL
@ -1092,7 +1095,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s)
#ifdef USE_MSPS
sps->nb_st_rps = 0; /* not used for intra */
sps->long_term_ref_pics_present_flag = 0; /* not used for intra */
sps->sps_temporal_mvp_enabled_flag = 0; /* not used for intra */
sps->sps_temporal_mvp_enabled_flag = 1; /* not used for intra */
sps->sps_strong_intra_smoothing_enable_flag = get_bits1(gb);
sps->vui.sar = (AVRational){0, 1};
#else

View file

@ -177,6 +177,12 @@ static int decode_nal_sei_message(HEVCContext *s)
active_parameter_sets(s);
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type);
} else
#endif
#ifdef USE_FRAME_DURATION_SEI
if (payload_type == 257) {
/* frame duration in multiples of the frame rate period */
s->frame_duration = get_bits(gb, 16);
} else
#endif
{
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type);

View file

@ -238,45 +238,31 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth)
PEL_FUNC(put_hevc_qpel_bi_w, 1, 1, put_hevc_qpel_bi_w_hv, depth)
#ifdef USE_PRED
#define HEVC_DSP(depth) \
hevcdsp->put_pcm = FUNC(put_pcm, depth); \
hevcdsp->transform_add[0] = FUNC(transform_add4x4, depth); \
hevcdsp->transform_add[1] = FUNC(transform_add8x8, depth); \
hevcdsp->transform_add[2] = FUNC(transform_add16x16, depth); \
hevcdsp->transform_add[3] = FUNC(transform_add32x32, depth); \
hevcdsp->transform_skip = FUNC(transform_skip, depth); \
hevcdsp->transform_rdpcm = FUNC(transform_rdpcm, depth); \
hevcdsp->idct_4x4_luma = FUNC(transform_4x4_luma, depth); \
hevcdsp->idct[0] = FUNC(idct_4x4, depth); \
hevcdsp->idct[1] = FUNC(idct_8x8, depth); \
hevcdsp->idct[2] = FUNC(idct_16x16, depth); \
hevcdsp->idct[3] = FUNC(idct_32x32, depth); \
\
hevcdsp->idct_dc[0] = FUNC(idct_4x4_dc, depth); \
hevcdsp->idct_dc[1] = FUNC(idct_8x8_dc, depth); \
hevcdsp->idct_dc[2] = FUNC(idct_16x16_dc, depth); \
hevcdsp->idct_dc[3] = FUNC(idct_32x32_dc, depth); \
\
hevcdsp->sao_band_filter = FUNC(sao_band_filter_0, depth); \
hevcdsp->sao_edge_filter[0] = FUNC(sao_edge_filter_0, depth); \
hevcdsp->sao_edge_filter[1] = FUNC(sao_edge_filter_1, depth); \
\
#ifdef USE_BIPRED
#define HEVC_DSP_PRED(depth) \
QPEL_FUNCS(depth); \
QPEL_UNI_FUNCS(depth); \
QPEL_BI_FUNCS(depth); \
EPEL_FUNCS(depth); \
EPEL_UNI_FUNCS(depth); \
EPEL_BI_FUNCS(depth); \
\
hevcdsp->hevc_h_loop_filter_luma = FUNC(hevc_h_loop_filter_luma, depth); \
hevcdsp->hevc_v_loop_filter_luma = FUNC(hevc_v_loop_filter_luma, depth); \
hevcdsp->hevc_h_loop_filter_chroma = FUNC(hevc_h_loop_filter_chroma, depth); \
hevcdsp->hevc_v_loop_filter_chroma = FUNC(hevc_v_loop_filter_chroma, depth); \
hevcdsp->hevc_h_loop_filter_luma_c = FUNC(hevc_h_loop_filter_luma, depth); \
hevcdsp->hevc_v_loop_filter_luma_c = FUNC(hevc_v_loop_filter_luma, depth); \
hevcdsp->hevc_h_loop_filter_chroma_c = FUNC(hevc_h_loop_filter_chroma, depth); \
hevcdsp->hevc_v_loop_filter_chroma_c = FUNC(hevc_v_loop_filter_chroma, depth)
EPEL_BI_FUNCS(depth);
#else
#define HEVC_DSP_PRED(depth) \
QPEL_UNI_FUNCS(depth); \
EPEL_UNI_FUNCS(depth);
#endif
#else
#define HEVC_DSP_PRED(depth)
#endif
#define HEVC_DSP(depth) \
hevcdsp->put_pcm = FUNC(put_pcm, depth); \
hevcdsp->transform_add[0] = FUNC(transform_add4x4, depth); \
@ -295,7 +281,7 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth)
hevcdsp->idct_dc[1] = FUNC(idct_8x8_dc, depth); \
hevcdsp->idct_dc[2] = FUNC(idct_16x16_dc, depth); \
hevcdsp->idct_dc[3] = FUNC(idct_32x32_dc, depth); \
\
HEVC_DSP_PRED(depth) \
hevcdsp->sao_band_filter = FUNC(sao_band_filter_0, depth); \
hevcdsp->sao_edge_filter[0] = FUNC(sao_edge_filter_0, depth); \
hevcdsp->sao_edge_filter[1] = FUNC(sao_edge_filter_1, depth); \
@ -308,7 +294,6 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth)
hevcdsp->hevc_v_loop_filter_luma_c = FUNC(hevc_v_loop_filter_luma, depth); \
hevcdsp->hevc_h_loop_filter_chroma_c = FUNC(hevc_h_loop_filter_chroma, depth); \
hevcdsp->hevc_v_loop_filter_chroma_c = FUNC(hevc_v_loop_filter_chroma, depth)
#endif
#ifdef USE_PRED
int i = 0;

View file

@ -78,33 +78,33 @@ typedef struct HEVCDSPContext {
uint8_t *horiz_edge, uint8_t *diag_edge BIT_DEPTH_PARAM);
void (*put_hevc_qpel[10][2][2])(int16_t *dst, uint8_t *src, ptrdiff_t srcstride,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_qpel_uni[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_qpel_uni_w[10][2][2])(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width);
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_qpel_bi[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_qpel_bi_w[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width);
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_epel[10][2][2])(int16_t *dst, uint8_t *src, ptrdiff_t srcstride,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_epel_uni[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_epel_uni_w[10][2][2])(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width);
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_epel_bi[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width);
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*put_hevc_epel_bi_w[10][2][2])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int ox0, int wx1,
int ox1, intptr_t mx, intptr_t my, int width);
int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM);
void (*hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride,
int beta, int32_t *tc,

View file

@ -544,9 +544,10 @@ static void FUNC(sao_edge_filter_1)(uint8_t *_dst, uint8_t *_src,
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
#ifdef USE_BIPRED
static void FUNC(put_hevc_pel_pixels)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -559,9 +560,10 @@ static void FUNC(put_hevc_pel_pixels)(int16_t *dst,
dst += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_pel_uni_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int y;
pixel *src = (pixel *)_src;
@ -576,9 +578,10 @@ static void FUNC(put_hevc_pel_uni_pixels)(uint8_t *_dst, ptrdiff_t _dststride, u
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -587,11 +590,7 @@ static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, ui
ptrdiff_t dststride = _dststride / sizeof(pixel);
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -601,9 +600,10 @@ static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, ui
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -611,11 +611,7 @@ static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride,
pixel *dst = (pixel *)_dst;
ptrdiff_t dststride = _dststride / sizeof(pixel);
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
ox = ox * (1 << (BIT_DEPTH - 8));
for (y = 0; y < height; y++) {
@ -626,10 +622,11 @@ static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -651,6 +648,7 @@ static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride,
src2 += MAX_PB_SIZE;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////
//
@ -665,9 +663,10 @@ static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride,
filter[6] * src[x + 3 * stride] + \
filter[7] * src[x + 4 * stride])
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_h)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -683,7 +682,7 @@ static void FUNC(put_hevc_qpel_h)(int16_t *dst,
static void FUNC(put_hevc_qpel_v)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -701,7 +700,7 @@ static void FUNC(put_hevc_qpel_hv)(int16_t *dst,
uint8_t *_src,
ptrdiff_t _srcstride,
int height, intptr_t mx,
intptr_t my, int width)
intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
const int8_t *filter;
@ -728,10 +727,11 @@ static void FUNC(put_hevc_qpel_hv)(int16_t *dst,
dst += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -740,12 +740,7 @@ static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride,
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_qpel_filters[mx - 1];
int shift = 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -755,9 +750,10 @@ static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -768,11 +764,7 @@ static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
const int8_t *filter = ff_hevc_qpel_filters[mx - 1];
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -782,10 +774,11 @@ static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -794,12 +787,8 @@ static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride,
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_qpel_filters[my - 1];
int shift = 14 - BIT_DEPTH;
int offset = (1 << shift) >> 1;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -810,9 +799,10 @@ static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride,
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -823,11 +813,7 @@ static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
const int8_t *filter = ff_hevc_qpel_filters[my - 1];
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -837,10 +823,11 @@ static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
const int8_t *filter;
@ -851,12 +838,7 @@ static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride,
int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= QPEL_EXTRA_BEFORE * srcstride;
filter = ff_hevc_qpel_filters[mx - 1];
@ -878,9 +860,10 @@ static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
const int8_t *filter;
@ -891,11 +874,7 @@ static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8
int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= QPEL_EXTRA_BEFORE * srcstride;
filter = ff_hevc_qpel_filters[mx - 1];
@ -917,11 +896,12 @@ static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox,
intptr_t mx, intptr_t my, int width)
intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -930,11 +910,7 @@ static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride,
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_qpel_filters[mx - 1];
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
ox = ox * (1 << (BIT_DEPTH - 8));
for (y = 0; y < height; y++) {
@ -945,10 +921,11 @@ static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -972,11 +949,12 @@ static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox,
intptr_t mx, intptr_t my, int width)
intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -985,11 +963,7 @@ static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride,
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_qpel_filters[my - 1];
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
ox = ox * (1 << (BIT_DEPTH - 8));
for (y = 0; y < height; y++) {
@ -1000,10 +974,11 @@ static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel*)_src;
@ -1027,11 +1002,12 @@ static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride,
uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox,
intptr_t mx, intptr_t my, int width)
intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
const int8_t *filter;
@ -1042,11 +1018,7 @@ static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride,
int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= QPEL_EXTRA_BEFORE * srcstride;
filter = ff_hevc_qpel_filters[mx - 1];
@ -1069,10 +1041,11 @@ static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride,
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
const int8_t *filter;
@ -1108,6 +1081,7 @@ static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uin
src2 += MAX_PB_SIZE;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////
//
@ -1118,9 +1092,10 @@ static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uin
filter[2] * src[x + stride] + \
filter[3] * src[x + 2 * stride])
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_h)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1136,7 +1111,7 @@ static void FUNC(put_hevc_epel_h)(int16_t *dst,
static void FUNC(put_hevc_epel_v)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1153,7 +1128,7 @@ static void FUNC(put_hevc_epel_v)(int16_t *dst,
static void FUNC(put_hevc_epel_hv)(int16_t *dst,
uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1181,9 +1156,10 @@ static void FUNC(put_hevc_epel_hv)(int16_t *dst,
dst += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1192,11 +1168,7 @@ static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_epel_filters[mx - 1];
int shift = 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -1206,9 +1178,10 @@ static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1217,11 +1190,7 @@ static void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_epel_filters[mx - 1];
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
@ -1232,9 +1201,10 @@ static void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1243,11 +1213,7 @@ static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_epel_filters[my - 1];
int shift = 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -1257,9 +1223,10 @@ static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1268,11 +1235,7 @@ static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
pixel *dst = (pixel *)_dst;
ptrdiff_t dststride = _dststride / sizeof(pixel);
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
@ -1282,9 +1245,10 @@ static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1295,11 +1259,7 @@ static void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint
int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= EPEL_EXTRA_BEFORE * srcstride;
@ -1321,9 +1281,10 @@ static void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width)
int height, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1334,11 +1295,7 @@ static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8
int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = 14 + 1 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= EPEL_EXTRA_BEFORE * srcstride;
@ -1360,9 +1317,10 @@ static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1371,11 +1329,7 @@ static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uin
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_epel_filters[mx - 1];
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
ox = ox * (1 << (BIT_DEPTH - 8));
for (y = 0; y < height; y++) {
@ -1387,10 +1341,11 @@ static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uin
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1412,9 +1367,10 @@ static void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1423,11 +1379,7 @@ static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uin
ptrdiff_t dststride = _dststride / sizeof(pixel);
const int8_t *filter = ff_hevc_epel_filters[my - 1];
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
ox = ox * (1 << (BIT_DEPTH - 8));
for (y = 0; y < height; y++) {
@ -1439,10 +1391,11 @@ static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uin
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1464,9 +1417,10 @@ static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint
src2 += MAX_PB_SIZE;
}
}
#endif
static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1477,11 +1431,7 @@ static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, ui
int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int shift = denom + 14 - BIT_DEPTH;
#if BIT_DEPTH < 14
int offset = 1 << (shift - 1);
#else
int offset = 0;
#endif
int offset = (1 << shift) >> 1;
src -= EPEL_EXTRA_BEFORE * srcstride;
@ -1504,10 +1454,11 @@ static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, ui
}
}
#ifdef USE_BIPRED
static void FUNC(put_hevc_epel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
int16_t *src2,
int height, int denom, int wx0, int wx1,
int ox0, int ox1, intptr_t mx, intptr_t my, int width)
int ox0, int ox1, intptr_t mx, intptr_t my, int width BIT_DEPTH_PARAM)
{
int x, y;
pixel *src = (pixel *)_src;
@ -1545,6 +1496,8 @@ static void FUNC(put_hevc_epel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uin
}// line zero
#endif
#endif /* USE_PRED */
#define P3 pix[-4 * xstride]
#define P2 pix[-3 * xstride]

76
libavcodec/videodsp.c Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2012 Ronald S. Bultje
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "videodsp.h"
#ifdef USE_PRED
#if !defined(USE_VAR_BIT_DEPTH)
#define BIT_DEPTH 8
#include "videodsp_template.c"
#undef BIT_DEPTH
#endif
#if defined(USE_VAR_BIT_DEPTH) || defined(USE_FULL)
#define BIT_DEPTH 16
#include "videodsp_template.c"
#undef BIT_DEPTH
#endif
#ifdef USE_FULL
static void just_return(uint8_t *buf, ptrdiff_t stride, int h)
{
}
#endif
av_cold void ff_videodsp_init(VideoDSPContext *ctx, int bpc)
{
#ifdef USE_FULL
ctx->prefetch = just_return;
#endif
#ifdef USE_FULL
if (bpc <= 8) {
ctx->emulated_edge_mc = ff_emulated_edge_mc_8;
} else {
ctx->emulated_edge_mc = ff_emulated_edge_mc_16;
}
#else
#if defined(USE_VAR_BIT_DEPTH)
ctx->emulated_edge_mc = ff_emulated_edge_mc_var;
#else
ctx->emulated_edge_mc = ff_emulated_edge_mc_8;
#endif
#endif /* !USE_FULL */
if (ARCH_AARCH64)
ff_videodsp_init_aarch64(ctx, bpc);
if (ARCH_ARM)
ff_videodsp_init_arm(ctx, bpc);
if (ARCH_PPC)
ff_videodsp_init_ppc(ctx, bpc);
if (ARCH_X86)
ff_videodsp_init_x86(ctx, bpc);
}
#endif

View file

@ -0,0 +1,100 @@
/*
* Copyright (c) 2002-2012 Michael Niedermayer
* Copyright (C) 2012 Ronald S. Bultje
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "bit_depth_template.c"
void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src,
ptrdiff_t buf_linesize,
ptrdiff_t src_linesize,
int block_w, int block_h,
int src_x, int src_y, int w, int h)
{
int x, y;
int start_y, start_x, end_y, end_x;
if (!w || !h)
return;
if (src_y >= h) {
src -= src_y * src_linesize;
src += (h - 1) * src_linesize;
src_y = h - 1;
} else if (src_y <= -block_h) {
src -= src_y * src_linesize;
src += (1 - block_h) * src_linesize;
src_y = 1 - block_h;
}
if (src_x >= w) {
src += (w - 1 - src_x) * sizeof(pixel);
src_x = w - 1;
} else if (src_x <= -block_w) {
src += (1 - block_w - src_x) * sizeof(pixel);
src_x = 1 - block_w;
}
start_y = FFMAX(0, -src_y);
start_x = FFMAX(0, -src_x);
end_y = FFMIN(block_h, h-src_y);
end_x = FFMIN(block_w, w-src_x);
av_assert2(start_y < end_y && block_h);
av_assert2(start_x < end_x && block_w);
w = end_x - start_x;
src += start_y * src_linesize + start_x * sizeof(pixel);
buf += start_x * sizeof(pixel);
// top
for (y = 0; y < start_y; y++) {
memcpy(buf, src, w * sizeof(pixel));
buf += buf_linesize;
}
// copy existing part
for (; y < end_y; y++) {
memcpy(buf, src, w * sizeof(pixel));
src += src_linesize;
buf += buf_linesize;
}
// bottom
src -= src_linesize;
for (; y < block_h; y++) {
memcpy(buf, src, w * sizeof(pixel));
buf += buf_linesize;
}
buf -= block_h * buf_linesize + start_x * sizeof(pixel);
while (block_h--) {
pixel *bufp = (pixel *) buf;
// left
for(x = 0; x < start_x; x++) {
bufp[x] = bufp[start_x];
}
// right
for (x = end_x; x < block_w; x++) {
bufp[x] = bufp[end_x - 1];
}
buf += buf_linesize;
}
}

View file

@ -112,7 +112,7 @@ static const AVPixFmtDescriptorEntry pix_desc[] = {
}
},
{
AV_PIX_FMT_YUV422P16LE,
AV_PIX_FMT_YUV422P,
{
//.name = "yuv422p",
.nb_components = 3,

680
libbpg.c
View file

@ -30,8 +30,13 @@
#include <libavcodec/avcodec.h>
#include <libavutil/common.h>
/* The following global defines are used:
- USE_VAR_BIT_DEPTH : support of bit depth > 8 bits
- USE_PRED : support of animations
*/
#ifndef EMSCRIPTEN
#define USE_RGB48
#define USE_RGB48 /* support all pixel formats */
//#define DEBUG
#endif
@ -72,6 +77,8 @@ typedef void ColorConvertFunc(ColorConvertState *s,
int n, int incr);
struct BPGDecoderContext {
AVCodecContext *dec_ctx;
AVCodecContext *alpha_dec_ctx;
AVFrame *frame;
AVFrame *alpha_frame;
int w, h;
@ -82,14 +89,27 @@ struct BPGDecoderContext {
uint8_t has_w_plane;
uint8_t limited_range;
uint8_t premultiplied_alpha;
uint8_t has_animation;
BPGColorSpaceEnum color_space;
int keep_extension_data; /* true if the extension data must be
kept during parsing */
uint8_t keep_extension_data; /* true if the extension data must be
kept during parsing */
uint8_t decode_animation; /* true if animation decoding is enabled */
BPGExtensionData *first_md;
/* animation */
uint16_t loop_count;
uint16_t frame_delay_num;
uint16_t frame_delay_den;
uint8_t *input_buf;
int input_buf_pos;
int input_buf_len;
/* the following is used for format conversion */
uint8_t output_inited;
BPGDecoderOutputFormat out_fmt;
uint8_t is_rgba;
uint8_t is_rgb48;
uint8_t is_16bpp;
uint8_t is_cmyk;
int y; /* current line */
int w2, h2;
const uint8_t *y_buf, *cb_buf, *cr_buf, *a_buf;
@ -171,35 +191,6 @@ static int get_ue(uint32_t *pv, const uint8_t *buf, int len)
return ret;
}
static int decode_write_data(AVCodecContext *avctx,
AVFrame *frame, int *frame_count,
const uint8_t *buf, int buf_len)
{
AVPacket avpkt;
int len, got_frame;
av_init_packet(&avpkt);
avpkt.data = (uint8_t *)buf;
avpkt.size = buf_len;
len = avcodec_decode_video2(avctx, frame, &got_frame, &avpkt);
if (len < 0) {
#ifdef DEBUG
fprintf(stderr, "Error while decoding frame %d\n", *frame_count);
#endif
return len;
}
if (got_frame) {
#ifdef DEBUG
printf("got frame %d\n", *frame_count);
#endif
(*frame_count)++;
}
return 0;
}
extern AVCodec ff_hevc_decoder;
static int build_msps(uint8_t **pbuf, int *pbuf_len,
const uint8_t *input_data, int input_data_len1,
int width, int height, int chroma_format_idc,
@ -275,41 +266,6 @@ static int build_msps(uint8_t **pbuf, int *pbuf_len,
return input_data_len1 - input_data_len;
}
static AVFrame *hevc_decode_frame(const uint8_t *buf, int buf_len)
{
AVCodec *codec;
AVCodecContext *c;
AVFrame *frame;
int frame_count, ret;
codec = &ff_hevc_decoder;
c = avcodec_alloc_context3(codec);
if (!c)
goto fail;
frame = av_frame_alloc();
if (!frame)
goto fail;
/* for testing: use the MD5 or CRC in SEI to check the decoded bit
stream. */
c->err_recognition |= AV_EF_CRCCHECK;
/* open it */
if (avcodec_open2(c, codec, NULL) < 0)
goto fail;
frame_count = 0;
ret = decode_write_data(c, frame, &frame_count, buf, buf_len);
avcodec_close(c);
if (ret < 0 || frame_count != 1)
goto fail;
av_free(c);
return frame;
fail:
av_free(c);
av_frame_free(&frame);
return NULL;
}
/* return the position of the end of the NAL or -1 if error */
static int find_nal_end(const uint8_t *buf, int buf_len, int has_startcode)
{
@ -386,53 +342,117 @@ static int dyn_buf_push(DynBuf *s, const uint8_t *data, int len)
return 0;
}
static int hevc_decode(AVFrame **pcframe, AVFrame **paframe,
const uint8_t *buf, int buf_len,
int width, int height, int chroma_format_idc,
int bit_depth, int has_alpha)
extern AVCodec ff_hevc_decoder;
static int hevc_decode_init1(DynBuf *pbuf, AVFrame **pframe,
AVCodecContext **pc,
const uint8_t *buf, int buf_len,
int width, int height, int chroma_format_idc,
int bit_depth)
{
int nal_len, start, first_nal, nal_buf_len, ret, nuh_layer_id;
AVFrame *cframe = NULL, *aframe = NULL;
AVCodec *codec;
AVCodecContext *c;
AVFrame *frame;
uint8_t *nal_buf;
DynBuf abuf_s, *abuf = &abuf_s;
DynBuf cbuf_s, *cbuf = &cbuf_s;
DynBuf *pbuf;
dyn_buf_init(abuf);
dyn_buf_init(cbuf);
if (has_alpha) {
ret = build_msps(&nal_buf, &nal_len, buf, buf_len,
width, height, 0, bit_depth);
if (ret < 0)
goto fail;
buf += ret;
buf_len -= ret;
if (dyn_buf_push(abuf, nal_buf, nal_len) < 0)
goto fail;
free(nal_buf);
}
int nal_len, ret, ret1;
ret = build_msps(&nal_buf, &nal_len, buf, buf_len,
width, height, chroma_format_idc, bit_depth);
if (ret < 0)
goto fail;
buf += ret;
buf_len -= ret;
if (dyn_buf_push(cbuf, nal_buf, nal_len) < 0)
goto fail;
free(nal_buf);
return -1;
ret1 = dyn_buf_push(pbuf, nal_buf, nal_len);
av_free(nal_buf);
if (ret1 < 0)
return -1;
codec = &ff_hevc_decoder;
first_nal = 1;
c = avcodec_alloc_context3(codec);
if (!c)
return -1;
frame = av_frame_alloc();
if (!frame)
return -1;
/* for testing: use the MD5 or CRC in SEI to check the decoded bit
stream. */
c->err_recognition |= AV_EF_CRCCHECK;
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
av_frame_free(&frame);
return -1;
}
*pc = c;
*pframe = frame;
return ret;
}
static int hevc_write_frame(AVCodecContext *avctx,
AVFrame *frame,
uint8_t *buf, int buf_len)
{
AVPacket avpkt;
int len, got_frame;
av_init_packet(&avpkt);
avpkt.data = (uint8_t *)buf;
avpkt.size = buf_len;
/* avoid using uninitialized data */
memset(buf + buf_len, 0, FF_INPUT_BUFFER_PADDING_SIZE);
len = avcodec_decode_video2(avctx, frame, &got_frame, &avpkt);
if (len < 0 || !got_frame)
return -1;
else
return 0;
}
static int hevc_decode_frame_internal(BPGDecoderContext *s,
DynBuf *abuf, DynBuf *cbuf,
const uint8_t *buf, int buf_len1,
int first_nal)
{
int nal_len, start, nal_buf_len, ret, nuh_layer_id, buf_len, has_alpha;
int nut, frame_start_found[2];
DynBuf *pbuf;
uint8_t *nal_buf;
has_alpha = (s->alpha_dec_ctx != NULL);
buf_len = buf_len1;
frame_start_found[0] = 0;
frame_start_found[1] = 0;
while (buf_len > 0) {
nal_len = find_nal_end(buf, buf_len, !first_nal);
if (nal_len < 0)
if (buf_len < (first_nal ? 3 : 0) + 2)
goto fail;
if (first_nal)
start = 0;
else
start = 3 + (buf[2] == 0);
if (buf_len < start + 3)
goto fail;
nuh_layer_id = ((buf[start] & 1) << 5) | (buf[start + 1] >> 3);
nut = (buf[start] >> 1) & 0x3f;
#if 0
printf("nal: type=%d layer_id=%d fs=%d %d\n",
nut, nuh_layer_id, frame_start_found[0], frame_start_found[1]);
#endif
/* Note: we assume the alpha and color data are correctly
interleaved */
if ((nut >= 32 && nut <= 35) || nut == 39 || nut >= 41) {
if (frame_start_found[0] && frame_start_found[has_alpha])
break;
} else if ((nut <= 9 || (nut >= 16 && nut <= 21)) &&
start + 2 < buf_len && (buf[start + 2] & 0x80)) {
/* first slice segment */
if (frame_start_found[0] && frame_start_found[has_alpha])
break;
if (has_alpha && nuh_layer_id == 1)
frame_start_found[1] = 1;
else
frame_start_found[0] = 1;
}
nal_len = find_nal_end(buf, buf_len, !first_nal);
if (nal_len < 0)
goto fail;
nal_buf_len = nal_len - start + 3;
if (has_alpha && nuh_layer_id == 1)
pbuf = abuf;
@ -453,28 +473,100 @@ static int hevc_decode(AVFrame **pcframe, AVFrame **paframe,
first_nal = 0;
}
if (has_alpha) {
aframe = hevc_decode_frame(abuf->buf, abuf->len);
if (!aframe)
if (s->alpha_dec_ctx) {
if (dyn_buf_resize(abuf, abuf->len + FF_INPUT_BUFFER_PADDING_SIZE) < 0)
goto fail;
ret = hevc_write_frame(s->alpha_dec_ctx, s->alpha_frame, abuf->buf, abuf->len);
if (ret < 0)
goto fail;
}
cframe = hevc_decode_frame(cbuf->buf, cbuf->len);
if (!cframe)
if (dyn_buf_resize(cbuf, cbuf->len + FF_INPUT_BUFFER_PADDING_SIZE) < 0)
goto fail;
ret = 0;
ret = hevc_write_frame(s->dec_ctx, s->frame, cbuf->buf, cbuf->len);
if (ret < 0)
goto fail;
ret = buf_len1 - buf_len;
done:
av_free(abuf->buf);
av_free(cbuf->buf);
*pcframe = cframe;
*paframe = aframe;
return ret;
fail:
av_frame_free(&cframe);
av_frame_free(&aframe);
ret = -1;
goto done;
}
/* decode the first frame */
static int hevc_decode_start(BPGDecoderContext *s,
const uint8_t *buf, int buf_len1,
int width, int height, int chroma_format_idc,
int bit_depth, int has_alpha)
{
int ret, buf_len;
DynBuf abuf_s, *abuf = &abuf_s;
DynBuf cbuf_s, *cbuf = &cbuf_s;
dyn_buf_init(abuf);
dyn_buf_init(cbuf);
buf_len = buf_len1;
if (has_alpha) {
ret = hevc_decode_init1(abuf, &s->alpha_frame, &s->alpha_dec_ctx,
buf, buf_len, width, height, 0, bit_depth);
if (ret < 0)
goto fail;
buf += ret;
buf_len -= ret;
}
ret = hevc_decode_init1(cbuf, &s->frame, &s->dec_ctx,
buf, buf_len, width, height, chroma_format_idc,
bit_depth);
if (ret < 0)
goto fail;
buf += ret;
buf_len -= ret;
ret = hevc_decode_frame_internal(s, abuf, cbuf, buf, buf_len, 1);
av_free(abuf->buf);
av_free(cbuf->buf);
if (ret < 0)
goto fail;
buf_len -= ret;
return buf_len1 - buf_len;
fail:
return -1;
}
#ifdef USE_PRED
static int hevc_decode_frame(BPGDecoderContext *s,
const uint8_t *buf, int buf_len)
{
int ret;
DynBuf abuf_s, *abuf = &abuf_s;
DynBuf cbuf_s, *cbuf = &cbuf_s;
dyn_buf_init(abuf);
dyn_buf_init(cbuf);
ret = hevc_decode_frame_internal(s, abuf, cbuf, buf, buf_len, 0);
av_free(abuf->buf);
av_free(cbuf->buf);
return ret;
}
#endif
static void hevc_decode_end(BPGDecoderContext *s)
{
if (s->alpha_dec_ctx) {
avcodec_close(s->alpha_dec_ctx);
av_free(s->alpha_dec_ctx);
s->alpha_dec_ctx = NULL;
}
if (s->dec_ctx) {
avcodec_close(s->dec_ctx);
av_free(s->dec_ctx);
s->dec_ctx = NULL;
}
}
uint8_t *bpg_decoder_get_data(BPGDecoderContext *img, int *pline_size, int plane)
{
int c_count;
@ -507,6 +599,8 @@ int bpg_decoder_get_info(BPGDecoderContext *img, BPGImageInfo *p)
p->limited_range = img->limited_range;
p->color_space = img->color_space;
p->bit_depth = img->bit_depth;
p->has_animation = img->has_animation;
p->loop_count = img->loop_count;
return 0;
}
@ -720,7 +814,7 @@ static void interp2_vh(PIXEL *dst, PIXEL **src, int n, int y_pos,
{
const PIXEL *src0, *src1, *src2, *src3, *src4, *src5, *src6;
int i, n2, shift, rnd;
PIXEL v;
int16_t v;
src0 = src[(y_pos - 3) & 7];
src1 = src[(y_pos - 2) & 7];
@ -1175,6 +1269,24 @@ static void alpha_divide16(uint16_t *dst, int n)
}
}
static void gray_one_minus8(uint8_t *dst, int n, int incr)
{
int x;
for(x = 0; x < n; x++) {
dst[0] = 255 - dst[0];
dst += incr;
}
}
static void gray_one_minus16(uint16_t *dst, int n, int incr)
{
int x;
for(x = 0; x < n; x++) {
dst[0] = 65535 - dst[0];
dst += incr;
}
}
static ColorConvertFunc *cs_to_rgb48[BPG_CS_COUNT] = {
ycc_to_rgb48,
rgb_to_rgb48,
@ -1244,11 +1356,10 @@ static void convert_init(ColorConvertState *s,
static int bpg_decoder_output_init(BPGDecoderContext *s,
BPGDecoderOutputFormat out_fmt)
{
int i, y1, c_idx;
PIXEL *cb_ptr, *cr_ptr;
int i;
#ifdef USE_RGB48
if ((unsigned)out_fmt > BPG_OUTPUT_FORMAT_RGBA64)
if ((unsigned)out_fmt > BPG_OUTPUT_FORMAT_CMYK64)
return -1;
#else
if ((unsigned)out_fmt > BPG_OUTPUT_FORMAT_RGBA32)
@ -1256,22 +1367,12 @@ static int bpg_decoder_output_init(BPGDecoderContext *s,
#endif
s->is_rgba = (out_fmt == BPG_OUTPUT_FORMAT_RGBA32 ||
out_fmt == BPG_OUTPUT_FORMAT_RGBA64);
s->is_rgb48 = (out_fmt == BPG_OUTPUT_FORMAT_RGB48 ||
out_fmt == BPG_OUTPUT_FORMAT_RGBA64);
s->y_buf = bpg_decoder_get_data(s, &s->y_linesize, 0);
if (s->format != BPG_FORMAT_GRAY) {
s->cb_buf = bpg_decoder_get_data(s, &s->cb_linesize, 1);
s->cr_buf = bpg_decoder_get_data(s, &s->cr_linesize, 2);
c_idx = 3;
} else {
c_idx = 1;
}
if (s->has_alpha)
s->a_buf = bpg_decoder_get_data(s, &s->a_linesize, c_idx);
else
s->a_buf = NULL;
s->is_16bpp = (out_fmt == BPG_OUTPUT_FORMAT_RGB48 ||
out_fmt == BPG_OUTPUT_FORMAT_RGBA64 ||
out_fmt == BPG_OUTPUT_FORMAT_CMYK64);
s->is_cmyk = (out_fmt == BPG_OUTPUT_FORMAT_CMYK32 ||
out_fmt == BPG_OUTPUT_FORMAT_CMYK64);
if (s->format == BPG_FORMAT_420 || s->format == BPG_FORMAT_422) {
s->w2 = (s->w + 1) / 2;
s->h2 = (s->h + 1) / 2;
@ -1285,29 +1386,14 @@ static int bpg_decoder_output_init(BPGDecoderContext *s,
s->cb_buf3[i] = av_malloc(s->w2 * sizeof(PIXEL));
s->cr_buf3[i] = av_malloc(s->w2 * sizeof(PIXEL));
}
/* init the vertical interpolation buffer */
for(i = 0; i < ITAPS; i++) {
y1 = i;
if (y1 > ITAPS2)
y1 -= ITAPS;
if (y1 < 0)
y1 = 0;
else if (y1 >= s->h2)
y1 = s->h2 - 1;
cb_ptr = (PIXEL *)(s->cb_buf + y1 * s->cb_linesize);
cr_ptr = (PIXEL *)(s->cr_buf + y1 * s->cr_linesize);
memcpy(s->cb_buf3[i], cb_ptr, s->w2 * sizeof(PIXEL));
memcpy(s->cr_buf3[i], cr_ptr, s->w2 * sizeof(PIXEL));
}
}
}
convert_init(&s->cvt, s->bit_depth, s->is_rgb48 ? 16 : 8,
convert_init(&s->cvt, s->bit_depth, s->is_16bpp ? 16 : 8,
s->color_space, s->limited_range);
if (s->format == BPG_FORMAT_GRAY) {
#ifdef USE_RGB48
if (s->is_rgb48) {
if (s->is_16bpp) {
s->cvt_func = gray_to_rgb48;
} else
#endif
@ -1316,7 +1402,7 @@ static int bpg_decoder_output_init(BPGDecoderContext *s,
}
} else {
#ifdef USE_RGB48
if (s->is_rgb48) {
if (s->is_16bpp) {
s->cvt_func = cs_to_rgb48[s->color_space];
} else
#endif
@ -1340,26 +1426,105 @@ static void bpg_decoder_output_end(BPGDecoderContext *s)
av_free(s->c_buf4);
}
int bpg_decoder_start(BPGDecoderContext *s, BPGDecoderOutputFormat out_fmt)
{
int ret, c_idx;
if (!s->frame)
return -1;
if (!s->output_inited) {
/* first frame is already decoded */
ret = bpg_decoder_output_init(s, out_fmt);
if (ret)
return ret;
s->output_inited = 1;
s->out_fmt = out_fmt;
} else {
#ifdef USE_PRED
if (s->has_animation && s->decode_animation) {
if (out_fmt != s->out_fmt)
return -1;
if (s->input_buf_pos >= s->input_buf_len) {
return -1;
} else {
ret = hevc_decode_frame(s, s->input_buf + s->input_buf_pos,
s->input_buf_len - s->input_buf_pos);
if (ret < 0)
return -1;
s->input_buf_pos += ret;
}
} else
#endif
{
return -1;
}
}
s->y_buf = bpg_decoder_get_data(s, &s->y_linesize, 0);
if (s->format != BPG_FORMAT_GRAY) {
s->cb_buf = bpg_decoder_get_data(s, &s->cb_linesize, 1);
s->cr_buf = bpg_decoder_get_data(s, &s->cr_linesize, 2);
c_idx = 3;
} else {
c_idx = 1;
}
if (s->has_alpha)
s->a_buf = bpg_decoder_get_data(s, &s->a_linesize, c_idx);
else
s->a_buf = NULL;
s->y = 0;
return 0;
}
void bpg_decoder_get_frame_duration(BPGDecoderContext *s, int *pnum, int *pden)
{
#ifdef USE_PRED
if (s->frame && s->has_animation) {
*pnum = s->frame_delay_num * (s->frame->pts);
*pden = s->frame_delay_den;
} else
#endif
{
*pnum = 0;
*pden = 1;
}
}
int bpg_decoder_get_line(BPGDecoderContext *s, void *rgb_line1)
{
uint8_t *rgb_line = rgb_line1;
int w, h, y, pos, y2, y1, incr, y_frac;
int w, y, pos, y2, y1, incr, y_frac;
PIXEL *y_ptr, *cb_ptr, *cr_ptr, *a_ptr;
w = s->w;
h = s->h;
y = s->y;
if ((unsigned)y >= h)
if ((unsigned)y >= s->h)
return -1;
w = s->w;
y_ptr = (PIXEL *)(s->y_buf + y * s->y_linesize);
incr = 3 + s->is_rgba;
incr = 3 + (s->is_rgba || s->is_cmyk);
switch(s->format) {
case BPG_FORMAT_GRAY:
s->cvt_func(&s->cvt, rgb_line, y_ptr, NULL, NULL, w, incr);
break;
case BPG_FORMAT_420:
if (y == 0) {
int i;
/* init the vertical interpolation buffer */
for(i = 0; i < ITAPS; i++) {
y1 = i;
if (y1 > ITAPS2)
y1 -= ITAPS;
if (y1 < 0)
y1 = 0;
else if (y1 >= s->h2)
y1 = s->h2 - 1;
cb_ptr = (PIXEL *)(s->cb_buf + y1 * s->cb_linesize);
cr_ptr = (PIXEL *)(s->cr_buf + y1 * s->cr_linesize);
memcpy(s->cb_buf3[i], cb_ptr, s->w2 * sizeof(PIXEL));
memcpy(s->cr_buf3[i], cr_ptr, s->w2 * sizeof(PIXEL));
}
}
y2 = y >> 1;
pos = y2 % ITAPS;
y_frac = y & 1;
@ -1399,10 +1564,27 @@ int bpg_decoder_get_line(BPGDecoderContext *s, void *rgb_line1)
}
/* alpha output or CMYK handling */
#ifdef USE_RGB48
if (s->is_cmyk) {
int i;
/* convert RGBW to CMYK */
if (s->is_16bpp) {
if (!s->has_w_plane)
put_dummy_gray16((uint16_t *)rgb_line + 3, w, 4);
for(i = 0; i < 4; i++)
gray_one_minus16((uint16_t *)rgb_line + i, w, 4);
} else {
if (!s->has_w_plane)
put_dummy_gray8(rgb_line + 3, w, 4);
for(i = 0; i < 4; i++)
gray_one_minus8(rgb_line + i, w, 4);
}
} else
#endif
if (s->has_w_plane) {
a_ptr = (PIXEL *)(s->a_buf + y * s->a_linesize);
#ifdef USE_RGB48
if (s->is_rgb48) {
if (s->is_16bpp) {
alpha_combine16(&s->cvt, (uint16_t *)rgb_line, a_ptr, w, incr);
if (s->is_rgba)
put_dummy_gray16((uint16_t *)rgb_line + 3, w, 4);
@ -1413,32 +1595,30 @@ int bpg_decoder_get_line(BPGDecoderContext *s, void *rgb_line1)
if (s->is_rgba)
put_dummy_gray8(rgb_line + 3, w, 4);
}
} else {
if (s->is_rgba) {
} else if (s->is_rgba) {
#ifdef USE_RGB48
if (s->is_rgb48) {
if (s->has_alpha) {
a_ptr = (PIXEL *)(s->a_buf + y * s->a_linesize);
gray_to_gray16(&s->cvt,
(uint16_t *)rgb_line + 3, a_ptr, w, 4);
if (s->premultiplied_alpha)
alpha_divide16((uint16_t *)rgb_line, w);
} else {
put_dummy_gray16((uint16_t *)rgb_line + 3, w, 4);
}
} else
#endif
{
if (s->has_alpha) {
a_ptr = (PIXEL *)(s->a_buf + y * s->a_linesize);
gray_to_gray8(&s->cvt, rgb_line + 3, a_ptr, w, 4);
if (s->premultiplied_alpha)
alpha_divide8((uint8_t *)rgb_line, w);
} else {
put_dummy_gray8(rgb_line + 3, w, 4);
}
if (s->is_16bpp) {
if (s->has_alpha) {
a_ptr = (PIXEL *)(s->a_buf + y * s->a_linesize);
gray_to_gray16(&s->cvt,
(uint16_t *)rgb_line + 3, a_ptr, w, 4);
if (s->premultiplied_alpha)
alpha_divide16((uint16_t *)rgb_line, w);
} else {
put_dummy_gray16((uint16_t *)rgb_line + 3, w, 4);
}
} else
#endif
{
if (s->has_alpha) {
a_ptr = (PIXEL *)(s->a_buf + y * s->a_linesize);
gray_to_gray8(&s->cvt, rgb_line + 3, a_ptr, w, 4);
if (s->premultiplied_alpha)
alpha_divide8((uint8_t *)rgb_line, w);
} else {
put_dummy_gray8(rgb_line + 3, w, 4);
}
}
}
}
/* go to next line */
@ -1446,19 +1626,6 @@ int bpg_decoder_get_line(BPGDecoderContext *s, void *rgb_line1)
return 0;
}
int bpg_decoder_start(BPGDecoderContext *s, BPGDecoderOutputFormat out_fmt)
{
int ret;
if (!s->frame || s->y >= 0)
return -1;
ret = bpg_decoder_output_init(s, out_fmt);
if (ret)
return ret;
s->y = 0;
return 0;
}
BPGDecoderContext *bpg_decoder_open(void)
{
BPGDecoderContext *s;
@ -1477,6 +1644,10 @@ typedef struct {
uint8_t has_w_plane;
uint8_t premultiplied_alpha;
uint8_t limited_range;
uint8_t has_animation;
uint16_t loop_count;
uint16_t frame_delay_num;
uint16_t frame_delay_den;
BPGColorSpaceEnum color_space;
uint32_t hevc_data_len;
BPGExtensionData *first_md;
@ -1511,7 +1682,10 @@ static int bpg_decode_header(BPGHeaderData *h,
has_extension = (flags2 >> 3) & 1;
alpha2_flag = (flags2 >> 2) & 1;
h->limited_range = (flags2 >> 1) & 1;
h->has_animation = flags2 & 1;
h->loop_count = 0;
h->frame_delay_num = 0;
h->frame_delay_den = 0;
h->has_alpha = 0;
h->has_w_plane = 0;
h->premultiplied_alpha = 0;
@ -1561,43 +1735,76 @@ static int bpg_decode_header(BPGHeaderData *h,
ext_end = idx + extension_data_len;
if (ext_end > buf_len)
return -1;
#ifndef EMSCRIPTEN
if (load_extensions) {
if (load_extensions || h->has_animation) {
BPGExtensionData *md, **plast_md;
uint32_t tag, buf_len;
plast_md = &h->first_md;
while (idx < ext_end) {
md = av_malloc(sizeof(BPGExtensionData));
*plast_md = md;
plast_md = &md->next;
ret = get_ue32(&md->tag, buf + idx, ext_end - idx);
ret = get_ue32(&tag, buf + idx, ext_end - idx);
if (ret < 0)
goto fail;
idx += ret;
ret = get_ue(&md->buf_len, buf + idx, ext_end - idx);
ret = get_ue(&buf_len, buf + idx, ext_end - idx);
if (ret < 0)
goto fail;
idx += ret;
if (idx + md->buf_len > ext_end) {
if (idx + buf_len > ext_end) {
fail:
bpg_decoder_free_extension_data(h->first_md);
return -1;
}
md->buf = av_malloc(md->buf_len);
memcpy(md->buf, buf + idx, md->buf_len);
idx += md->buf_len;
if (h->has_animation && tag == BPG_EXTENSION_TAG_ANIM_CONTROL) {
int idx1;
uint32_t loop_count, frame_delay_num, frame_delay_den;
idx1 = idx;
ret = get_ue(&loop_count, buf + idx1, ext_end - idx1);
if (ret < 0)
goto fail;
idx1 += ret;
ret = get_ue(&frame_delay_num, buf + idx1, ext_end - idx1);
if (ret < 0)
goto fail;
idx1 += ret;
ret = get_ue(&frame_delay_den, buf + idx1, ext_end - idx1);
if (ret < 0)
goto fail;
idx1 += ret;
if (frame_delay_num == 0 || frame_delay_den == 0 ||
(uint16_t)frame_delay_num != frame_delay_num ||
(uint16_t)frame_delay_den != frame_delay_den ||
(uint16_t)loop_count != loop_count)
goto fail;
h->loop_count = loop_count;
h->frame_delay_num = frame_delay_num;
h->frame_delay_den = frame_delay_den;
}
if (load_extensions) {
md = av_malloc(sizeof(BPGExtensionData));
md->tag = tag;
md->buf_len = buf_len;
*plast_md = md;
plast_md = &md->next;
md->buf = av_malloc(md->buf_len);
memcpy(md->buf, buf + idx, md->buf_len);
}
idx += buf_len;
}
} else
#endif
{
/* skip extension data */
idx += extension_data_len;
}
}
/* must have animation control extension for animations */
if (h->has_animation && h->frame_delay_num == 0)
goto fail;
if (h->hevc_data_len == 0)
h->hevc_data_len = buf_len - idx;
@ -1606,7 +1813,7 @@ static int bpg_decode_header(BPGHeaderData *h,
int bpg_decoder_decode(BPGDecoderContext *img, const uint8_t *buf, int buf_len)
{
int idx, has_alpha, bit_depth, color_space;
int idx, has_alpha, bit_depth, color_space, ret;
uint32_t width, height;
BPGHeaderData h_s, *h = &h_s;
@ -1638,27 +1845,49 @@ int bpg_decoder_decode(BPGDecoderContext *img, const uint8_t *buf, int buf_len)
img->limited_range = h->limited_range;
img->color_space = color_space;
img->bit_depth = bit_depth;
img->has_animation = h->has_animation;
img->loop_count = h->loop_count;
img->frame_delay_num = h->frame_delay_num;
img->frame_delay_den = h->frame_delay_den;
img->first_md = h->first_md;
if (idx + h->hevc_data_len > buf_len)
goto fail;
if (hevc_decode(&img->frame, &img->alpha_frame,
buf + idx, h->hevc_data_len,
width, height, img->format, bit_depth, has_alpha) < 0)
goto fail;
idx += h->hevc_data_len;
/* decode the first frame */
ret = hevc_decode_start(img, buf + idx, buf_len - idx,
width, height, img->format, bit_depth, has_alpha);
if (ret < 0)
goto fail;
idx += ret;
#ifdef USE_PRED
/* XXX: add an option to avoid decoding animations ? */
img->decode_animation = 1;
if (img->has_animation && img->decode_animation) {
int len;
/* keep trailing bitstream to decode the next frames */
len = buf_len - idx;
img->input_buf = av_malloc(len);
if (!img->input_buf)
goto fail;
memcpy(img->input_buf, buf + idx, len);
img->input_buf_len = len;
img->input_buf_pos = 0;
} else
#endif
{
hevc_decode_end(img);
}
if (img->frame->width < img->w || img->frame->height < img->h)
goto fail;
img->y = -1;
return 0;
fail:
if (img->frame)
av_frame_free(&img->frame);
if (img->alpha_frame)
av_frame_free(&img->alpha_frame);
av_frame_free(&img->frame);
av_frame_free(&img->alpha_frame);
bpg_decoder_free_extension_data(img->first_md);
img->first_md = NULL;
return -1;
@ -1667,10 +1896,10 @@ int bpg_decoder_decode(BPGDecoderContext *img, const uint8_t *buf, int buf_len)
void bpg_decoder_close(BPGDecoderContext *s)
{
bpg_decoder_output_end(s);
if (s->frame)
av_frame_free(&s->frame);
if (s->alpha_frame)
av_frame_free(&s->alpha_frame);
av_free(s->input_buf);
hevc_decode_end(s);
av_frame_free(&s->frame);
av_frame_free(&s->alpha_frame);
bpg_decoder_free_extension_data(s->first_md);
av_free(s);
}
@ -1688,7 +1917,6 @@ void bpg_decoder_free_extension_data(BPGExtensionData *first_md)
#endif
}
#ifndef EMSCRIPTEN
void bpg_decoder_keep_extension_data(BPGDecoderContext *s, int enable)
{
@ -1720,6 +1948,8 @@ int bpg_decoder_get_info_from_buf(BPGImageInfo *p,
p->limited_range = h->limited_range;
p->color_space = h->color_space;
p->bit_depth = h->bit_depth;
p->has_animation = h->has_animation;
p->loop_count = h->loop_count;
if (pfirst_md)
*pfirst_md = h->first_md;
return 0;

View file

@ -46,15 +46,17 @@ typedef enum {
} BPGColorSpaceEnum;
typedef struct {
int width;
int height;
int format; /* see BPGImageFormatEnum */
int has_alpha; /* TRUE if an alpha plane is present */
int color_space; /* see BPGColorSpaceEnum */
int bit_depth;
int premultiplied_alpha; /* TRUE if the color is alpha premultiplied */
int has_w_plane; /* TRUE if a W plane is present (for CMYK encoding) */
int limited_range; /* TRUE if limited range for the color */
uint32_t width;
uint32_t height;
uint8_t format; /* see BPGImageFormatEnum */
uint8_t has_alpha; /* TRUE if an alpha plane is present */
uint8_t color_space; /* see BPGColorSpaceEnum */
uint8_t bit_depth;
uint8_t premultiplied_alpha; /* TRUE if the color is alpha premultiplied */
uint8_t has_w_plane; /* TRUE if a W plane is present (for CMYK encoding) */
uint8_t limited_range; /* TRUE if limited range for the color */
uint8_t has_animation; /* TRUE if the image contains animations */
uint16_t loop_count; /* animations: number of loop, 0 = infinity */
} BPGImageInfo;
typedef enum {
@ -62,6 +64,7 @@ typedef enum {
BPG_EXTENSION_TAG_ICCP = 2,
BPG_EXTENSION_TAG_XMP = 3,
BPG_EXTENSION_TAG_THUMBNAIL = 4,
BPG_EXTENSION_TAG_ANIM_CONTROL = 5,
} BPGExtensionTagEnum;
typedef struct BPGExtensionData {
@ -76,6 +79,8 @@ typedef enum {
BPG_OUTPUT_FORMAT_RGBA32, /* not premultiplied alpha */
BPG_OUTPUT_FORMAT_RGB48,
BPG_OUTPUT_FORMAT_RGBA64, /* not premultiplied alpha */
BPG_OUTPUT_FORMAT_CMYK32,
BPG_OUTPUT_FORMAT_CMYK64,
} BPGDecoderOutputFormat;
#define BPG_DECODER_INFO_BUF_SIZE 16
@ -100,6 +105,10 @@ int bpg_decoder_get_info(BPGDecoderContext *s, BPGImageInfo *p);
/* return 0 if 0K, < 0 if error */
int bpg_decoder_start(BPGDecoderContext *s, BPGDecoderOutputFormat out_fmt);
/* return the frame delay for animations as a fraction (*pnum) / (*pden)
in seconds. In case there is no animation, 0 / 1 is returned. */
void bpg_decoder_get_frame_duration(BPGDecoderContext *s, int *pnum, int *pden);
/* return 0 if 0K, < 0 if error */
int bpg_decoder_get_line(BPGDecoderContext *s, void *buf);
@ -115,6 +124,8 @@ uint8_t *bpg_decoder_get_data(BPGDecoderContext *s, int *pline_size, int plane);
first element of the list is returned in *pfirst_md. The list must
be freed with bpg_decoder_free_extension_data().
BPGImageInfo.loop_count is only set if extension data are parsed.
Return 0 if OK, < 0 if unrecognized data. */
int bpg_decoder_get_info_from_buf(BPGImageInfo *p,
BPGExtensionData **pfirst_md,

90
post.js
View file

@ -25,6 +25,8 @@ window['BPGDecoder'] = function(ctx) {
this.ctx = ctx;
this['imageData'] = null;
this['onload'] = null;
this['frames'] = null;
this['loop_count'] = 0;
}
window['BPGDecoder'].prototype = {
@ -41,6 +43,8 @@ bpg_decoder_get_info: Module['cwrap']('bpg_decoder_get_info', 'number', [ 'numbe
bpg_decoder_start: Module['cwrap']('bpg_decoder_start', 'number', [ 'number', 'number' ]),
bpg_decoder_get_frame_duration: Module['cwrap']('bpg_decoder_get_frame_duration', 'void', [ 'number', 'number', 'number' ]),
bpg_decoder_get_line: Module['cwrap']('bpg_decoder_get_line', 'number', [ 'number', 'number' ]),
bpg_decoder_close: Module['cwrap']('bpg_decoder_close', 'void', [ 'number' ] ),
@ -62,8 +66,8 @@ _onload: function(request, event)
{
var data = request.response;
var array = new Uint8Array(data);
var img, w, h, img_info_buf, cimg, p0, rgba_line, w4;
var heap8, heap32, dst, v, i, y, func;
var img, w, h, img_info_buf, cimg, p0, rgba_line, w4, frame_count;
var heap8, heap16, heap32, dst, v, i, y, func, duration, frames, loop_count;
// console.log("loaded " + data.byteLength + " bytes");
@ -74,39 +78,52 @@ _onload: function(request, event)
return;
}
img_info_buf = this.malloc(9 * 4);
img_info_buf = this.malloc(5 * 4);
this.bpg_decoder_get_info(img, img_info_buf);
/* extract the image info */
heap8 = Module['HEAPU8'];
heap16 = Module['HEAPU16'];
heap32 = Module['HEAPU32'];
w = heap32[img_info_buf >> 2];
h = heap32[(img_info_buf + 4) >> 2];
this.free(img_info_buf);
// console.log("image " + w + " " + h);
loop_count = heap16[(img_info_buf + 16) >> 1];
// console.log("image: w=" + w + " h=" + h + " loop_count=" + loop_count);
/* select RGBA32 output */
this.bpg_decoder_start(img, 1);
rgba_line = this.malloc(w * 4);
cimg = this.ctx.createImageData(w, h);
dst = cimg.data;
p0 = 0;
heap8 = Module['HEAPU8'];
w4 = w * 4;
for(y = 0; y < h; y++) {
this.bpg_decoder_get_line(img, rgba_line);
for(i = 0; i < w4; i = (i + 1) | 0) {
dst[p0] = heap8[(rgba_line + i) | 0] | 0;
p0 = (p0 + 1) | 0;
rgba_line = this.malloc(w4);
frame_count = 0;
frames = [];
for(;;) {
/* select RGBA32 output */
if (this.bpg_decoder_start(img, 1) < 0)
break;
this.bpg_decoder_get_frame_duration(img, img_info_buf,
img_info_buf + 4);
duration = (heap32[img_info_buf >> 2] * 1000) / heap32[(img_info_buf + 4) >> 2];
cimg = this.ctx.createImageData(w, h);
dst = cimg.data;
p0 = 0;
for(y = 0; y < h; y++) {
this.bpg_decoder_get_line(img, rgba_line);
for(i = 0; i < w4; i = (i + 1) | 0) {
dst[p0] = heap8[(rgba_line + i) | 0] | 0;
p0 = (p0 + 1) | 0;
}
}
frames[frame_count++] = { 'img': cimg, 'duration': duration };
}
this.free(rgba_line);
this.free(img_info_buf);
this.bpg_decoder_close(img);
this['imageData'] = cimg;
this['loop_count'] = loop_count;
this['frames'] = frames;
this['imageData'] = frames[0]['img'];
if (this['onload'])
this['onload']();
}
@ -155,13 +172,42 @@ window.onload = function() {
ctx = canvas.getContext("2d");
dec = new BPGDecoder(ctx);
dec.onload = (function(canvas, ctx) {
var imageData = this['imageData'];
var dec = this;
var frames = this['frames'];
var imageData = frames[0]['img'];
function next_frame() {
var frame_index = dec.frame_index;
/* compute next frame index */
if (++frame_index >= frames.length) {
if (dec['loop_count'] == 0 ||
dec.loop_counter < dec['loop_count']) {
frame_index = 0;
dec.loop_counter++;
} else {
frame_index = -1;
}
}
if (frame_index >= 0) {
dec.frame_index = frame_index;
ctx.putImageData(frames[frame_index]['img'], 0, 0);
setTimeout(next_frame, frames[frame_index]['duration']);
}
};
/* resize the canvas to the image size */
canvas.width = imageData.width;
canvas.height = imageData.height;
/* draw the image */
ctx.putImageData(imageData, 0, 0);
/* if it is an animation, add a timer to display the next frame */
if (frames.length > 1) {
dec.frame_index = 0;
dec.loop_counter = 0;
setTimeout(next_frame, frames[0]['duration']);
}
}).bind(dec, canvas, ctx);
dec.load(url);
}

View file

@ -31,27 +31,31 @@
#include "x265.h"
int x265_encode_picture(uint8_t **pbuf, Image *img,
const HEVCEncodeParams *params)
{
struct HEVCEncoderContext {
x265_encoder *enc;
x265_param *p;
x265_picture *pic, *pic_in;
x265_nal *p_nal;
int buf_len, idx, c_count, i, ret, pic_count;
uint32_t nal_count;
x265_picture *pic;
uint8_t *buf;
int buf_len, buf_size;
};
static HEVCEncoderContext *x265_open(const HEVCEncodeParams *params)
{
HEVCEncoderContext *s;
x265_param *p;
int preset_index;
const char *preset;
if (img->bit_depth != x265_max_bit_depth) {
s = malloc(sizeof(HEVCEncoderContext));
memset(s, 0, sizeof(*s));
if (params->bit_depth != x265_max_bit_depth) {
fprintf(stderr, "x265 is compiled to support only %d bit depth. Use the '-b %d' option to force the bit depth.\n",
x265_max_bit_depth, x265_max_bit_depth);
return -1;
return NULL;
}
if (img->format == BPG_FORMAT_GRAY) {
if (params->chroma_format == BPG_FORMAT_GRAY) {
fprintf(stderr, "x265 does not support monochrome (or alpha) data yet. Plase use the jctvc encoder.\n");
return -1;
return NULL;
}
p = x265_param_alloc();
@ -66,9 +70,9 @@ int x265_encode_picture(uint8_t **pbuf, Image *img,
p->bRepeatHeaders = 1;
p->decodedPictureHashSEI = params->sei_decoded_picture_hash;
p->sourceWidth = img->w;
p->sourceHeight = img->h;
switch(img->format) {
p->sourceWidth = params->width;
p->sourceHeight = params->height;
switch(params->chroma_format) {
case BPG_FORMAT_GRAY:
p->internalCsp = X265_CSP_I400;
break;
@ -84,8 +88,18 @@ int x265_encode_picture(uint8_t **pbuf, Image *img,
default:
abort();
}
p->keyframeMax = 1; /* only I frames */
p->internalBitDepth = img->bit_depth;
if (params->intra_only) {
p->keyframeMax = 1; /* only I frames */
p->totalFrames = 1;
} else {
p->keyframeMax = 250;
p->totalFrames = 0;
p->maxNumReferences = 1;
p->bframes = 0;
}
p->bEnableRectInter = 1;
p->bEnableAMP = 1; /* cannot use 0 due to header restriction */
p->internalBitDepth = params->bit_depth;
p->bEmitInfoSEI = 0;
if (params->verbose)
p->logLevel = X265_LOG_INFO;
@ -95,20 +109,51 @@ int x265_encode_picture(uint8_t **pbuf, Image *img,
/* dummy frame rate */
p->fpsNum = 25;
p->fpsDenom = 1;
p->totalFrames = 1;
p->rc.rateControlMode = X265_RC_CQP;
/* XXX: why do we need this offset to match the JCTVC quality ? */
if (img->bit_depth == 10)
if (params->bit_depth == 10)
p->rc.qp = params->qp + 7;
else
p->rc.qp = params->qp + 1;
p->bLossless = params->lossless;
enc = x265_encoder_open(p);
s->enc = x265_encoder_open(p);
pic = x265_picture_alloc();
x265_picture_init(p, pic);
s->pic = x265_picture_alloc();
x265_picture_init(p, s->pic);
s->pic->colorSpace = p->internalCsp;
x265_param_free(p);
return s;
}
static void add_nal(HEVCEncoderContext *s, const uint8_t *data, int data_len)
{
int new_size, size;
size = s->buf_len + data_len;
if (size > s->buf_size) {
new_size = (s->buf_size * 3) / 2;
if (new_size < size)
new_size = size;
s->buf = realloc(s->buf, new_size);
s->buf_size = new_size;
}
memcpy(s->buf + s->buf_len, data, data_len);
s->buf_len += data_len;
}
static int x265_encode(HEVCEncoderContext *s, Image *img)
{
int c_count, i, ret;
x265_picture *pic;
uint32_t nal_count;
x265_nal *p_nal;
pic = s->pic;
if (img->format == BPG_FORMAT_GRAY)
c_count = 1;
@ -119,48 +164,47 @@ int x265_encode_picture(uint8_t **pbuf, Image *img,
pic->stride[i] = img->linesize[i];
}
pic->bitDepth = img->bit_depth;
pic->colorSpace = p->internalCsp;
pic_count = 0;
for(;;) {
if (pic_count == 0)
pic_in = pic;
else
pic_in = NULL;
ret = x265_encoder_encode(enc, &p_nal, &nal_count, pic_in, NULL);
if (ret < 0)
goto fail;
if (ret == 1)
break;
pic_count++;
ret = x265_encoder_encode(s->enc, &p_nal, &nal_count, pic, NULL);
if (ret > 0) {
for(i = 0; i < nal_count; i++) {
add_nal(s, p_nal[i].payload, p_nal[i].sizeBytes);
}
}
buf_len = 0;
for(i = 0; i < nal_count; i++) {
buf_len += p_nal[i].sizeBytes;
}
// printf("nal_count=%d buf_len=%d\n", nal_count, buf_len);
buf = malloc(buf_len);
idx = 0;
for(i = 0; i < nal_count; i++) {
memcpy(buf + idx, p_nal[i].payload, p_nal[i].sizeBytes);
idx += p_nal[i].sizeBytes;
}
x265_encoder_close(enc);
x265_param_free(p);
x265_picture_free(pic);
*pbuf = buf;
return buf_len;
fail:
x265_encoder_close(enc);
x265_param_free(p);
x265_picture_free(pic);
*pbuf = NULL;
return -1;
return 0;
}
static int x265_close(HEVCEncoderContext *s, uint8_t **pbuf)
{
int buf_len, ret, i;
uint32_t nal_count;
x265_nal *p_nal;
/* get last compressed pictures */
for(;;) {
ret = x265_encoder_encode(s->enc, &p_nal, &nal_count, NULL, NULL);
if (ret <= 0)
break;
for(i = 0; i < nal_count; i++) {
add_nal(s, p_nal[i].payload, p_nal[i].sizeBytes);
}
}
if (s->buf_len < s->buf_size) {
s->buf = realloc(s->buf, s->buf_len);
}
*pbuf = s->buf;
buf_len = s->buf_len;
x265_encoder_close(s->enc);
x265_picture_free(s->pic);
free(s);
return buf_len;
}
HEVCEncoder x265_hevc_encoder = {
.open = x265_open,
.encode = x265_encode,
.close = x265_close,
};