*/
#define HAVE_AV_CONFIG_H
#include "avformat.h"
+#include "framehook.h"
#ifndef CONFIG_WIN32
#include <unistd.h>
av_free(buf);
}
+static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp)
+{
+ AVCodecContext *dec;
+ AVPicture *picture2;
+ AVPicture picture_tmp;
+ UINT8 *buf = 0;
+
+ dec = &ist->st->codec;
+
+ /* deinterlace : must be done before any resize */
+ if (do_deinterlace) {
+ int size;
+
+ /* create temporary picture */
+ size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
+ buf = av_malloc(size);
+ if (!buf)
+ return;
+
+ picture2 = &picture_tmp;
+ avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
+
+ if (avpicture_deinterlace(picture2, picture,
+ dec->pix_fmt, dec->width, dec->height) < 0) {
+ /* if error, do not deinterlace */
+ av_free(buf);
+ buf = NULL;
+ picture2 = picture;
+ }
+ } else {
+ picture2 = picture;
+ }
+
+ frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height);
+
+ if (picture != picture2)
+ *picture = *picture2;
+ *bufp = buf;
+}
+
/* we begin to correct av delay at this threshold */
#define AV_DELAY_MAX 0.100
int *frame_size, AVOutputStream *audio_sync)
{
int nb_frames, i, ret;
- AVPicture *picture, *picture2, *pict;
- AVPicture picture_tmp1, picture_tmp2;
+ AVPicture *picture, *pict;
+ AVPicture picture_tmp1;
static UINT8 *video_buffer;
UINT8 *buf = NULL, *buf1 = NULL;
AVCodecContext *enc, *dec;
else if (av_delay > AV_DELAY_MAX)
nb_frames = 0;
}
+ } else {
+ double vdelta;
+
+ if (ost->sync_ipts != AV_NOPTS_VALUE) {
+ vdelta = (double)(ost->st->pts.val) * s->pts_num / s->pts_den - ost->sync_ipts;
+ if (vdelta < -AV_DELAY_MAX)
+ nb_frames = 2;
+ else if (vdelta > AV_DELAY_MAX)
+ nb_frames = 0;
+ //printf("vdelta=%f\n", vdelta);
+ }
}
- /* XXX: also handle frame rate conversion */
if (nb_frames <= 0)
return;
if (!video_buffer)
return;
- /* deinterlace : must be done before any resize */
- if (do_deinterlace) {
- int size;
-
- /* create temporary picture */
- size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
- buf1 = av_malloc(size);
- if (!buf1)
- return;
-
- picture2 = &picture_tmp2;
- avpicture_fill(picture2, buf1, dec->pix_fmt, dec->width, dec->height);
-
- if (avpicture_deinterlace(picture2, picture1,
- dec->pix_fmt, dec->width, dec->height) < 0) {
- /* if error, do not deinterlace */
- av_free(buf1);
- buf1 = NULL;
- picture2 = picture1;
- }
- } else {
- picture2 = picture1;
- }
-
/* convert pixel format if needed */
if (enc->pix_fmt != dec->pix_fmt) {
int size;
avpicture_fill(pict, buf, enc->pix_fmt, dec->width, dec->height);
if (img_convert(pict, enc->pix_fmt,
- picture2, dec->pix_fmt,
+ picture1, dec->pix_fmt,
dec->width, dec->height) < 0) {
fprintf(stderr, "pixel format conversion not handled\n");
goto the_end;
}
} else {
- pict = picture2;
+ pict = picture1;
}
/* XXX: resampling could be done before raw format convertion in
ost = ost_table[i];
os = output_files[ost->file_index];
enc = &ost->st->codec;
+ if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
+ sprintf(buf + strlen(buf), "q=%2d ",
+ enc->quality);
+ }
if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
frame_number = ost->frame_number;
sprintf(buf + strlen(buf), "frame=%5d q=%2d ",
AVCodec *codec;
codec = avcodec_find_decoder(ist->st->codec.codec_id);
if (!codec) {
- fprintf(stderr, "Unsupported codec for input stream #%d.%d\n",
- ist->file_index, ist->index);
+ fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n",
+ ist->st->codec.codec_id, ist->file_index, ist->index);
exit(1);
}
if (avcodec_open(&ist->st->codec, codec) < 0) {
int data_size, got_picture;
AVPicture picture;
short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
+ void *buffer_to_free;
double pts_min;
redo:
ptr += ret;
len -= ret;
+ buffer_to_free = 0;
+ if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) {
+ pre_process_video_frame(ist, &picture, &buffer_to_free);
+ }
+
ist->frame_decoded = 1;
#if 0
/* XXX: take into account the various fifos,
in particular for audio */
ost->sync_opts = ost->st->pts.val;
+ //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ipts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts);
+ } else {
+ //printf("pts.val=%lld\n", ost->st->pts.val);
}
if (ost->encoding_needed) {
}
}
}
+ av_free(buffer_to_free);
ipts = AV_NOPTS_VALUE;
}
discard_packet:
}
}
+void add_frame_hooker(const char *arg)
+{
+ int argc = 0;
+ char *argv[64];
+ int i;
+ char *args = strdup(arg);
+
+ argv[0] = strtok(args, " ");
+ while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
+ }
+
+ i = frame_hook_add(argc, argv);
+
+ if (i != 0) {
+ fprintf(stderr, "Failed to add video hook function: %s\n", arg);
+ exit(1);
+ }
+}
+
const char *motion_str[] = {
"zero",
"full",
{ "psnr", OPT_BOOL | OPT_EXPERT, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
{ "vstats", OPT_BOOL | OPT_EXPERT, {(void*)&do_vstats}, "dump video coding statistics to file" },
{ "bitexact", OPT_EXPERT, {(void*)opt_bitexact}, "only use bit exact algorithms (for codec testing)" },
+ { "vhook", HAS_ARG | OPT_EXPERT, {(void*)add_frame_hooker}, "insert video processing module", "module name and parameters" },
{ NULL, },
};
exit(1);
}
arg = NULL;
- if (po->flags & HAS_ARG)
+ if (po->flags & HAS_ARG) {
arg = argv[optindex++];
+ if (!arg) {
+ fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
+ exit(1);
+ }
+ }
if (po->flags & OPT_STRING) {
char *str;
str = strdup(arg);