Commit 0e7fc3ca authored by Michael Niedermayer's avatar Michael Niedermayer

Merge remote-tracking branch 'qatar/master'

* qatar/master: (22 commits)
  rv34: frame-level multi-threading
  mpegvideo: claim ownership of referenced pictures
  aacsbr: prevent out of bounds memcpy().
  ipmovie: fix pts for CODEC_ID_INTERPLAY_DPCM
  sierravmd: fix audio pts
  bethsoftvideo: Use bytestream2 functions to prevent buffer overreads.
  bmpenc: support for PIX_FMT_RGB444
  swscale: fix crash in fast_bilinear code when compiled with -mred-zone.
  swscale: specify register type.
  rv34: use get_bits_left()
  avconv: reinitialize the filtergraph on resolution change.
  vsrc_buffer: error on changing frame parameters.
  avconv: fix -copyinkf.
  fate: Update file checksums after the mov muxer change in a78dbada
  movenc: Don't store a nonzero creation time if nothing was set by the caller
  bmpdec: support for rgb444 with bitfields compression
  rgb2rgb: allow conversion for <15 bpp
  doc: fix stray reference to FFmpeg
  v4l2: use C99 struct initializer
  v4l2: poll the file descriptor
  ...

Conflicts:
	avconv.c
	libavcodec/aacsbr.c
	libavcodec/bethsoftvideo.c
	libavcodec/kmvc.c
	libavdevice/v4l2.c
	libavfilter/vsrc_buffer.c
	libswscale/swscale_unscaled.c
	libswscale/x86/input.asm
	tests/ref/acodec/alac
	tests/ref/acodec/pcm_s16be
	tests/ref/acodec/pcm_s24be
	tests/ref/acodec/pcm_s32be
	tests/ref/acodec/pcm_s8
	tests/ref/lavf/mov
	tests/ref/vsynth1/dnxhd_1080i
	tests/ref/vsynth1/mpeg4
	tests/ref/vsynth1/qtrle
	tests/ref/vsynth1/svq1
	tests/ref/vsynth2/dnxhd_1080i
	tests/ref/vsynth2/mpeg4
	tests/ref/vsynth2/qtrle
	tests/ref/vsynth2/svq1
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents a9bd29e1 9472d37d
...@@ -638,7 +638,6 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) ...@@ -638,7 +638,6 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0) if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
return ret; return ret;
av_freep(&ost->avfilter);
} else { } else {
if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0) if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0)
return ret; return ret;
...@@ -767,6 +766,10 @@ void exit_program(int ret) ...@@ -767,6 +766,10 @@ void exit_program(int ret)
bsfc = next; bsfc = next;
} }
output_streams[i].bitstream_filters = NULL; output_streams[i].bitstream_filters = NULL;
#if CONFIG_AVFILTER
av_freep(&output_streams[i].avfilter);
#endif
} }
for (i = 0; i < nb_input_files; i++) { for (i = 0; i < nb_input_files; i++) {
avformat_close_input(&input_files[i].ctx); avformat_close_input(&input_files[i].ctx);
...@@ -1302,6 +1305,7 @@ static void do_subtitle_out(AVFormatContext *s, ...@@ -1302,6 +1305,7 @@ static void do_subtitle_out(AVFormatContext *s,
static int bit_buffer_size = 1024 * 256; static int bit_buffer_size = 1024 * 256;
static uint8_t *bit_buffer = NULL; static uint8_t *bit_buffer = NULL;
#if !CONFIG_AVFILTER
static void do_video_resample(OutputStream *ost, static void do_video_resample(OutputStream *ost,
InputStream *ist, InputStream *ist,
AVFrame *in_picture, AVFrame *in_picture,
...@@ -1316,7 +1320,6 @@ static void do_video_resample(OutputStream *ost, ...@@ -1316,7 +1320,6 @@ static void do_video_resample(OutputStream *ost,
ost->resample_height != dec->height || ost->resample_height != dec->height ||
ost->resample_pix_fmt != dec->pix_fmt; ost->resample_pix_fmt != dec->pix_fmt;
#if !CONFIG_AVFILTER
if (resample_changed) { if (resample_changed) {
av_log(NULL, AV_LOG_INFO, av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
...@@ -1332,6 +1335,7 @@ static void do_video_resample(OutputStream *ost, ...@@ -1332,6 +1335,7 @@ static void do_video_resample(OutputStream *ost,
dec->height != enc->height || dec->height != enc->height ||
dec->pix_fmt != enc->pix_fmt; dec->pix_fmt != enc->pix_fmt;
if (ost->video_resample) { if (ost->video_resample) {
*out_picture = &ost->resample_frame; *out_picture = &ost->resample_frame;
if (!ost->img_resample_ctx || resample_changed) { if (!ost->img_resample_ctx || resample_changed) {
...@@ -1357,21 +1361,13 @@ static void do_video_resample(OutputStream *ost, ...@@ -1357,21 +1361,13 @@ static void do_video_resample(OutputStream *ost,
sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize, sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize,
0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize); 0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize);
} }
#else
if (resample_changed) {
avfilter_graph_free(&ost->graph);
if (configure_video_filters(ist, ost)) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
}
}
#endif
if (resample_changed) { if (resample_changed) {
ost->resample_width = dec->width; ost->resample_width = dec->width;
ost->resample_height = dec->height; ost->resample_height = dec->height;
ost->resample_pix_fmt = dec->pix_fmt; ost->resample_pix_fmt = dec->pix_fmt;
} }
} }
#endif
static void do_video_out(AVFormatContext *s, static void do_video_out(AVFormatContext *s,
...@@ -1426,7 +1422,11 @@ static void do_video_out(AVFormatContext *s, ...@@ -1426,7 +1422,11 @@ static void do_video_out(AVFormatContext *s,
if (nb_frames <= 0) if (nb_frames <= 0)
return; return;
#if !CONFIG_AVFILTER
do_video_resample(ost, ist, in_picture, &final_picture); do_video_resample(ost, ist, in_picture, &final_picture);
#else
final_picture = in_picture;
#endif
/* duplicates frame if needed */ /* duplicates frame if needed */
for (i = 0; i < nb_frames; i++) { for (i = 0; i < nb_frames; i++) {
...@@ -2012,12 +2012,33 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int ...@@ -2012,12 +2012,33 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
for (i = 0; i < nb_output_streams; i++) { for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i]; OutputStream *ost = &output_streams[i];
int frame_size; int frame_size, resample_changed;
if (!check_output_constraints(ist, ost) || !ost->encoding_needed) if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue; continue;
#if CONFIG_AVFILTER #if CONFIG_AVFILTER
resample_changed = ost->resample_width != decoded_frame->width ||
ost->resample_height != decoded_frame->height ||
ost->resample_pix_fmt != decoded_frame->format;
if (resample_changed) {
av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
ist->file_index, ist->st->index,
ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
avfilter_graph_free(&ost->graph);
if (configure_video_filters(ist, ost)) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
}
ost->resample_width = decoded_frame->width;
ost->resample_height = decoded_frame->height;
ost->resample_pix_fmt = decoded_frame->format;
}
if (!decoded_frame->sample_aspect_ratio.num) if (!decoded_frame->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
decoded_frame->pts = ist->pts; decoded_frame->pts = ist->pts;
...@@ -3736,13 +3757,13 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) ...@@ -3736,13 +3757,13 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
ost->top_field_first = -1; ost->top_field_first = -1;
MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
#if CONFIG_AVFILTER #if CONFIG_AVFILTER
MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
if (filters) if (filters)
ost->avfilter = av_strdup(filters); ost->avfilter = av_strdup(filters);
#endif #endif
} else {
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
} }
return ost; return ost;
......
...@@ -1092,7 +1092,7 @@ drawbox=10:20:200:60:red@@0.5" ...@@ -1092,7 +1092,7 @@ drawbox=10:20:200:60:red@@0.5"
Draw text string or text from specified file on top of video using the Draw text string or text from specified file on top of video using the
libfreetype library. libfreetype library.
To enable compilation of this filter you need to configure FFmpeg with To enable compilation of this filter you need to configure Libav with
@code{--enable-libfreetype}. @code{--enable-libfreetype}.
The filter also recognizes strftime() sequences in the provided text The filter also recognizes strftime() sequences in the provided text
......
...@@ -4042,13 +4042,13 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) ...@@ -4042,13 +4042,13 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
ost->top_field_first = -1; ost->top_field_first = -1;
MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
#if CONFIG_AVFILTER #if CONFIG_AVFILTER
MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
if (filters) if (filters)
ost->avfilter = av_strdup(filters); ost->avfilter = av_strdup(filters);
#endif #endif
} else {
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
} }
return ost; return ost;
......
...@@ -1185,14 +1185,15 @@ static void sbr_qmf_synthesis(DSPContext *dsp, FFTContext *mdct, ...@@ -1185,14 +1185,15 @@ static void sbr_qmf_synthesis(DSPContext *dsp, FFTContext *mdct,
{ {
int i, n; int i, n;
const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us; const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us;
const int step = 128 >> div;
float *v; float *v;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
if (*v_off < 128 >> div) { if (*v_off < step) {
int saved_samples = (1280 - 128) >> div; int saved_samples = (1280 - 128) >> div;
memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float)); memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float));
*v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - (128 >> div); *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step;
} else { } else {
*v_off -= 128 >> div; *v_off -= step;
} }
v = v0 + *v_off; v = v0 + *v_off;
if (div) { if (div) {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
typedef struct BethsoftvidContext { typedef struct BethsoftvidContext {
AVFrame frame; AVFrame frame;
GetByteContext g;
} BethsoftvidContext; } BethsoftvidContext;
static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx) static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx)
...@@ -47,19 +48,19 @@ static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx) ...@@ -47,19 +48,19 @@ static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx)
return 0; return 0;
} }
static int set_palette(AVFrame * frame, const uint8_t * palette_buffer, int buf_size) static int set_palette(BethsoftvidContext *ctx)
{ {
uint32_t * palette = (uint32_t *)frame->data[1]; uint32_t *palette = (uint32_t *)ctx->frame.data[1];
int a; int a;
if (buf_size < 256*3) if (bytestream2_get_bytes_left(&ctx->g) < 256*3)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
for(a = 0; a < 256; a++){ for(a = 0; a < 256; a++){
palette[a] = 0xFF << 24 | AV_RB24(&palette_buffer[a * 3]) * 4; palette[a] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->g) * 4;
palette[a] |= palette[a] >> 6 & 0x30303; palette[a] |= palette[a] >> 6 & 0x30303;
} }
frame->palette_has_changed = 1; ctx->frame.palette_has_changed = 1;
return 256*3; return 256*3;
} }
...@@ -67,8 +68,6 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, ...@@ -67,8 +68,6 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx,
void *data, int *data_size, void *data, int *data_size,
AVPacket *avpkt) AVPacket *avpkt)
{ {
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
BethsoftvidContext * vid = avctx->priv_data; BethsoftvidContext * vid = avctx->priv_data;
char block_type; char block_type;
uint8_t * dst; uint8_t * dst;
...@@ -82,29 +81,32 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, ...@@ -82,29 +81,32 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return -1; return -1;
} }
bytestream2_init(&vid->g, avpkt->data, avpkt->size);
dst = vid->frame.data[0]; dst = vid->frame.data[0];
frame_end = vid->frame.data[0] + vid->frame.linesize[0] * avctx->height; frame_end = vid->frame.data[0] + vid->frame.linesize[0] * avctx->height;
switch(block_type = *buf++){ switch(block_type = bytestream2_get_byte(&vid->g)){
case PALETTE_BLOCK: case PALETTE_BLOCK: {
return set_palette(&vid->frame, buf, buf_size); return set_palette(vid);
}
case VIDEO_YOFF_P_FRAME: case VIDEO_YOFF_P_FRAME:
yoffset = bytestream_get_le16(&buf); yoffset = bytestream2_get_le16(&vid->g);
if(yoffset >= avctx->height) if(yoffset >= avctx->height)
return -1; return -1;
dst += vid->frame.linesize[0] * yoffset; dst += vid->frame.linesize[0] * yoffset;
} }
// main code // main code
while((code = *buf++)){ while((code = bytestream2_get_byte(&vid->g))){
int length = code & 0x7f; int length = code & 0x7f;
// copy any bytes starting at the current position, and ending at the frame width // copy any bytes starting at the current position, and ending at the frame width
while(length > remaining){ while(length > remaining){
if(code < 0x80) if(code < 0x80)
bytestream_get_buffer(&buf, dst, remaining); bytestream2_get_buffer(&vid->g, dst, remaining);
else if(block_type == VIDEO_I_FRAME) else if(block_type == VIDEO_I_FRAME)
memset(dst, buf[0], remaining); memset(dst, bytestream2_peek_byte(&vid->g), remaining);
length -= remaining; // decrement the number of bytes to be copied length -= remaining; // decrement the number of bytes to be copied
dst += remaining + wrap_to_next_line; // skip over extra bytes at end of frame dst += remaining + wrap_to_next_line; // skip over extra bytes at end of frame
remaining = avctx->width; remaining = avctx->width;
...@@ -114,9 +116,9 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, ...@@ -114,9 +116,9 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx,
// copy any remaining bytes after / if line overflows // copy any remaining bytes after / if line overflows
if(code < 0x80) if(code < 0x80)
bytestream_get_buffer(&buf, dst, length); bytestream2_get_buffer(&vid->g, dst, length);
else if(block_type == VIDEO_I_FRAME) else if(block_type == VIDEO_I_FRAME)
memset(dst, *buf++, length); memset(dst, bytestream2_get_byte(&vid->g), length);
remaining -= length; remaining -= length;
dst += length; dst += length;
} }
...@@ -125,7 +127,7 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, ...@@ -125,7 +127,7 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx,
*data_size = sizeof(AVFrame); *data_size = sizeof(AVFrame);
*(AVFrame*)data = vid->frame; *(AVFrame*)data = vid->frame;
return buf_size; return avpkt->size;
} }
static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx) static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx)
......
This diff is collapsed.
...@@ -1135,25 +1135,26 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) ...@@ -1135,25 +1135,26 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
s->codec_id == CODEC_ID_SVQ3); s->codec_id == CODEC_ID_SVQ3);
/* mark & release old frames */ /* mark & release old frames */
if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) {
s->last_picture_ptr != s->next_picture_ptr && if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr &&
s->last_picture_ptr->f.data[0]) { s->last_picture_ptr != s->next_picture_ptr &&
if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) { s->last_picture_ptr->f.data[0]) {
if (s->last_picture_ptr->owner2 == s) if (s->last_picture_ptr->owner2 == s)
free_frame_buffer(s, s->last_picture_ptr); free_frame_buffer(s, s->last_picture_ptr);
}
/* release forgotten pictures */ /* release forgotten pictures */
/* if (mpeg124/h263) */ /* if (mpeg124/h263) */
if (!s->encoding) { if (!s->encoding) {
for (i = 0; i < s->picture_count; i++) { for (i = 0; i < s->picture_count; i++) {
if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && if (s->picture[i].owner2 == s && s->picture[i].f.data[0] &&
&s->picture[i] != s->next_picture_ptr && &s->picture[i] != s->last_picture_ptr &&
s->picture[i].f.reference) { &s->picture[i] != s->next_picture_ptr &&
if (!(avctx->active_thread_type & FF_THREAD_FRAME)) s->picture[i].f.reference) {
av_log(avctx, AV_LOG_ERROR, if (!(avctx->active_thread_type & FF_THREAD_FRAME))
"releasing zombie picture\n"); av_log(avctx, AV_LOG_ERROR,
free_frame_buffer(s, &s->picture[i]); "releasing zombie picture\n");
} free_frame_buffer(s, &s->picture[i]);
} }
} }
} }
...@@ -1274,6 +1275,14 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) ...@@ -1274,6 +1275,14 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
if (s->next_picture_ptr) if (s->next_picture_ptr)
ff_copy_picture(&s->next_picture, s->next_picture_ptr); ff_copy_picture(&s->next_picture, s->next_picture_ptr);
if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME) &&
(s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3)) {
if (s->next_picture_ptr)
s->next_picture_ptr->owner2 = s;
if (s->last_picture_ptr)
s->last_picture_ptr->owner2 = s;
}
assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
s->last_picture_ptr->f.data[0])); s->last_picture_ptr->f.data[0]));
......
...@@ -279,8 +279,10 @@ AVCodec ff_rv30_decoder = { ...@@ -279,8 +279,10 @@ AVCodec ff_rv30_decoder = {
.init = rv30_decode_init, .init = rv30_decode_init,
.close = ff_rv34_decode_end, .close = ff_rv34_decode_end,
.decode = ff_rv34_decode_frame, .decode = ff_rv34_decode_frame,
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_FRAME_THREADS,
.flush = ff_mpeg_flush, .flush = ff_mpeg_flush,
.long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"), .long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"),
.pix_fmts = ff_pixfmt_list_420, .pix_fmts = ff_pixfmt_list_420,
.init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context),
}; };
...@@ -24,12 +24,16 @@ ...@@ -24,12 +24,16 @@
* RV30/40 decoder common data * RV30/40 decoder common data
*/ */
#include "libavutil/internal.h"
#include "avcodec.h" #include "avcodec.h"
#include "dsputil.h" #include "dsputil.h"
#include "mpegvideo.h" #include "mpegvideo.h"
#include "golomb.h" #include "golomb.h"
#include "internal.h"
#include "mathops.h" #include "mathops.h"
#include "rectangle.h" #include "rectangle.h"
#include "thread.h"
#include "rv34vlc.h" #include "rv34vlc.h"
#include "rv34data.h" #include "rv34data.h"
...@@ -669,6 +673,14 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, ...@@ -669,6 +673,14 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type,
if(uvmx == 6 && uvmy == 6) if(uvmx == 6 && uvmy == 6)
uvmx = uvmy = 4; uvmx = uvmy = 4;
} }
if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
/* wait for the referenced mb row to be finished */
int mb_row = FFMIN(s->mb_height - 1, s->mb_y + ((yoff + my + 21) >> 4));
AVFrame *f = dir ? &s->next_picture_ptr->f : &s->last_picture_ptr->f;
ff_thread_await_progress(f, mb_row, 0);
}
dxy = ly*4 + lx; dxy = ly*4 + lx;
srcY = dir ? s->next_picture_ptr->f.data[0] : s->last_picture_ptr->f.data[0]; srcY = dir ? s->next_picture_ptr->f.data[0] : s->last_picture_ptr->f.data[0];
srcU = dir ? s->next_picture_ptr->f.data[1] : s->last_picture_ptr->f.data[1]; srcU = dir ? s->next_picture_ptr->f.data[1] : s->last_picture_ptr->f.data[1];
...@@ -824,6 +836,10 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type) ...@@ -824,6 +836,10 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type)
} }
case RV34_MB_B_DIRECT: case RV34_MB_B_DIRECT:
//surprisingly, it uses motion scheme from next reference frame //surprisingly, it uses motion scheme from next reference frame
/* wait for the current mb row to be finished */
if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
ff_thread_await_progress(&s->next_picture_ptr->f, s->mb_y - 1, 0);
next_bt = s->next_picture_ptr->f.mb_type[s->mb_x + s->mb_y * s->mb_stride]; next_bt = s->next_picture_ptr->f.mb_type[s->mb_x + s->mb_y * s->mb_stride];
if(IS_INTRA(next_bt) || IS_SKIP(next_bt)){ if(IS_INTRA(next_bt) || IS_SKIP(next_bt)){
ZERO8x2(s->current_picture_ptr->f.motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); ZERO8x2(s->current_picture_ptr->f.motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride);
...@@ -1186,7 +1202,7 @@ static int check_slice_end(RV34DecContext *r, MpegEncContext *s) ...@@ -1186,7 +1202,7 @@ static int check_slice_end(RV34DecContext *r, MpegEncContext *s)
return 1; return 1;
if(r->s.mb_skip_run > 1) if(r->s.mb_skip_run > 1)
return 0; return 0;
bits = r->bits - get_bits_count(&s->gb); bits = get_bits_left(&s->gb);
if(bits < 0 || (bits < 8 && !show_bits(&s->gb, bits))) if(bits < 0 || (bits < 8 && !show_bits(&s->gb, bits)))
return 1; return 1;
return 0; return 0;
...@@ -1255,6 +1271,7 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int ...@@ -1255,6 +1271,7 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
} }
} }
s->mb_x = s->mb_y = 0; s->mb_x = s->mb_y = 0;
ff_thread_finish_setup(s->avctx);
} else { } else {
int slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I; int slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I;
...@@ -1270,7 +1287,6 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int ...@@ -1270,7 +1287,6 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
r->si.end = end; r->si.end = end;
s->qscale = r->si.quant; s->qscale = r->si.quant;
r->bits = buf_size*8;
s->mb_num_left = r->si.end - r->si.start; s->mb_num_left = r->si.end - r->si.start;
r->s.mb_skip_run = 0; r->s.mb_skip_run = 0;
...@@ -1304,6 +1320,11 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int ...@@ -1304,6 +1320,11 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
if(r->loop_filter && s->mb_y >= 2) if(r->loop_filter && s->mb_y >= 2)
r->loop_filter(r, s->mb_y - 2); r->loop_filter(r, s->mb_y - 2);
if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
ff_thread_report_progress(&s->current_picture_ptr->f,
s->mb_y - 2, 0);
} }
if(s->mb_x == s->resync_mb_x) if(s->mb_x == s->resync_mb_x)
s->first_slice_line=0; s->first_slice_line=0;
...@@ -1369,6 +1390,71 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx) ...@@ -1369,6 +1390,71 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx)
return 0; return 0;
} }
int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx)
{
RV34DecContext *r = avctx->priv_data;
r->s.avctx = avctx;
if (avctx->internal->is_copy) {
r->cbp_chroma = av_malloc(r->s.mb_stride * r->s.mb_height *
sizeof(*r->cbp_chroma));
r->cbp_luma = av_malloc(r->s.mb_stride * r->s.mb_height *
sizeof(*r->cbp_luma));
r->deblock_coefs = av_malloc(r->s.mb_stride * r->s.mb_height *
sizeof(*r->deblock_coefs));
r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 *
sizeof(*r->intra_types_hist));
r->mb_type = av_malloc(r->s.mb_stride * r->s.mb_height *
sizeof(*r->mb_type));
if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs &&
r->intra_types_hist && r->mb_type)) {
av_freep(&r->cbp_chroma);
av_freep(&r->cbp_luma);
av_freep(&r->deblock_coefs);
av_freep(&r->intra_types_hist);
av_freep(&r->mb_type);
r->intra_types = NULL;
return AVERROR(ENOMEM);
}
r->intra_types = r->intra_types_hist + r->intra_types_stride * 4;
r->tmp_b_block_base = NULL;
memset(r->mb_type, 0, r->s.mb_stride * r->s.mb_height *
sizeof(*r->mb_type));
MPV_common_init(&r->s);
}
return 0;
}
int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
RV34DecContext *r = dst->priv_data, *r1 = src->priv_data;
MpegEncContext * const s = &r->s, * const s1 = &r1->s;
int err;
if (dst == src || !s1->context_initialized)
return 0;
if ((err = ff_mpeg_update_thread_context(dst, src)))
return err;
r->cur_pts = r1->cur_pts;
r->last_pts = r1->last_pts;
r->next_pts = r1->next_pts;
memset(&r->si, 0, sizeof(r->si));
/* necessary since it is it the condition checked for in decode_slice
* to call MPV_frame_start. cmp. comment at the end of decode_frame */
s->current_picture_ptr = NULL;
return 0;
}
static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n)
{ {
if(avctx->slice_count) return avctx->slice_offset[n]; if(avctx->slice_count) return avctx->slice_offset[n];
...@@ -1470,6 +1556,9 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, ...@@ -1470,6 +1556,9 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
if(last && s->current_picture_ptr){ if(last && s->current_picture_ptr){
if(r->loop_filter) if(r->loop_filter)
r->loop_filter(r, s->mb_height - 1); r->loop_filter(r, s->mb_height - 1);
if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
ff_thread_report_progress(&s->current_picture_ptr->f,
s->mb_height - 1, 0);
ff_er_frame_end(s); ff_er_frame_end(s);
MPV_frame_end(s); MPV_frame_end(s);
if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
......
...@@ -92,7 +92,6 @@ typedef struct RV34DecContext{ ...@@ -92,7 +92,6 @@ typedef struct RV34DecContext{
const uint8_t *luma_dc_quant_p;///< luma subblock DC quantizer for interframes const uint8_t *luma_dc_quant_p;///< luma subblock DC quantizer for interframes
RV34VLC *cur_vlcs; ///< VLC set used for current frame decoding RV34VLC *cur_vlcs; ///< VLC set used for current frame decoding
int bits; ///< slice size in bits
H264PredContext h; ///< functions for 4x4 and 16x16 intra block prediction H264PredContext h; ///< functions for 4x4 and 16x16 intra block prediction
SliceInfo si; ///< current slice information SliceInfo si; ///< current slice information
...@@ -134,5 +133,7 @@ int ff_rv34_get_start_offset(GetBitContext *gb, int blocks); ...@@ -134,5 +133,7 @@ int ff_rv34_get_start_offset(GetBitContext *gb, int blocks);
int ff_rv34_decode_init(AVCodecContext *avctx); int ff_rv34_decode_init(AVCodecContext *avctx);
int ff_rv34_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt); int ff_rv34_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt);
int ff_rv34_decode_end(AVCodecContext *avctx); int ff_rv34_decode_end(AVCodecContext *avctx);
int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx);
int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src);
#endif /* AVCODEC_RV34_H */ #endif /* AVCODEC_RV34_H */
...@@ -566,8 +566,10 @@ AVCodec ff_rv40_decoder = { ...@@ -566,8 +566,10 @@ AVCodec ff_rv40_decoder = {
.init = rv40_decode_init, .init = rv40_decode_init,
.close = ff_rv34_decode_end, .close = ff_rv34_decode_end,
.decode = ff_rv34_decode_frame, .decode = ff_rv34_decode_frame,
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_FRAME_THREADS,
.flush = ff_mpeg_flush, .flush = ff_mpeg_flush,
.long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"), .long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"),
.pix_fmts = ff_pixfmt_list_420, .pix_fmts = ff_pixfmt_list_420,
.init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context),
}; };
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/time.h> #include <sys/time.h>
#include <poll.h>
#if HAVE_SYS_VIDEOIO_H #if HAVE_SYS_VIDEOIO_H
#include <sys/videoio.h> #include <sys/videoio.h>
#else #else
...@@ -54,6 +55,7 @@ ...@@ -54,6 +55,7 @@
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/mathematics.h"
#if CONFIG_LIBV4L2 #if CONFIG_LIBV4L2
#include <libv4l2.h> #include <libv4l2.h>
...@@ -79,6 +81,7 @@ struct video_data { ...@@ -79,6 +81,7 @@ struct video_data {
int frame_format; /* V4L2_PIX_FMT_* */ int frame_format; /* V4L2_PIX_FMT_* */
int width, height; int width, height;
int frame_size; int frame_size;
int timeout;
int interlaced; int interlaced;
int top_field_first; int top_field_first;
...@@ -197,14 +200,11 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, ...@@ -197,14 +200,11 @@ static int device_init(AVFormatContext *ctx, int *width, int *height,
{ {
struct video_data *s = ctx->priv_data; struct video_data *s = ctx->priv_data;
int fd = s->fd; int fd = s->fd;
struct v4l2_format fmt; struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
struct v4l2_pix_format *pix = &fmt.fmt.pix; struct v4l2_pix_format *pix = &fmt.fmt.pix;
int res; int res;
memset(&fmt, 0, sizeof(struct v4l2_format));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pix->width = *width; pix->width = *width;
pix->height = *height; pix->height = *height;
pix->pixelformat = pix_fmt; pix->pixelformat = pix_fmt;
...@@ -362,13 +362,14 @@ static void list_formats(AVFormatContext *ctx, int fd, int type) ...@@ -362,13 +362,14 @@ static void list_formats(AVFormatContext *ctx, int fd, int type)
static int mmap_init(AVFormatContext *ctx) static int mmap_init(AVFormatContext *ctx)
{ {
struct video_data *s = ctx->priv_data;
struct v4l2_requestbuffers req = {0};
int i, res; int i, res;
struct video_data *s = ctx->priv_data;
struct v4l2_requestbuffers req = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.count = desired_video_buffers,
.memory = V4L2_MEMORY_MMAP
};
req.count = desired_video_buffers;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
res = v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req); res = v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req);
if (res < 0) { if (res < 0) {
if (errno == EINVAL) { if (errno == EINVAL) {
...@@ -397,11 +398,11 @@ static int mmap_init(AVFormatContext *ctx) ...@@ -397,11 +398,11 @@ static int mmap_init(AVFormatContext *ctx)
} }
for (i = 0; i < req.count; i++) { for (i = 0; i < req.count; i++) {
struct v4l2_buffer buf = {0}; struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; .index = i,
buf.memory = V4L2_MEMORY_MMAP; .memory = V4L2_MEMORY_MMAP
buf.index = i; };
res = v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf); res = v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
if (res < 0) { if (res < 0) {
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n"); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
...@@ -431,7 +432,7 @@ static int mmap_init(AVFormatContext *ctx) ...@@ -431,7 +432,7 @@ static int mmap_init(AVFormatContext *ctx)
static void mmap_release_buffer(AVPacket *pkt) static void mmap_release_buffer(AVPacket *pkt)
{ {
struct v4l2_buffer buf = {0}; struct v4l2_buffer buf = { 0 };
int res, fd; int res, fd;
struct buff_data *buf_descriptor = pkt->priv; struct buff_data *buf_descriptor = pkt->priv;
...@@ -456,12 +457,20 @@ static void mmap_release_buffer(AVPacket *pkt) ...@@ -456,12 +457,20 @@ static void mmap_release_buffer(AVPacket *pkt)
static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
{ {
struct video_data *s = ctx->priv_data; struct video_data *s = ctx->priv_data;
struct v4l2_buffer buf = {0}; struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_MMAP
};
struct buff_data *buf_descriptor; struct buff_data *buf_descriptor;
struct pollfd p = { .fd = s->fd, .events = POLLIN };
int res; int res;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; res = poll(&p, 1, s->timeout);
buf.memory = V4L2_MEMORY_MMAP; if (res < 0)
return AVERROR(errno);
if (!(p.revents & (POLLIN | POLLERR | POLLHUP)))
return AVERROR(EAGAIN);
/* FIXME: Some special treatment might be needed in case of loss of signal... */ /* FIXME: Some special treatment might be needed in case of loss of signal... */
while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
...@@ -513,11 +522,11 @@ static int mmap_start(AVFormatContext *ctx) ...@@ -513,11 +522,11 @@ static int mmap_start(AVFormatContext *ctx)
int i, res; int i, res;
for (i = 0; i < s->buffers; i++) { for (i = 0; i < s->buffers; i++) {
struct v4l2_buffer buf = {0}; struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; .index = i,
buf.memory = V4L2_MEMORY_MMAP; .memory = V4L2_MEMORY_MMAP
buf.index = i; };
res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
if (res < 0) { if (res < 0) {
...@@ -560,12 +569,12 @@ static void mmap_close(struct video_data *s) ...@@ -560,12 +569,12 @@ static void mmap_close(struct video_data *s)
static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
{ {
struct video_data *s = s1->priv_data; struct video_data *s = s1->priv_data;
struct v4l2_input input = {0}; struct v4l2_input input = { 0 };
struct v4l2_standard standard = {0}; struct v4l2_standard standard = { 0 };
struct v4l2_streamparm streamparm = {0}; struct v4l2_streamparm streamparm = { 0 };
struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe; struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
AVRational framerate_q = { 0 };
int i, ret; int i, ret;
AVRational framerate_q={0};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
...@@ -596,7 +605,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) ...@@ -596,7 +605,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n", av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
s->standard); s->standard);
/* set tv standard */ /* set tv standard */
for (i = 0;; i++) { for(i=0;;i++) {
standard.index = i; standard.index = i;
ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard); ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
if (ret < 0 || !av_strcasecmp(standard.name, s->standard)) if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
...@@ -649,6 +658,10 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) ...@@ -649,6 +658,10 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
s1->streams[0]->codec->time_base.den = tpf->denominator; s1->streams[0]->codec->time_base.den = tpf->denominator;
s1->streams[0]->codec->time_base.num = tpf->numerator; s1->streams[0]->codec->time_base.num = tpf->numerator;
s->timeout = 100 +
av_rescale_q(1, s1->streams[0]->codec->time_base,
(AVRational){1, 1000});
return 0; return 0;
} }
...@@ -722,11 +735,15 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) ...@@ -722,11 +735,15 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
} }
if (s->pixel_format) { if (s->pixel_format) {
AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);
if (codec)
s1->video_codec_id = codec->id;
pix_fmt = av_get_pix_fmt(s->pixel_format); pix_fmt = av_get_pix_fmt(s->pixel_format);
if (pix_fmt == PIX_FMT_NONE) { if (pix_fmt == PIX_FMT_NONE && !codec) {
av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", av_log(s1, AV_LOG_ERROR, "No such input format: %s.\n",
s->pixel_format); s->pixel_format);
res = AVERROR(EINVAL); res = AVERROR(EINVAL);
...@@ -832,7 +849,8 @@ static const AVOption options[] = { ...@@ -832,7 +849,8 @@ static const AVOption options[] = {
{ "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC }, { "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC },
{ "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC }, { "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC },
{ "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "pixel_format", "Preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "input_format", "Preferred pixel format (for raw video) or codec name", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" }, { "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" },
{ "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" }, { "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" },
......
...@@ -39,6 +39,12 @@ typedef struct { ...@@ -39,6 +39,12 @@ typedef struct {
char sws_param[256]; char sws_param[256];
} BufferSourceContext; } BufferSourceContext;
#define CHECK_PARAM_CHANGE(s, c, width, height, format)\
if (c->w != width || c->h != height || c->pix_fmt != format) {\
av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
return AVERROR(EINVAL);\
}
int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter,
AVFilterBufferRef *picref, int flags) AVFilterBufferRef *picref, int flags)
{ {
...@@ -125,6 +131,8 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) ...@@ -125,6 +131,8 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
// CHECK_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
c->picref = buf; c->picref = buf;
return 0; return 0;
......
...@@ -144,7 +144,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -144,7 +144,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
(s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8)); (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
else else
s->audio_frame_count += s->audio_frame_count +=
(s->audio_chunk_size - 6) / s->audio_channels; (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
av_dlog(NULL, "sending audio frame with pts %"PRId64" (%d audio frames)\n", av_dlog(NULL, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
pkt->pts, s->audio_frame_count); pkt->pts, s->audio_frame_count);
......
...@@ -2570,7 +2570,8 @@ static int mov_write_header(AVFormatContext *s) ...@@ -2570,7 +2570,8 @@ static int mov_write_header(AVFormatContext *s)
#endif #endif
if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
mov->time = ff_iso8601_to_unix_time(t->value); mov->time = ff_iso8601_to_unix_time(t->value);
mov->time += 0x7C25B080; //1970 based -> 1904 based if (mov->time)
mov->time += 0x7C25B080; // 1970 based -> 1904 based
if (mov->chapter_track) if (mov->chapter_track)
mov_create_chapter_track(s, mov->chapter_track); mov_create_chapter_track(s, mov->chapter_track);
......
...@@ -207,7 +207,7 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -207,7 +207,7 @@ static int vmd_read_header(AVFormatContext *s,
vmd->frame_table[total_frames].pts = current_audio_pts; vmd->frame_table[total_frames].pts = current_audio_pts;
total_frames++; total_frames++;
if(!current_audio_pts) if(!current_audio_pts)
current_audio_pts += sound_buffers; current_audio_pts += sound_buffers - 1;
else else
current_audio_pts++; current_audio_pts++;
break; break;
......
...@@ -135,7 +135,7 @@ cglobal %2ToY, 5, 5, %1, dst, unused0, unused1, src, w ...@@ -135,7 +135,7 @@ cglobal %2ToY, 5, 5, %1, dst, unused0, unused1, src, w
%macro YUYV_TO_UV_FN 2-3 %macro YUYV_TO_UV_FN 2-3
cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w
%ifdef ARCH_X86_64 %ifdef ARCH_X86_64
movsxd wq, r5m movsxd wq, dword r5m
%else ; x86-32 %else ; x86-32
mov wq, r5m mov wq, r5m
%endif %endif
...@@ -190,7 +190,7 @@ cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w ...@@ -190,7 +190,7 @@ cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w
%macro NVXX_TO_UV_FN 2 %macro NVXX_TO_UV_FN 2
cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w
%ifdef ARCH_X86_64 %ifdef ARCH_X86_64
movsxd wq, r5m movsxd wq, dword r5m
%else ; x86-32 %else ; x86-32
mov wq, r5m mov wq, r5m
%endif %endif
......
...@@ -1584,12 +1584,24 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, ...@@ -1584,12 +1584,24 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst,
void *mmx2FilterCode= c->lumMmx2FilterCode; void *mmx2FilterCode= c->lumMmx2FilterCode;
int i; int i;
#if defined(PIC) #if defined(PIC)
DECLARE_ALIGNED(8, uint64_t, ebxsave); uint64_t ebxsave;
#endif
#if ARCH_X86_64
uint64_t retsave;
#endif #endif
__asm__ volatile( __asm__ volatile(
#if defined(PIC) #if defined(PIC)
"mov %%"REG_b", %5 \n\t" "mov %%"REG_b", %5 \n\t"
#if ARCH_X86_64
"mov -8(%%rsp), %%"REG_a" \n\t"
"mov %%"REG_a", %6 \n\t"
#endif
#else
#if ARCH_X86_64
"mov -8(%%rsp), %%"REG_a" \n\t"
"mov %%"REG_a", %5 \n\t"
#endif
#endif #endif
"pxor %%mm7, %%mm7 \n\t" "pxor %%mm7, %%mm7 \n\t"
"mov %0, %%"REG_c" \n\t" "mov %0, %%"REG_c" \n\t"
...@@ -1631,11 +1643,23 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, ...@@ -1631,11 +1643,23 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst,
#if defined(PIC) #if defined(PIC)
"mov %5, %%"REG_b" \n\t" "mov %5, %%"REG_b" \n\t"
#if ARCH_X86_64
"mov %6, %%"REG_a" \n\t"
"mov %%"REG_a", -8(%%rsp) \n\t"
#endif
#else
#if ARCH_X86_64
"mov %5, %%"REG_a" \n\t"
"mov %%"REG_a", -8(%%rsp) \n\t"
#endif
#endif #endif
:: "m" (src), "m" (dst), "m" (filter), "m" (filterPos), :: "m" (src), "m" (dst), "m" (filter), "m" (filterPos),
"m" (mmx2FilterCode) "m" (mmx2FilterCode)
#if defined(PIC) #if defined(PIC)
,"m" (ebxsave) ,"m" (ebxsave)
#endif
#if ARCH_X86_64
,"m"(retsave)
#endif #endif
: "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
#if !defined(PIC) #if !defined(PIC)
...@@ -1658,10 +1682,22 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2, ...@@ -1658,10 +1682,22 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2,
#if defined(PIC) #if defined(PIC)
DECLARE_ALIGNED(8, uint64_t, ebxsave); DECLARE_ALIGNED(8, uint64_t, ebxsave);
#endif #endif
#if ARCH_X86_64
DECLARE_ALIGNED(8, uint64_t, retsave);
#endif
__asm__ volatile( __asm__ volatile(
#if defined(PIC) #if defined(PIC)
"mov %%"REG_b", %7 \n\t" "mov %%"REG_b", %7 \n\t"
#if ARCH_X86_64
"mov -8(%%rsp), %%"REG_a" \n\t"
"mov %%"REG_a", %8 \n\t"
#endif
#else
#if ARCH_X86_64
"mov -8(%%rsp), %%"REG_a" \n\t"
"mov %%"REG_a", %7 \n\t"
#endif
#endif #endif
"pxor %%mm7, %%mm7 \n\t" "pxor %%mm7, %%mm7 \n\t"
"mov %0, %%"REG_c" \n\t" "mov %0, %%"REG_c" \n\t"
...@@ -1691,11 +1727,23 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2, ...@@ -1691,11 +1727,23 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2,
#if defined(PIC) #if defined(PIC)
"mov %7, %%"REG_b" \n\t" "mov %7, %%"REG_b" \n\t"
#if ARCH_X86_64
"mov %8, %%"REG_a" \n\t"
"mov %%"REG_a", -8(%%rsp) \n\t"
#endif
#else
#if ARCH_X86_64
"mov %7, %%"REG_a" \n\t"
"mov %%"REG_a", -8(%%rsp) \n\t"
#endif
#endif #endif
:: "m" (src1), "m" (dst1), "m" (filter), "m" (filterPos), :: "m" (src1), "m" (dst1), "m" (filter), "m" (filterPos),
"m" (mmx2FilterCode), "m" (src2), "m"(dst2) "m" (mmx2FilterCode), "m" (src2), "m"(dst2)
#if defined(PIC) #if defined(PIC)
,"m" (ebxsave) ,"m" (ebxsave)
#endif
#if ARCH_X86_64
,"m"(retsave)
#endif #endif
: "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
#if !defined(PIC) #if !defined(PIC)
......
4fe333ff79e86cca6ba8c109cc08263e *./tests/data/acodec/alac.m4a cf9a4b40ab945367cbb0e6cbb4cf37a1 *./tests/data/acodec/alac.m4a
389166 ./tests/data/acodec/alac.m4a 389166 ./tests/data/acodec/alac.m4a
64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/alac.acodec.out.wav 64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/alac.acodec.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400
d07e475322765c20b1fcdb822ad5dc04 *./tests/data/acodec/pcm_s16be.mov 4529713e8b744edb3e62c4e688a3f987 *./tests/data/acodec/pcm_s16be.mov
1059065 ./tests/data/acodec/pcm_s16be.mov 1059065 ./tests/data/acodec/pcm_s16be.mov
64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s16be.acodec.out.wav 64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s16be.acodec.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400
f66d9543a4e04346818e802c4f2d7a30 *./tests/data/acodec/pcm_s24be.mov 8a7b79317738f91a137c7f6519c3df72 *./tests/data/acodec/pcm_s24be.mov
1588265 ./tests/data/acodec/pcm_s24be.mov 1588265 ./tests/data/acodec/pcm_s24be.mov
64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s24be.acodec.out.wav 64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s24be.acodec.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400
09c919947211de14b3ad0e7603e5b44e *./tests/data/acodec/pcm_s32be.mov c9f29c97890f69796faa227c3c08c3d8 *./tests/data/acodec/pcm_s32be.mov
2117465 ./tests/data/acodec/pcm_s32be.mov 2117465 ./tests/data/acodec/pcm_s32be.mov
64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s32be.acodec.out.wav 64151e4bcc2b717aa5a8454d424d6a1f *./tests/data/pcm_s32be.acodec.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400
52d8c65c4987227979785d5ac2030175 *./tests/data/acodec/pcm_s8.mov bfd442109b661daf8ee7a468d9d6b944 *./tests/data/acodec/pcm_s8.mov
529865 ./tests/data/acodec/pcm_s8.mov 529865 ./tests/data/acodec/pcm_s8.mov
651d4eb8d98dfcdda96ae6c43d8f156b *./tests/data/pcm_s8.acodec.out.wav 651d4eb8d98dfcdda96ae6c43d8f156b *./tests/data/pcm_s8.acodec.out.wav
stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400 stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400
3340b7ffe1b1d98a50622bd53f786d41 *./tests/data/lavf/lavf.mov 37c9c1272d9c524b44692e9192d82033 *./tests/data/lavf/lavf.mov
357857 ./tests/data/lavf/lavf.mov 357857 ./tests/data/lavf/lavf.mov
./tests/data/lavf/lavf.mov CRC=0x2f6a9b26 ./tests/data/lavf/lavf.mov CRC=0x2f6a9b26
d2621659037803a30b77e3d4f87eb733 *./tests/data/vsynth1/dnxhd-1080i.mov 153afc6bd83611db4ba0d6d509fc3d74 *./tests/data/vsynth1/dnxhd-1080i.mov
3031895 ./tests/data/vsynth1/dnxhd-1080i.mov 3031895 ./tests/data/vsynth1/dnxhd-1080i.mov
0c651e840f860592f0d5b66030d9fa32 *./tests/data/dnxhd_1080i.vsynth1.out.yuv 0c651e840f860592f0d5b66030d9fa32 *./tests/data/dnxhd_1080i.vsynth1.out.yuv
stddev: 6.29 PSNR: 32.15 MAXDIFF: 64 bytes: 760320/ 7603200 stddev: 6.29 PSNR: 32.15 MAXDIFF: 64 bytes: 760320/ 7603200
f32960be0f05be8b2ed03447e1eaea6f *./tests/data/vsynth1/odivx.mp4 6ea715a2de70af8d37128ce643e4cca0 *./tests/data/vsynth1/odivx.mp4
539996 ./tests/data/vsynth1/odivx.mp4 539996 ./tests/data/vsynth1/odivx.mp4
8828a375448dc5c2215163ba70656f89 *./tests/data/mpeg4.vsynth1.out.yuv 8828a375448dc5c2215163ba70656f89 *./tests/data/mpeg4.vsynth1.out.yuv
stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200
062e1f5ec6ebdbc43ee69e0393221866 *./tests/data/vsynth1/prores.mov e8487134a5e4b8351de7ad386fb25e27 *./tests/data/vsynth1/prores.mov
5022795 ./tests/data/vsynth1/prores.mov 5022795 ./tests/data/vsynth1/prores.mov
a2e2d1d45341a94ff994d1d92629f778 *./tests/data/prores.vsynth1.out.yuv a2e2d1d45341a94ff994d1d92629f778 *./tests/data/prores.vsynth1.out.yuv
stddev: 2.47 PSNR: 40.27 MAXDIFF: 31 bytes: 7603200/ 7603200 stddev: 2.47 PSNR: 40.27 MAXDIFF: 31 bytes: 7603200/ 7603200
b67340783a817fe398fd138175c7fa07 *./tests/data/vsynth1/qtrle.mov 54a37ac94abdd95b9e5726a2211e8e1c *./tests/data/vsynth1/qtrle.mov
15263072 ./tests/data/vsynth1/qtrle.mov 15263072 ./tests/data/vsynth1/qtrle.mov
93695a27c24a61105076ca7b1f010bbd *./tests/data/qtrle.vsynth1.out.yuv 93695a27c24a61105076ca7b1f010bbd *./tests/data/qtrle.vsynth1.out.yuv
stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200 stddev: 3.42 PSNR: 37.44 MAXDIFF: 48 bytes: 7603200/ 7603200
f0c3cd26e80674a62683685d0508622a *./tests/data/vsynth1/qtrlegray.mov 7b04fbf0fa29600517d048882583128b *./tests/data/vsynth1/qtrlegray.mov
5113268 ./tests/data/vsynth1/qtrlegray.mov 5113268 ./tests/data/vsynth1/qtrlegray.mov
29def4aed035ed65d3a89f7d382fccbe *./tests/data/qtrlegray.vsynth1.out.yuv 29def4aed035ed65d3a89f7d382fccbe *./tests/data/qtrlegray.vsynth1.out.yuv
stddev: 25.95 PSNR: 19.85 MAXDIFF: 122 bytes: 7603200/ 7603200 stddev: 25.95 PSNR: 19.85 MAXDIFF: 122 bytes: 7603200/ 7603200
ebaf85e8743ad1f6c2228d473fe16d83 *./tests/data/vsynth1/svq1.mov 0658c40cfef3964c60bb9b05233727de *./tests/data/vsynth1/svq1.mov
1334207 ./tests/data/vsynth1/svq1.mov 1334207 ./tests/data/vsynth1/svq1.mov
9cc35c54b2c77d36bd7e308b393c1f81 *./tests/data/svq1.vsynth1.out.yuv 9cc35c54b2c77d36bd7e308b393c1f81 *./tests/data/svq1.vsynth1.out.yuv
stddev: 9.58 PSNR: 28.50 MAXDIFF: 210 bytes: 7603200/ 7603200 stddev: 9.58 PSNR: 28.50 MAXDIFF: 210 bytes: 7603200/ 7603200
af3b282a2194a7e2748df7684330728a *./tests/data/vsynth2/dnxhd-1080i.mov 677588203650770792b63a66231bd127 *./tests/data/vsynth2/dnxhd-1080i.mov
3031895 ./tests/data/vsynth2/dnxhd-1080i.mov 3031895 ./tests/data/vsynth2/dnxhd-1080i.mov
3c559af629ae0a8fb1a9a0e4b4da7733 *./tests/data/dnxhd_1080i.vsynth2.out.yuv 3c559af629ae0a8fb1a9a0e4b4da7733 *./tests/data/dnxhd_1080i.vsynth2.out.yuv
stddev: 1.31 PSNR: 45.77 MAXDIFF: 23 bytes: 760320/ 7603200 stddev: 1.31 PSNR: 45.77 MAXDIFF: 23 bytes: 760320/ 7603200
4d092ca067362a61b9c96f5f12a1ab5a *./tests/data/vsynth2/odivx.mp4 051ff85797971b9047723044eaec07be *./tests/data/vsynth2/odivx.mp4
119649 ./tests/data/vsynth2/odivx.mp4 119649 ./tests/data/vsynth2/odivx.mp4
90a3577850239083a9042bef33c50e85 *./tests/data/mpeg4.vsynth2.out.yuv 90a3577850239083a9042bef33c50e85 *./tests/data/mpeg4.vsynth2.out.yuv
stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200 stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200
85f16a09120b668d02cb9cce86dfa9b1 *./tests/data/vsynth2/prores.mov 81988143e6169dbf735bd180bf5a8703 *./tests/data/vsynth2/prores.mov
2844034 ./tests/data/vsynth2/prores.mov 2844034 ./tests/data/vsynth2/prores.mov
b5844025c0f4c7c37db702c3213db232 *./tests/data/prores.vsynth2.out.yuv b5844025c0f4c7c37db702c3213db232 *./tests/data/prores.vsynth2.out.yuv
stddev: 1.31 PSNR: 45.77 MAXDIFF: 11 bytes: 7603200/ 7603200 stddev: 1.31 PSNR: 45.77 MAXDIFF: 11 bytes: 7603200/ 7603200
f18ed8321e19a7cadedc3ba32d71e0ea *./tests/data/vsynth2/qtrle.mov 04c58848958a0684eba8a816e00dba28 *./tests/data/vsynth2/qtrle.mov
14798259 ./tests/data/vsynth2/qtrle.mov 14798259 ./tests/data/vsynth2/qtrle.mov
98d0e2854731472c5bf13d8638502d0a *./tests/data/qtrle.vsynth2.out.yuv 98d0e2854731472c5bf13d8638502d0a *./tests/data/qtrle.vsynth2.out.yuv
stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200 stddev: 1.26 PSNR: 46.10 MAXDIFF: 13 bytes: 7603200/ 7603200
799451fc6215c51fc892a2284721b8e7 *./tests/data/vsynth2/qtrlegray.mov b9769bd1ff7e3b0fb26dfc7555e789b4 *./tests/data/vsynth2/qtrlegray.mov
5111257 ./tests/data/vsynth2/qtrlegray.mov 5111257 ./tests/data/vsynth2/qtrlegray.mov
f63b5ebdfdba750e547c25131b0a3fd1 *./tests/data/qtrlegray.vsynth2.out.yuv f63b5ebdfdba750e547c25131b0a3fd1 *./tests/data/qtrlegray.vsynth2.out.yuv
stddev: 19.42 PSNR: 22.36 MAXDIFF: 72 bytes: 7603200/ 7603200 stddev: 19.42 PSNR: 22.36 MAXDIFF: 72 bytes: 7603200/ 7603200
8d5275bf59aac368d5da11d9c34b8cf2 *./tests/data/vsynth2/svq1.mov 320a7fbbaecc0989df054bf9678bfdf6 *./tests/data/vsynth2/svq1.mov
766691 ./tests/data/vsynth2/svq1.mov 766691 ./tests/data/vsynth2/svq1.mov
aa03471dac3f49455a33a2b19fda1098 *./tests/data/svq1.vsynth2.out.yuv aa03471dac3f49455a33a2b19fda1098 *./tests/data/svq1.vsynth2.out.yuv
stddev: 3.23 PSNR: 37.93 MAXDIFF: 61 bytes: 7603200/ 7603200 stddev: 3.23 PSNR: 37.93 MAXDIFF: 61 bytes: 7603200/ 7603200
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment