#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavdevice/avdevice.h"
+#include "libavresample/avresample.h"
#include "libswscale/swscale.h"
-#if CONFIG_POSTPROC
-#include "libpostproc/postprocess.h"
-#endif
+#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/mathematics.h"
+#include "libavutil/imgutils.h"
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/eval.h"
struct SwsContext *sws_opts;
AVDictionary *format_opts, *codec_opts;
-static const int this_year = 2011;
+static const int this_year = 2012;
void init_opts(void)
{
if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
/* handle 'no' bool option */
po = find_option(options, opt + 2);
- if (!(po->name && (po->flags & OPT_BOOL)))
- goto unknown_opt;
- bool_val = 0;
+ if ((po->name && (po->flags & OPT_BOOL)))
+ bool_val = 0;
}
if (!po->name)
po = find_option(options, "default");
if (!po->name) {
-unknown_opt:
av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
return AVERROR(EINVAL);
}
}
}
-/*
- * Return index of option opt in argv or 0 if not found.
- */
-static int locate_option(int argc, char **argv, const OptionDef *options,
- const char *optname)
+int locate_option(int argc, char **argv, const OptionDef *options,
+ const char *optname)
{
const OptionDef *po;
int i;
const char *indent = flags & INDENT? " " : ""; \
if (flags & SHOW_VERSION) { \
unsigned int version = libname##_version(); \
- av_log(NULL, level, "%slib%-9s %2d.%3d.%2d / %2d.%3d.%2d\n",\
+ av_log(NULL, level, \
+ "%slib%-10s %2d.%3d.%2d / %2d.%3d.%2d\n", \
indent, #libname, \
LIB##LIBNAME##_VERSION_MAJOR, \
LIB##LIBNAME##_VERSION_MINOR, \
PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
+ PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
-#if CONFIG_POSTPROC
- PRINT_LIB_INFO(postproc, POSTPROC, flags, level);
-#endif
}
void show_banner(void)
decode = encode = cap = 0;
}
if (p2 && strcmp(p->name, p2->name) == 0) {
- if (p->decode)
+ if (av_codec_is_decoder(p))
decode = 1;
- if (p->encode)
+ if (av_codec_is_encoder(p))
encode = 1;
cap |= p->capabilities;
}
for (i = 0; i < 3 && !f; i++) {
if (!base[i])
continue;
- snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i],
+ snprintf(filename, filename_size, "%s%s/%s.avpreset", base[i],
i != 1 ? "" : "/.avconv", preset_name);
f = fopen(filename, "r");
if (!f && codec_name) {
snprintf(filename, filename_size,
- "%s%s/%s-%s.ffpreset",
+ "%s%s/%s-%s.avpreset",
base[i], i != 1 ? "" : "/.avconv", codec_name,
preset_name);
f = fopen(filename, "r");
case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
case 'd': type = AVMEDIA_TYPE_DATA; break;
case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
+ default: av_assert0(0);
}
if (type != st->codec->codec_type)
return 0;
return opts;
}
-#if CONFIG_AVFILTER
+void *grow_array(void *array, int elem_size, int *size, int new_size)
+{
+ if (new_size >= INT_MAX / elem_size) {
+ av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
+ exit_program(1);
+ }
+ if (*size < new_size) {
+ uint8_t *tmp = av_realloc(array, new_size*elem_size);
+ if (!tmp) {
+ av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
+ exit_program(1);
+ }
+ memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
+ *size = new_size;
+ return tmp;
+ }
+ return array;
+}
-static int ffsink_init(AVFilterContext *ctx, const char *args, void *opaque)
+static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf)
{
- FFSinkContext *priv = ctx->priv;
+ FrameBuffer *buf = av_mallocz(sizeof(*buf));
+ int i, ret;
+ const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
+ int h_chroma_shift, v_chroma_shift;
+ int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
+ int w = s->width, h = s->height;
+
+ if (!buf)
+ return AVERROR(ENOMEM);
- if (!opaque)
- return AVERROR(EINVAL);
- *priv = *(FFSinkContext *)opaque;
+ if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
+ w += 2*edge;
+ h += 2*edge;
+ }
+ avcodec_align_dimensions(s, &w, &h);
+ if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
+ s->pix_fmt, 32)) < 0) {
+ av_freep(&buf);
+ return ret;
+ }
+ /* XXX this shouldn't be needed, but some tests break without this line
+ * those decoders are buggy and need to be fixed.
+ * the following tests fail:
+ * cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
+ */
+ memset(buf->base[0], 128, ret);
+
+ avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+ for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
+ const int h_shift = i==0 ? 0 : h_chroma_shift;
+ const int v_shift = i==0 ? 0 : v_chroma_shift;
+ if (s->flags & CODEC_FLAG_EMU_EDGE)
+ buf->data[i] = buf->base[i];
+ else
+ buf->data[i] = buf->base[i] +
+ FFALIGN((buf->linesize[i]*edge >> v_shift) +
+ (pixel_size*edge >> h_shift), 32);
+ }
+ buf->w = s->width;
+ buf->h = s->height;
+ buf->pix_fmt = s->pix_fmt;
+ buf->pool = pool;
+
+ *pbuf = buf;
return 0;
}
-static void null_end_frame(AVFilterLink *inlink) { }
-
-static int ffsink_query_formats(AVFilterContext *ctx)
+int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
{
- FFSinkContext *priv = ctx->priv;
- enum PixelFormat pix_fmts[] = { priv->pix_fmt, PIX_FMT_NONE };
+ FrameBuffer **pool = s->opaque;
+ FrameBuffer *buf;
+ int ret, i;
+
+ if (!*pool && (ret = alloc_buffer(pool, s, pool)) < 0)
+ return ret;
+
+ buf = *pool;
+ *pool = buf->next;
+ buf->next = NULL;
+ if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
+ av_freep(&buf->base[0]);
+ av_free(buf);
+ if ((ret = alloc_buffer(pool, s, &buf)) < 0)
+ return ret;
+ }
+ buf->refcount++;
+
+ frame->opaque = buf;
+ frame->type = FF_BUFFER_TYPE_USER;
+ frame->extended_data = frame->data;
+ frame->pkt_pts = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE;
+ frame->width = buf->w;
+ frame->height = buf->h;
+ frame->format = buf->pix_fmt;
+ frame->sample_aspect_ratio = s->sample_aspect_ratio;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
+ frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't
+ frame->data[i] = buf->data[i];
+ frame->linesize[i] = buf->linesize[i];
+ }
- avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
return 0;
}
-AVFilter ffsink = {
- .name = "ffsink",
- .priv_size = sizeof(FFSinkContext),
- .init = ffsink_init,
-
- .query_formats = ffsink_query_formats,
+static void unref_buffer(FrameBuffer *buf)
+{
+ FrameBuffer **pool = buf->pool;
- .inputs = (AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .end_frame = null_end_frame,
- .min_perms = AV_PERM_READ, },
- { .name = NULL }},
- .outputs = (AVFilterPad[]) {{ .name = NULL }},
-};
+ av_assert0(buf->refcount);
+ buf->refcount--;
+ if (!buf->refcount) {
+ buf->next = *pool;
+ *pool = buf;
+ }
+}
-int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
- AVFilterBufferRef **picref_ptr, AVRational *tb)
+void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
{
- int ret;
- AVFilterBufferRef *picref;
+ FrameBuffer *buf = frame->opaque;
+ int i;
- if ((ret = avfilter_request_frame(ctx->inputs[0])) < 0)
- return ret;
- if (!(picref = ctx->inputs[0]->cur_buf))
- return AVERROR(ENOENT);
- *picref_ptr = picref;
- ctx->inputs[0]->cur_buf = NULL;
- *tb = ctx->inputs[0]->time_base;
-
- memcpy(frame->data, picref->data, sizeof(frame->data));
- memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize));
- frame->interlaced_frame = picref->video->interlaced;
- frame->top_field_first = picref->video->top_field_first;
- frame->key_frame = picref->video->key_frame;
- frame->pict_type = picref->video->pict_type;
- frame->sample_aspect_ratio = picref->video->pixel_aspect;
-
- return 1;
+ for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
+ frame->data[i] = NULL;
+
+ unref_buffer(buf);
}
-#endif /* CONFIG_AVFILTER */
+void filter_release_buffer(AVFilterBuffer *fb)
+{
+ FrameBuffer *buf = fb->priv;
+ av_free(fb);
+ unref_buffer(buf);
+}
-void *grow_array(void *array, int elem_size, int *size, int new_size)
+void free_buffer_pool(FrameBuffer **pool)
{
- if (new_size >= INT_MAX / elem_size) {
- av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
- exit_program(1);
+ FrameBuffer *buf = *pool;
+ while (buf) {
+ *pool = buf->next;
+ av_freep(&buf->base[0]);
+ av_free(buf);
+ buf = *pool;
}
- if (*size < new_size) {
- uint8_t *tmp = av_realloc(array, new_size*elem_size);
- if (!tmp) {
- av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
- exit_program(1);
- }
- memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
- *size = new_size;
- return tmp;
- }
- return array;
}