Merge remote-tracking branch 'qatar/master'

* qatar/master:
  avs: call release_buffer() at the end.
  Add minor bumps and APIchanges entries for lavc/lavfi changes.
  mpegvideo.c: K&R formatting and cosmetics.
  avconv: avoid memcpy in vsrc_buffer when possible.
  avconv: implement get_buffer()/release_buffer().
  lavfi: add a new function av_buffersrc_buffer().
  lavfi: add avfilter_copy_frame_props()
  lavc: add format field to AVFrame
  lavc: add width and height fields to AVFrame
  lavc: add a sample_aspect_ratio field to AVFrame
  doxy: add website-alike style to the html output
  FAQ: add an entry for common error when using -profile

Conflicts:
	avconv.c
	cmdutils.c
	doc/APIchanges
	libavcodec/avcodec.h
	libavcodec/mpegvideo.c
	libavcodec/utils.c
	libavcodec/version.h
	libavfilter/Makefile
	libavfilter/avfilter.c
	libavfilter/avfilter.h
	libavfilter/src_movie.c
	libavfilter/vsrc_buffer.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
pull/3/head
Michael Niedermayer 13 years ago
commit 484e59a0a0
  1. 14
      Doxyfile
  2. 171
      avconv.c
  3. 1130
      doc/doxy/doxy_stylesheet.css
  4. 22
      doc/doxy/footer.html
  5. 17
      doc/doxy/header.html
  6. 20
      doc/faq.texi
  7. 144
      ffmpeg.c
  8. 38
      libavcodec/avcodec.h
  9. 10
      libavcodec/avs.c
  10. 379
      libavcodec/mpegvideo.c
  11. 4
      libavcodec/pthread.c
  12. 2
      libavcodec/utils.c
  13. 2
      libavcodec/version.h
  14. 4
      libavfilter/avcodec.c
  15. 2
      libavfilter/avcodec.h
  16. 11
      libavfilter/avfilter.h
  17. 38
      libavfilter/buffersrc.h
  18. 1
      libavfilter/src_movie.c
  19. 18
      libavfilter/vsrc_buffer.c

@ -33,6 +33,12 @@ PROJECT_NAME = FFmpeg
PROJECT_NUMBER =
# With the PROJECT_LOGO tag one can specify an logo or icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will
# copy the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
@ -761,7 +767,7 @@ ALPHABETICAL_INDEX = YES
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
COLS_IN_ALPHA_INDEX = 2
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
@ -795,13 +801,13 @@ HTML_FILE_EXTENSION = .html
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
HTML_HEADER = doc/doxy/header.html
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
HTML_FOOTER = doc/doxy/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
@ -810,7 +816,7 @@ HTML_FOOTER =
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
HTML_STYLESHEET = doc/doxy/doxy_stylesheet.css
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
# Doxygen will adjust the colors in the stylesheet and background images

@ -44,6 +44,7 @@
#include "libavutil/pixdesc.h"
#include "libavutil/avstring.h"
#include "libavutil/libm.h"
#include "libavutil/imgutils.h"
#include "libavformat/os_support.h"
#include "libavformat/ffm.h" // not public API
@ -53,6 +54,7 @@
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
# include "libavfilter/buffersink.h"
# include "libavfilter/buffersrc.h"
# include "libavfilter/vsrc_buffer.h"
#endif
@ -157,6 +159,19 @@ static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
typedef struct FrameBuffer {
uint8_t *base[4];
uint8_t *data[4];
int linesize[4];
int h, w;
enum PixelFormat pix_fmt;
int refcount;
struct InputStream *ist;
struct FrameBuffer *next;
} FrameBuffer;
typedef struct InputStream {
int file_index;
AVStream *st;
@ -174,6 +189,9 @@ typedef struct InputStream {
int is_start; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning;
AVDictionary *opts;
/* a pool of free buffers for decoded data */
FrameBuffer *buffer_pool;
} InputStream;
typedef struct InputFile {
@ -416,6 +434,131 @@ static void reset_options(OptionsContext *o)
init_opts();
}
static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf)
{
AVCodecContext *s = ist->st->codec;
FrameBuffer *buf = av_mallocz(sizeof(*buf));
int 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 (!(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:
* bethsoft-vid, 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 (int 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->ist = ist;
*pbuf = buf;
return 0;
}
static void free_buffer_pool(InputStream *ist)
{
FrameBuffer *buf = ist->buffer_pool;
while (buf) {
ist->buffer_pool = buf->next;
av_freep(&buf->base[0]);
av_free(buf);
buf = ist->buffer_pool;
}
}
static void unref_buffer(InputStream *ist, FrameBuffer *buf)
{
av_assert0(buf->refcount);
buf->refcount--;
if (!buf->refcount) {
buf->next = ist->buffer_pool;
ist->buffer_pool = buf;
}
}
static int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
{
InputStream *ist = s->opaque;
FrameBuffer *buf;
int ret, i;
if (!ist->buffer_pool && (ret = alloc_buffer(ist, &ist->buffer_pool)) < 0)
return ret;
buf = ist->buffer_pool;
ist->buffer_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(ist, &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;
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];
}
return 0;
}
static void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
{
InputStream *ist = s->opaque;
FrameBuffer *buf = frame->opaque;
int i;
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
frame->data[i] = NULL;
unref_buffer(ist, buf);
}
static void filter_release_buffer(AVFilterBuffer *fb)
{
FrameBuffer *buf = fb->priv;
av_free(fb);
unref_buffer(buf->ist, buf);
}
#if CONFIG_AVFILTER
static int configure_video_filters(InputStream *ist, OutputStream *ost)
@ -618,6 +761,7 @@ void exit_program(int ret)
av_freep(&input_streams[i].decoded_frame);
av_freep(&input_streams[i].filtered_frame);
av_dict_free(&input_streams[i].opts);
free_buffer_pool(&input_streams[i]);
}
if (vstats_file)
@ -1855,20 +1999,35 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
continue;
#if CONFIG_AVFILTER
if (ost->input_video_filter) {
if (!decoded_frame->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
decoded_frame->pts = ist->pts;
if (ist->st->codec->codec->capabilities & CODEC_CAP_DR1) {
FrameBuffer *buf = decoded_frame->opaque;
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
decoded_frame->data, decoded_frame->linesize,
AV_PERM_READ | AV_PERM_PRESERVE,
ist->st->codec->width, ist->st->codec->height,
ist->st->codec->pix_fmt);
avfilter_copy_frame_props(fb, decoded_frame);
fb->pts = ist->pts;
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
buf->refcount++;
av_buffersrc_buffer(ost->input_video_filter, fb);
} else
av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
av_free(buffer_to_free);
return AVERROR(ENOMEM);
} else
avcodec_get_frame_defaults(ist->filtered_frame);
filtered_frame = ist->filtered_frame;
frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
}
while (frame_available) {
if (ost->output_video_filter) {
AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
@ -2055,6 +2214,12 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb
return AVERROR(EINVAL);
}
if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) {
ist->st->codec->get_buffer = codec_get_buffer;
ist->st->codec->release_buffer = codec_release_buffer;
ist->st->codec->opaque = ist;
}
if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
ist->file_index, ist->st->index);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
</div>
<div id="footer">
<!--BEGIN GENERATE_TREEVIEW-->
<li class="footer">$generatedby
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
</ul>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<address class="footer"><small>
$generatedby &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
</a> $doxygenversion
</small></address>
<!--END !GENERATE_TREEVIEW-->
</div>
</div>
</body>
</html>

@ -0,0 +1,17 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath$doxy_stylesheet.css" rel="stylesheet" type="text/css" />
$treeview
$search
$mathjax
</head>
<div id="container">
<div id="body">
<div>

@ -272,6 +272,26 @@ ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i all.a \
rm temp[12].[av] all.[av]
@end example
@section -profile option fails when encoding H.264 video with AAC audio
@command{ffmpeg} prints an error like
@example
Undefined constant or missing '(' in 'baseline'
Unable to parse option value "baseline"
Error setting option profile to value baseline.
@end example
Short answer: write @option{-profile:v} instead of @option{-profile}.
Long answer: this happens because the @option{-profile} option can apply to both
video and audio. Specifically the AAC encoder also defines some profiles, none
of which are named @var{baseline}.
The solution is to apply the @option{-profile} option to the video stream only
by using @url{http://ffmpeg.org/ffmpeg.html#Stream-specifiers-1, Stream specifiers}.
Appending @code{:v} to it will do exactly that.
@chapter Development
@section Are there examples illustrating how to use the FFmpeg libraries, particularly libavcodec and libavformat?

@ -44,6 +44,7 @@
#include "libavutil/pixdesc.h"
#include "libavutil/avstring.h"
#include "libavutil/libm.h"
#include "libavutil/imgutils.h"
#include "libavformat/os_support.h"
#include "libswresample/swresample.h"
@ -54,6 +55,7 @@
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
# include "libavfilter/buffersink.h"
# include "libavfilter/buffersrc.h"
# include "libavfilter/vsrc_buffer.h"
#endif
@ -172,6 +174,19 @@ static uint8_t *input_tmp= NULL;
#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
typedef struct FrameBuffer {
uint8_t *base[4];
uint8_t *data[4];
int linesize[4];
int h, w;
enum PixelFormat pix_fmt;
int refcount;
struct InputStream *ist;
struct FrameBuffer *next;
} FrameBuffer;
typedef struct InputStream {
int file_index;
AVStream *st;
@ -189,6 +204,9 @@ typedef struct InputStream {
int is_start; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning;
AVDictionary *opts;
/* a pool of free buffers for decoded data */
FrameBuffer *buffer_pool;
} InputStream;
typedef struct InputFile {
@ -441,6 +459,131 @@ static void reset_options(OptionsContext *o, int is_input)
init_opts();
}
static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf)
{
AVCodecContext *s = ist->st->codec;
FrameBuffer *buf = av_mallocz(sizeof(*buf));
int 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 (!(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:
* bethsoft-vid, 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 (int 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->ist = ist;
*pbuf = buf;
return 0;
}
static void free_buffer_pool(InputStream *ist)
{
FrameBuffer *buf = ist->buffer_pool;
while (buf) {
ist->buffer_pool = buf->next;
av_freep(&buf->base[0]);
av_free(buf);
buf = ist->buffer_pool;
}
}
static void unref_buffer(InputStream *ist, FrameBuffer *buf)
{
av_assert0(buf->refcount);
buf->refcount--;
if (!buf->refcount) {
buf->next = ist->buffer_pool;
ist->buffer_pool = buf;
}
}
static int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
{
InputStream *ist = s->opaque;
FrameBuffer *buf;
int ret, i;
if (!ist->buffer_pool && (ret = alloc_buffer(ist, &ist->buffer_pool)) < 0)
return ret;
buf = ist->buffer_pool;
ist->buffer_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(ist, &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;
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];
}
return 0;
}
static void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
{
InputStream *ist = s->opaque;
FrameBuffer *buf = frame->opaque;
int i;
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
frame->data[i] = NULL;
unref_buffer(ist, buf);
}
static void filter_release_buffer(AVFilterBuffer *fb)
{
FrameBuffer *buf = fb->priv;
av_free(fb);
unref_buffer(buf->ist, buf);
}
#if CONFIG_AVFILTER
static int configure_video_filters(InputStream *ist, OutputStream *ost)
@ -667,6 +810,7 @@ void av_noreturn exit_program(int ret)
av_freep(&input_streams[i].decoded_frame);
av_freep(&input_streams[i].filtered_frame);
av_dict_free(&input_streams[i].opts);
free_buffer_pool(&input_streams[i]);
}
if (vstats_file)

@ -1285,51 +1285,45 @@ typedef struct AVFrame {
uint8_t **extended_data;
/**
* frame timestamp estimated using various heuristics, in stream time base
* Code outside libavcodec should access this field using:
* av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp");
* sample aspect ratio for the video frame, 0/1 if unknown\unspecified
* - encoding: unused
* - decoding: set by libavcodec, read by user.
* - decoding: Read by user.
*/
int64_t best_effort_timestamp;
AVRational sample_aspect_ratio;
/**
* reordered pos from the last AVPacket that has been input into the decoder
* Code outside libavcodec should access this field using:
* av_opt_ptr(avcodec_get_frame_class(), frame, "pkt_pos");
* width and height of the video frame
* - encoding: unused
* - decoding: Read by user.
*/
int64_t pkt_pos;
int width, height;
/**
* reordered sample aspect ratio for the video frame, 0/1 if unknown\unspecified
* Code outside libavcodec should access this field using:
* av_opt_ptr(avcodec_get_frame_class(), frame, "sample_aspect_ratio");
* format of the frame, -1 if unknown or unset
* Values correspond to enum PixelFormat for video frames,
* enum AVSampleFormat for audio)
* - encoding: unused
* - decoding: Read by user.
*/
AVRational sample_aspect_ratio;
int format;
/**
* width and height of the video frame
* frame timestamp estimated using various heuristics, in stream time base
* Code outside libavcodec should access this field using:
* av_opt_ptr(avcodec_get_frame_class(), frame, "width");
* av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp");
* - encoding: unused
* - decoding: Read by user.
* - decoding: set by libavcodec, read by user.
*/
int width, height;
int64_t best_effort_timestamp;
/**
* format of the frame, -1 if unknown or unset
* It should be cast to the corresponding enum (enum PixelFormat
* for video, enum AVSampleFormat for audio)
* reordered pos from the last AVPacket that has been input into the decoder
* Code outside libavcodec should access this field using:
* av_opt_ptr(avcodec_get_frame_class(), frame, "format");
* av_opt_ptr(avcodec_get_frame_class(), frame, "pkt_pos");
* - encoding: unused
* - decoding: Read by user.
*/
int format;
int64_t pkt_pos;
} AVFrame;

@ -165,6 +165,15 @@ static av_cold int avs_decode_init(AVCodecContext * avctx)
return 0;
}
static av_cold int avs_decode_end(AVCodecContext *avctx)
{
AvsContext *s = avctx->priv_data;
if (s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
return 0;
}
AVCodec ff_avs_decoder = {
.name = "avs",
.type = AVMEDIA_TYPE_VIDEO,
@ -172,6 +181,7 @@ AVCodec ff_avs_decoder = {
.priv_data_size = sizeof(AvsContext),
.init = avs_decode_init,
.decode = avs_decode_frame,
.close = avs_decode_end,
.capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"),
};

@ -1098,7 +1098,8 @@ int ff_find_unused_picture(MpegEncContext *s, int shared)
return -1;
}
static void update_noise_reduction(MpegEncContext *s){
static void update_noise_reduction(MpegEncContext *s)
{
int intra, i;
for (intra = 0; intra < 2; intra++) {
@ -1110,13 +1111,17 @@ static void update_noise_reduction(MpegEncContext *s){
}
for (i = 0; i < 64; i++) {
s->dct_offset[intra][i]= (s->avctx->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i]/2) / (s->dct_error_sum[intra][i]+1);
s->dct_offset[intra][i] = (s->avctx->noise_reduction *
s->dct_count[intra] +
s->dct_error_sum[intra][i] / 2) /
(s->dct_error_sum[intra][i] + 1);
}
}
}
/**
* generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded
* generic function for encode/decode called after coding/decoding
* the header and before a frame is coded/decoded.
*/
int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
{
@ -1124,10 +1129,13 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
Picture *pic;
s->mb_skipped = 0;
assert(s->last_picture_ptr==NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3);
assert(s->last_picture_ptr == NULL || s->out_format != FMT_H264 ||
s->codec_id == CODEC_ID_SVQ3);
/* mark & release old frames */
if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f.data[0]) {
if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr &&
s->last_picture_ptr != s->next_picture_ptr &&
s->last_picture_ptr->f.data[0]) {
if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) {
if (s->last_picture_ptr->owner2 == s)
free_frame_buffer(s, s->last_picture_ptr);
@ -1136,9 +1144,12 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
/* if (mpeg124/h263) */
if (!s->encoding) {
for (i = 0; i < s->picture_count; i++) {
if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].f.reference) {
if (s->picture[i].owner2 == s && s->picture[i].f.data[0] &&
&s->picture[i] != s->next_picture_ptr &&
s->picture[i].f.reference) {
if (!(avctx->active_thread_type & FF_THREAD_FRAME))
av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
av_log(avctx, AV_LOG_ERROR,
"releasing zombie picture\n");
free_frame_buffer(s, &s->picture[i]);
}
}
@ -1149,9 +1160,12 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
if (!s->encoding) {
ff_release_unused_pictures(s, 1);
if (s->current_picture_ptr && s->current_picture_ptr->f.data[0] == NULL)
pic= s->current_picture_ptr; //we already have a unused image (maybe it was set before reading the header)
else{
if (s->current_picture_ptr &&
s->current_picture_ptr->f.data[0] == NULL) {
// we already have a unused image
// (maybe it was set before reading the header)
pic = s->current_picture_ptr;
} else {
i = ff_find_unused_picture(s, 0);
if (i < 0)
return i;
@ -1174,11 +1188,14 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
s->current_picture_ptr = pic;
// FIXME use only the vars from current_pic
s->current_picture_ptr->f.top_field_first = s->top_field_first;
if(s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO) {
if (s->codec_id == CODEC_ID_MPEG1VIDEO ||
s->codec_id == CODEC_ID_MPEG2VIDEO) {
if (s->picture_structure != PICT_FRAME)
s->current_picture_ptr->f.top_field_first = (s->picture_structure == PICT_TOP_FIELD) == s->first_field;
s->current_picture_ptr->f.top_field_first =
(s->picture_structure == PICT_TOP_FIELD) == s->first_field;
}
s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame && !s->progressive_sequence;
s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame &&
!s->progressive_sequence;
s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME;
}
@ -1194,19 +1211,24 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
if (!s->dropable)
s->next_picture_ptr = s->current_picture_ptr;
}
/* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
/* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n",
s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
s->last_picture_ptr ? s->last_picture_ptr->f.data[0] : NULL,
s->next_picture_ptr ? s->next_picture_ptr->f.data[0] : NULL,
s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL,
s->pict_type, s->dropable); */
if (s->codec_id != CODEC_ID_H264) {
if ((s->last_picture_ptr == NULL || s->last_picture_ptr->f.data[0] == NULL) &&
(s->pict_type!=AV_PICTURE_TYPE_I || s->picture_structure != PICT_FRAME)){
if ((s->last_picture_ptr == NULL ||
s->last_picture_ptr->f.data[0] == NULL) &&
(s->pict_type != AV_PICTURE_TYPE_I ||
s->picture_structure != PICT_FRAME)) {
if (s->pict_type != AV_PICTURE_TYPE_I)
av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n");
av_log(avctx, AV_LOG_ERROR,
"warning: first frame is no keyframe\n");
else if (s->picture_structure != PICT_FRAME)
av_log(avctx, AV_LOG_INFO, "allocate dummy last picture for field based first keyframe\n");
av_log(avctx, AV_LOG_INFO,
"allocate dummy last picture for field based first keyframe\n");
/* Allocate a dummy frame */
i = ff_find_unused_picture(s, 0);
@ -1222,10 +1244,14 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width);
}
ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 0);
ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 1);
ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
INT_MAX, 0);
ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
INT_MAX, 1);
}
if ((s->next_picture_ptr == NULL || s->next_picture_ptr->f.data[0] == NULL) && s->pict_type == AV_PICTURE_TYPE_B) {
if ((s->next_picture_ptr == NULL ||
s->next_picture_ptr->f.data[0] == NULL) &&
s->pict_type == AV_PICTURE_TYPE_B) {
/* Allocate a dummy frame */
i = ff_find_unused_picture(s, 0);
if (i < 0)
@ -1234,21 +1260,27 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
s->next_picture_ptr->f.key_frame = 0;
if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0)
return -1;
ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 0);
ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 1);
ff_thread_report_progress((AVFrame *) s->next_picture_ptr,
INT_MAX, 0);
ff_thread_report_progress((AVFrame *) s->next_picture_ptr,
INT_MAX, 1);
}
}
if(s->last_picture_ptr) ff_copy_picture(&s->last_picture, s->last_picture_ptr);
if(s->next_picture_ptr) ff_copy_picture(&s->next_picture, s->next_picture_ptr);
if (s->last_picture_ptr)
ff_copy_picture(&s->last_picture, s->last_picture_ptr);
if (s->next_picture_ptr)
ff_copy_picture(&s->next_picture, s->next_picture_ptr);
assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && s->last_picture_ptr->f.data[0]));
assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
s->last_picture_ptr->f.data[0]));
if (s->picture_structure!= PICT_FRAME && s->out_format != FMT_H264) {
int i;
for (i = 0; i < 4; i++) {
if (s->picture_structure == PICT_BOTTOM_FIELD) {
s->current_picture.f.data[i] += s->current_picture.f.linesize[i];
s->current_picture.f.data[i] +=
s->current_picture.f.linesize[i];
}
s->current_picture.f.linesize[i] *= 2;
s->last_picture.f.linesize[i] *= 2;
@ -1258,8 +1290,9 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
s->err_recognition = avctx->err_recognition;
/* set dequantizer, we can't do it during init as it might change for mpeg4
and we can't do it in the header decode as init is not called for mpeg4 there yet */
/* set dequantizer, we can't do it during init as
* it might change for mpeg4 and we can't do it in the header
* decode as init is not called for mpeg4 there yet */
if (s->mpeg_quant || s->codec_id == CODEC_ID_MPEG2VIDEO) {
s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra;
s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter;
@ -1273,7 +1306,6 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
if (s->dct_error_sum) {
assert(s->avctx->noise_reduction && s->encoding);
update_noise_reduction(s);
}
@ -1283,7 +1315,8 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
return 0;
}
/* generic function for encode/decode called after a frame has been coded/decoded */
/* generic function for encode/decode called after a
* frame has been coded/decoded. */
void MPV_frame_end(MpegEncContext *s)
{
int i;
@ -1291,24 +1324,27 @@ void MPV_frame_end(MpegEncContext *s)
// just to make sure that all data is rendered.
if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) {
ff_xvmc_field_end(s);
}else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND))
&& !s->avctx->hwaccel
&& !(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
&& s->unrestricted_mv
&& s->current_picture.f.reference
&& !s->intra_only
&& !(s->flags&CODEC_FLAG_EMU_EDGE)) {
} else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) &&
!s->avctx->hwaccel &&
!(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) &&
s->unrestricted_mv &&
s->current_picture.f.reference &&
!s->intra_only &&
!(s->flags & CODEC_FLAG_EMU_EDGE)) {
int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w;
int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h;
s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize,
s->h_edge_pos, s->v_edge_pos,
EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM);
EDGE_WIDTH, EDGE_WIDTH,
EDGE_TOP | EDGE_BOTTOM);
s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize,
s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
EDGE_TOP | EDGE_BOTTOM);
s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize,
s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
EDGE_TOP | EDGE_BOTTOM);
}
emms_c();
@ -1332,7 +1368,8 @@ void MPV_frame_end(MpegEncContext *s)
if (s->encoding) {
/* release non-reference frames */
for (i = 0; i < s->picture_count; i++) {
if (s->picture[i].f.data[0] && !s->picture[i].f.reference /*&& s->picture[i].type != FF_BUFFER_TYPE_SHARED*/) {
if (s->picture[i].f.data[0] && !s->picture[i].f.reference
/* && s->picture[i].type != FF_BUFFER_TYPE_SHARED */) {
free_frame_buffer(s, &s->picture[i]);
}
}
@ -1346,7 +1383,8 @@ void MPV_frame_end(MpegEncContext *s)
s->avctx->coded_frame = (AVFrame *) s->current_picture_ptr;
if (s->codec_id != CODEC_ID_H264 && s->current_picture.f.reference) {
ff_thread_report_progress((AVFrame*)s->current_picture_ptr, s->mb_height-1, 0);
ff_thread_report_progress((AVFrame *) s->current_picture_ptr,
s->mb_height - 1, 0);
}
}
@ -1357,7 +1395,9 @@ void MPV_frame_end(MpegEncContext *s)
* @param stride stride/linesize of the image
* @param color color of the arrow
*/
static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int stride, int color){
static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey,
int w, int h, int stride, int color)
{
int x, y, fr, f;
sx = av_clip(sx, 0, w - 1);
@ -1388,8 +1428,10 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h
}
buf += sx + sy * stride;
ey -= sy;
if(ey) f= ((ex-sx)<<16)/ey;
else f= 0;
if (ey)
f = ((ex - sx) << 16) / ey;
else
f = 0;
for(y= 0; y <= ey; y++){
x = (y*f) >> 16;
fr = (y*f) & 0xFFFF;
@ -1406,7 +1448,9 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h
* @param stride stride/linesize of the image
* @param color color of the arrow
*/
static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int stride, int color){
static void draw_arrow(uint8_t *buf, int sx, int sy, int ex,
int ey, int w, int h, int stride, int color)
{
int dx,dy;
sx = av_clip(sx, -100, w + 100);
@ -1433,11 +1477,12 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int
}
/**
* Print debuging info for the given picture.
* Print debugging info for the given picture.
*/
void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
if(s->avctx->hwaccel || !pict || !pict->mb_type) return;
void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
{
if (s->avctx->hwaccel || !pict || !pict->mb_type)
return;
if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
int x,y;
@ -1448,11 +1493,13 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
for (x = 0; x < s->mb_width; x++) {
if (s->avctx->debug & FF_DEBUG_SKIP) {
int count = s->mbskip_table[x + y * s->mb_stride];
if(count>9) count=9;
if (count > 9)
count = 9;
av_log(s->avctx, AV_LOG_DEBUG, "%1d", count);
}
if (s->avctx->debug & FF_DEBUG_QP) {
av_log(s->avctx, AV_LOG_DEBUG, "%2d", pict->qscale_table[x + y*s->mb_stride]);
av_log(s->avctx, AV_LOG_DEBUG, "%2d",
pict->qscale_table[x + y * s->mb_stride]);
}
if (s->avctx->debug & FF_DEBUG_MB_TYPE) {
int mb_type = pict->mb_type[x + y * s->mb_stride];
@ -1509,7 +1556,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
}
if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) ||
s->avctx->debug_mv) {
(s->avctx->debug_mv)) {
const int shift = 1 + s->quarter_sample;
int mb_y;
uint8_t *ptr;
@ -1518,12 +1565,16 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
const int width = s->avctx->width;
const int height = s->avctx->height;
const int mv_sample_log2 = 4 - pict->motion_subsample_log2;
const int mv_stride= (s->mb_width << mv_sample_log2) + (s->codec_id == CODEC_ID_H264 ? 0 : 1);
const int mv_stride = (s->mb_width << mv_sample_log2) +
(s->codec_id == CODEC_ID_H264 ? 0 : 1);
s->low_delay = 0; // needed to see the vectors without trashing the buffers
avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,
&h_chroma_shift, &v_chroma_shift);
for (i = 0; i < 3; i++) {
memcpy(s->visualization_buffer[i], pict->data[i], (i==0) ? pict->linesize[i]*height:pict->linesize[i]*height >> v_chroma_shift);
memcpy(s->visualization_buffer[i], pict->data[i],
(i == 0) ? pict->linesize[i] * height:
pict->linesize[i] * height >> v_chroma_shift);
pict->data[i] = s->visualization_buffer[i];
}
pict->type = FF_BUFFER_TYPE_COPY;
@ -1535,20 +1586,26 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
int mb_x;
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
const int mb_index = mb_x + mb_y * s->mb_stride;
if (s->avctx->debug_mv && pict->motion_val) {
if ((s->avctx->debug_mv) && pict->motion_val) {
int type;
for (type = 0; type < 3; type++) {
int direction = 0;
switch (type) {
case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_P))
case 0:
if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_P_FOR)) ||
(pict->pict_type!= AV_PICTURE_TYPE_P))
continue;
direction = 0;
break;
case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
case 1:
if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_FOR)) ||
(pict->pict_type!= AV_PICTURE_TYPE_B))
continue;
direction = 0;
break;
case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
case 2:
if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_BACK)) ||
(pict->pict_type!= AV_PICTURE_TYPE_B))
continue;
direction = 1;
break;
@ -1561,10 +1618,12 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
for (i = 0; i < 4; i++) {
int sx = mb_x * 16 + 4 + 8 * (i & 1);
int sy = mb_y * 16 + 4 + 8 * (i >> 1);
int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1);
int xy = (mb_x * 2 + (i & 1) +
(mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1);
int mx = (pict->motion_val[direction][xy][0] >> shift) + sx;
int my = (pict->motion_val[direction][xy][1] >> shift) + sy;
draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
draw_arrow(ptr, sx, sy, mx, my, width,
height, s->linesize, 100);
}
} else if (IS_16X8(pict->mb_type[mb_index])) {
int i;
@ -1578,7 +1637,8 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
if (IS_INTERLACED(pict->mb_type[mb_index]))
my *= 2;
draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100);
draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
height, s->linesize, 100);
}
} else if (IS_8X16(pict->mb_type[mb_index])) {
int i;
@ -1586,13 +1646,14 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
int sx = mb_x * 16 + 4 + 8 * i;
int sy = mb_y * 16 + 8;
int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1);
int mx=(pict->motion_val[direction][xy][0]>>shift);
int my=(pict->motion_val[direction][xy][1]>>shift);
int mx = pict->motion_val[direction][xy][0] >> shift;
int my = pict->motion_val[direction][xy][1] >> shift;
if (IS_INTERLACED(pict->mb_type[mb_index]))
my *= 2;
draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100);
draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
height, s->linesize, 100);
}
} else {
int sx= mb_x * 16 + 8;
@ -1605,14 +1666,20 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
}
}
if ((s->avctx->debug & FF_DEBUG_VIS_QP) && pict->motion_val) {
uint64_t c= (pict->qscale_table[mb_index]*128/31) * 0x0101010101010101ULL;
uint64_t c = (pict->qscale_table[mb_index] * 128 / 31) *
0x0101010101010101ULL;
int y;
for (y = 0; y < block_height; y++) {
*(uint64_t*)(pict->data[1] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[1])= c;
*(uint64_t*)(pict->data[2] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[2])= c;
*(uint64_t *)(pict->data[1] + 8 * mb_x +
(block_height * mb_y + y) *
pict->linesize[1]) = c;
*(uint64_t *)(pict->data[2] + 8 * mb_x +
(block_height * mb_y + y) *
pict->linesize[2]) = c;
}
}
if((s->avctx->debug&FF_DEBUG_VIS_MB_TYPE) && pict->motion_val){
if ((s->avctx->debug & FF_DEBUG_VIS_MB_TYPE) &&
pict->motion_val) {
int mb_type = pict->mb_type[mb_index];
uint64_t u,v;
int y;
@ -1624,7 +1691,8 @@ v= (int)(128 + r*sin(theta*3.141592/180));
u = v = 128;
if (IS_PCM(mb_type)) {
COLOR(120, 48)
}else if((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || IS_INTRA16x16(mb_type)){
} else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) ||
IS_INTRA16x16(mb_type)) {
COLOR(30, 48)
} else if (IS_INTRA4x4(mb_type)) {
COLOR(90, 48)
@ -1650,36 +1718,45 @@ v= (int)(128 + r*sin(theta*3.141592/180));
u *= 0x0101010101010101ULL;
v *= 0x0101010101010101ULL;
for (y = 0; y < block_height; y++) {
*(uint64_t*)(pict->data[1] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[1])= u;
*(uint64_t*)(pict->data[2] + 8*mb_x + (block_height*mb_y + y)*pict->linesize[2])= v;
*(uint64_t *)(pict->data[1] + 8 * mb_x +
(block_height * mb_y + y) * pict->linesize[1]) = u;
*(uint64_t *)(pict->data[2] + 8 * mb_x +
(block_height * mb_y + y) * pict->linesize[2]) = v;
}
// segmentation
if (IS_8X8(mb_type) || IS_16X8(mb_type)) {
*(uint64_t*)(pict->data[0] + 16*mb_x + 0 + (16*mb_y + 8)*pict->linesize[0])^= 0x8080808080808080ULL;
*(uint64_t*)(pict->data[0] + 16*mb_x + 8 + (16*mb_y + 8)*pict->linesize[0])^= 0x8080808080808080ULL;
*(uint64_t *)(pict->data[0] + 16 * mb_x + 0 +
(16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL;
*(uint64_t *)(pict->data[0] + 16 * mb_x + 8 +
(16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL;
}
if (IS_8X8(mb_type) || IS_8X16(mb_type)) {
for (y = 0; y < 16; y++)
pict->data[0][16*mb_x + 8 + (16*mb_y + y)*pict->linesize[0]]^= 0x80;
pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) *
pict->linesize[0]] ^= 0x80;
}
if (IS_8X8(mb_type) && mv_sample_log2 >= 2) {
int dm = 1 << (mv_sample_log2 - 2);
for (i = 0; i < 4; i++) {
int sx = mb_x * 16 + 8 * (i & 1);
int sy = mb_y * 16 + 8 * (i >> 1);
int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1);
int xy = (mb_x * 2 + (i & 1) +
(mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1);
// FIXME bidir
int32_t *mv = (int32_t *) &pict->motion_val[0][xy];
if(mv[0] != mv[dm] || mv[dm*mv_stride] != mv[dm*(mv_stride+1)])
if (mv[0] != mv[dm] ||
mv[dm * mv_stride] != mv[dm * (mv_stride + 1)])
for (y = 0; y < 8; y++)
pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80;
if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)])
*(uint64_t*)(pict->data[0] + sx + (sy + 4)*pict->linesize[0])^= 0x8080808080808080ULL;
*(uint64_t *)(pict->data[0] + sx + (sy + 4) *
pict->linesize[0]) ^= 0x8080808080808080ULL;
}
}
if(IS_INTERLACED(mb_type) && s->codec_id == CODEC_ID_H264){
if (IS_INTERLACED(mb_type) &&
s->codec_id == CODEC_ID_H264) {
// hmm
}
}
@ -1711,15 +1788,18 @@ static inline int hpel_motion_lowres(MpegEncContext *s,
sx = motion_x & s_mask;
sy = motion_y & s_mask;
src_x += motion_x >> (lowres+1);
src_y += motion_y >> (lowres+1);
src_x += motion_x >> lowres + 1;
src_y += motion_y >> lowres + 1;
src += src_y * stride + src_x;
if( (unsigned)src_x > h_edge_pos - (!!sx) - w
|| (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<<field_based,
src_x, src_y<<field_based, h_edge_pos, v_edge_pos);
if ((unsigned)src_x > h_edge_pos - (!!sx) - w ||
(unsigned)src_y > (v_edge_pos >> field_based) - (!!sy) - h) {
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
(h + 1) << field_based, src_x,
src_y << field_based,
h_edge_pos,
v_edge_pos);
src = s->edge_emu_buffer;
emu = 1;
}
@ -1734,13 +1814,20 @@ static inline int hpel_motion_lowres(MpegEncContext *s,
/* apply one mpeg motion vector to the three components */
static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int field_based, int bottom_field, int field_select,
uint8_t **ref_picture, h264_chroma_mc_func *pix_op,
int motion_x, int motion_y, int h, int mb_y)
uint8_t *dest_y,
uint8_t *dest_cb,
uint8_t *dest_cr,
int field_based,
int bottom_field,
int field_select,
uint8_t **ref_picture,
h264_chroma_mc_func *pix_op,
int motion_x, int motion_y,
int h, int mb_y)
{
uint8_t *ptr_y, *ptr_cb, *ptr_cr;
int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy, uvsx, uvsy;
int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
uvsx, uvsy;
const int lowres = s->avctx->lowres;
const int op_index = FFMIN(lowres-1+s->chroma_x_shift, 2);
const int block_s = 8>>lowres;
@ -1750,7 +1837,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
linesize = s->current_picture.f.linesize[0] << field_based;
uvlinesize = s->current_picture.f.linesize[1] << field_based;
if(s->quarter_sample){ //FIXME obviously not perfect but qpel will not work in lowres anyway
// FIXME obviously not perfect but qpel will not work in lowres anyway
if (s->quarter_sample) {
motion_x /= 2;
motion_y /= 2;
}
@ -1761,15 +1849,16 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
sx = motion_x & s_mask;
sy = motion_y & s_mask;
src_x = s->mb_x*2*block_s + (motion_x >> (lowres+1));
src_y =( mb_y*2*block_s>>field_based) + (motion_y >> (lowres+1));
src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1);
src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1);
if (s->out_format == FMT_H263) {
uvsx = ((motion_x >> 1) & s_mask) | (sx & 1);
uvsy = ((motion_y >> 1) & s_mask) | (sy & 1);
uvsrc_x = src_x >> 1;
uvsrc_y = src_y >> 1;
}else if(s->out_format == FMT_H261){//even chroma mv's are full pel in H261
} else if (s->out_format == FMT_H261) {
// even chroma mv's are full pel in H261
mx = motion_x / 4;
my = motion_y / 4;
uvsx = (2 * mx) & s_mask;
@ -1782,8 +1871,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
my = motion_y / 2;
uvsx = mx & s_mask;
uvsy = my & s_mask;
uvsrc_x = s->mb_x*block_s + (mx >> (lowres+1));
uvsrc_y =( mb_y*block_s>>field_based) + (my >> (lowres+1));
uvsrc_x = s->mb_x * block_s + (mx >> lowres + 1);
uvsrc_y = (mb_y * block_s >> field_based) + (my >> lowres + 1);
} else {
if(s->chroma_x_shift){
//Chroma422
@ -1806,23 +1895,30 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
if( (unsigned)src_x > h_edge_pos - (!!sx) - 2*block_s
|| (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
src_x, src_y<<field_based, h_edge_pos, v_edge_pos);
if ((unsigned) src_x > h_edge_pos - (!!sx) - 2 * block_s ||
(unsigned) src_y > (v_edge_pos >> field_based) - (!!sy) - h) {
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
s->linesize, 17, 17 + field_based,
src_x, src_y << field_based, h_edge_pos,
v_edge_pos);
ptr_y = s->edge_emu_buffer;
if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize;
s->dsp.emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based,
uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1);
s->dsp.emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based,
uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1);
s->dsp.emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9,
9 + field_based,
uvsrc_x, uvsrc_y << field_based,
h_edge_pos >> 1, v_edge_pos >> 1);
s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9,
9 + field_based,
uvsrc_x, uvsrc_y << field_based,
h_edge_pos >> 1, v_edge_pos >> 1);
ptr_cb = uvbuf;
ptr_cr = uvbuf + 16;
}
}
if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
// FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
if (bottom_field) {
dest_y += s->linesize;
dest_cb += s->uvlinesize;
dest_cr += s->uvlinesize;
@ -1853,13 +1949,14 @@ static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
uint8_t *dest_cb, uint8_t *dest_cr,
uint8_t **ref_picture,
h264_chroma_mc_func * pix_op,
int mx, int my){
int mx, int my)
{
const int lowres = s->avctx->lowres;
const int op_index = FFMIN(lowres, 2);
const int block_s = 8 >> lowres;
const int s_mask = (2 << lowres) - 1;
const int h_edge_pos = s->h_edge_pos >> (lowres+1);
const int v_edge_pos = s->v_edge_pos >> (lowres+1);
const int h_edge_pos = s->h_edge_pos >> lowres + 1;
const int v_edge_pos = s->v_edge_pos >> lowres + 1;
int emu = 0, src_x, src_y, offset, sx, sy;
uint8_t *ptr;
@ -1875,15 +1972,16 @@ static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
sx = mx & s_mask;
sy = my & s_mask;
src_x = s->mb_x*block_s + (mx >> (lowres+1));
src_y = s->mb_y*block_s + (my >> (lowres+1));
src_x = s->mb_x * block_s + (mx >> lowres + 1);
src_y = s->mb_y * block_s + (my >> lowres + 1);
offset = src_y * s->uvlinesize + src_x;
ptr = ref_picture[1] + offset;
if (s->flags & CODEC_FLAG_EMU_EDGE) {
if( (unsigned)src_x > h_edge_pos - (!!sx) - block_s
|| (unsigned)src_y > v_edge_pos - (!!sy) - block_s){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
if ((unsigned) src_x > h_edge_pos - (!!sx) - block_s ||
(unsigned) src_y > v_edge_pos - (!!sy) - block_s) {
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
ptr = s->edge_emu_buffer;
emu = 1;
}
@ -1894,7 +1992,8 @@ static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
ptr = ref_picture[2] + offset;
if (emu) {
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
src_x, src_y, h_edge_pos, v_edge_pos);
ptr = s->edge_emu_buffer;
}
pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);
@ -1912,7 +2011,8 @@ static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
* the motion vectors are taken from s->mv and the MV type from s->mv_type
*/
static inline void MPV_motion_lowres(MpegEncContext *s,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
uint8_t *dest_y, uint8_t *dest_cb,
uint8_t *dest_cr,
int dir, uint8_t **ref_picture,
h264_chroma_mc_func *pix_op)
{
@ -1929,15 +2029,18 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
0, 0, 0,
ref_picture, pix_op,
s->mv[dir][0][0], s->mv[dir][0][1], 2*block_s, mb_y);
s->mv[dir][0][0], s->mv[dir][0][1],
2 * block_s, mb_y);
break;
case MV_TYPE_8X8:
mx = 0;
my = 0;
for (i = 0; i < 4; i++) {
hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) * s->linesize)*block_s,
hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) *
s->linesize) * block_s,
ref_picture[0], 0, 0,
(2*mb_x + (i & 1))*block_s, (2*mb_y + (i >>1))*block_s,
(2 * mb_x + (i & 1)) * block_s,
(2 * mb_y + (i >> 1)) * block_s,
s->width, s->height, s->linesize,
s->h_edge_pos >> lowres, s->v_edge_pos >> lowres,
block_s, block_s, pix_op,
@ -1948,7 +2051,8 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
}
if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY))
chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture, pix_op, mx, my);
chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture,
pix_op, mx, my);
break;
case MV_TYPE_FIELD:
if (s->picture_structure == PICT_FRAME) {
@ -1956,28 +2060,33 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
1, 0, s->field_select[dir][0],
ref_picture, pix_op,
s->mv[dir][0][0], s->mv[dir][0][1], block_s, mb_y);
s->mv[dir][0][0], s->mv[dir][0][1],
block_s, mb_y);
/* bottom field */
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
1, 1, s->field_select[dir][1],
ref_picture, pix_op,
s->mv[dir][1][0], s->mv[dir][1][1], block_s, mb_y);
s->mv[dir][1][0], s->mv[dir][1][1],
block_s, mb_y);
} else {
if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){
if (s->picture_structure != s->field_select[dir][0] + 1 &&
s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
ref_picture = s->current_picture_ptr->f.data;
}
}
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
0, 0, s->field_select[dir][0],
ref_picture, pix_op,
s->mv[dir][0][0], s->mv[dir][0][1], 2*block_s, mb_y>>1);
s->mv[dir][0][0],
s->mv[dir][0][1], 2 * block_s, mb_y >> 1);
}
break;
case MV_TYPE_16X8:
for (i = 0; i < 2; i++) {
uint8_t **ref2picture;
if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){
if (s->picture_structure == s->field_select[dir][i] + 1 ||
s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
ref2picture = ref_picture;
} else {
ref2picture = s->current_picture_ptr->f.data;
@ -1986,7 +2095,8 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
0, 0, s->field_select[dir][i],
ref2picture, pix_op,
s->mv[dir][i][0], s->mv[dir][i][1] + 2*block_s*i, block_s, mb_y>>1);
s->mv[dir][i][0], s->mv[dir][i][1] +
2 * block_s * i, block_s, mb_y >> 1);
dest_y += 2 * block_s * s->linesize;
dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
@ -2001,7 +2111,9 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
1, j, j ^ i,
ref_picture, pix_op,
s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], block_s, mb_y);
s->mv[dir][2 * i + j][0],
s->mv[dir][2 * i + j][1],
block_s, mb_y);
}
pix_op = s->dsp.avg_h264_chroma_pixels_tab;
}
@ -2010,19 +2122,22 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
0, 0, s->picture_structure != i + 1,
ref_picture, pix_op,
s->mv[dir][2*i][0],s->mv[dir][2*i][1],2*block_s, mb_y>>1);
s->mv[dir][2 * i][0],s->mv[dir][2 * i][1],
2 * block_s, mb_y >> 1);
// after put we make avg of the same block
pix_op = s->dsp.avg_h264_chroma_pixels_tab;
//opposite parity is always in the same frame if this is second field
// opposite parity is always in the same
// frame if this is second field
if (!s->first_field) {
ref_picture = s->current_picture_ptr->f.data;
}
}
}
break;
default: assert(0);
default:
assert(0);
}
}

@ -604,6 +604,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
*picture = p->frame;
*got_picture_ptr = p->got_frame;
picture->pkt_dts = p->avpkt.dts;
picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
picture->width = avctx->width;
picture->height = avctx->height;
picture->format = avctx->pix_fmt;
/*
* A later call with avkpt->size == 0 may loop over all threads,

@ -1093,6 +1093,8 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
if (ret >= 0 && *got_frame_ptr) {
avctx->frame_number++;
frame->pkt_dts = avpkt->dts;
if (frame->format == AV_SAMPLE_FMT_NONE)
frame->format = avctx->sample_fmt;
}
}
return ret;

@ -21,7 +21,7 @@
#define AVCODEC_VERSION_H
#define LIBAVCODEC_VERSION_MAJOR 53
#define LIBAVCODEC_VERSION_MINOR 47
#define LIBAVCODEC_VERSION_MINOR 48
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \

@ -23,7 +23,7 @@
#include "avcodec.h"
void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
{
dst->pts = src->pts;
dst->pos = src->pkt_pos;
@ -39,6 +39,8 @@ void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
dst->video->key_frame = src->key_frame;
dst->video->pict_type = src->pict_type;
}
return 0;
}
AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame,

@ -36,7 +36,7 @@
* Copy the frame properties of src to dst, without copying the actual
* image data.
*/
void avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
/**
* Create and return a picref reference from the data and properties

@ -27,9 +27,10 @@
#include "libavutil/samplefmt.h"
#include "libavutil/pixfmt.h"
#include "libavutil/rational.h"
#include "libavcodec/avcodec.h"
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 53
#define LIBAVFILTER_VERSION_MINOR 54
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
@ -953,4 +954,12 @@ static inline void avfilter_insert_outpad(AVFilterContext *f, unsigned index,
&f->output_pads, &f->outputs, p);
}
/**
* Copy the frame properties of src to dst, without copying the actual
* image data.
*
* @return 0 on success, a negative number on error.
*/
int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src);
#endif /* AVFILTER_AVFILTER_H */

@ -0,0 +1,38 @@
/*
*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFILTER_BUFFERSRC_H
#define AVFILTER_BUFFERSRC_H
/**
* @file
* Memory buffer source API.
*/
#include "avfilter.h"
/**
* Add a buffer to the filtergraph s.
*
* @param buf buffer containing frame data to be passed down the filtergraph.
* This function will take ownership of buf, the user must not free it.
*/
int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf);
#endif /* AVFILTER_BUFFERSRC_H */

@ -264,6 +264,7 @@ static int movie_get_frame(AVFilterLink *outlink)
/* use pkt_dts if pkt_pts is not available */
movie->picref->pts = movie->frame->pkt_pts == AV_NOPTS_VALUE ?
movie->frame->pkt_dts : movie->frame->pkt_pts;
if (!movie->frame->sample_aspect_ratio.num)
movie->picref->video->sample_aspect_ratio = st->sample_aspect_ratio;
av_dlog(outlink->src,

@ -26,6 +26,7 @@
#include "avfilter.h"
#include "internal.h"
#include "avcodec.h"
#include "buffersrc.h"
#include "vsrc_buffer.h"
#include "libavutil/imgutils.h"
@ -112,6 +113,23 @@ int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter,
return 0;
}
int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
{
BufferSourceContext *c = s->priv;
if (c->picref) {
av_log(s, AV_LOG_ERROR,
"Buffering several frames is not supported. "
"Please consume all available frames before adding a new one.\n"
);
return AVERROR(EINVAL);
}
c->picref = buf;
return 0;
}
#if CONFIG_AVCODEC
#include "avcodec.h"

Loading…
Cancel
Save