1. avformat_alloc_context

/**
* Allocate an AVFormatContext.
* avformat_free_context() can be used to free the context and everything
* allocated by the framework within it.
*/
AVFormatContext *avformat_alloc_context(void)
{
AVFormatContext *ic;
ic = av_malloc(sizeof(AVFormatContext));
if (!ic) return ic;
/* 设置 ic 中各成员的默认值 */
avformat_get_context_defaults(ic); /* internal:
* An opaque field for libavformat internal usage.
* Must not be accessed in any way by callers. */
ic->internal = av_mallocz(sizeof(*ic->internal));
if (!ic->internal) {
avformat_free_context(ic);
return NULL;
}
/* offset:
* 偏移重新映射时间戳为非负值
* 以时间戳为单位表示.
* @see AVStream.mux_ts_offset */
ic->internal->offset = AV_NOPTS_VALUE;
/* raw_packet_buffer_remaining_size:
* raw_packet_buffer 缓存中剩余可用的字节数
* 初值为 2500000 */
ic->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
/* shortest_end:
* 最短的流结束的时间戳 */
ic->internal->shortest_end = AV_NOPTS_VALUE; return ic;
}

首先为 AVFormatContext 结构体分配动态内存,然后调用 avformat_get_context_defaults 函数获取该 AVFormatContext 的默认值。

2. avformat_get_context_defaults

static void avformat_get_context_defaults(AVFormatContext *s)
{
memset(s, 0, sizeof(AVFormatContext)); s->av_class = &av_format_context_class; /**
* A callback for opening new IO streams.
*
* Whenever a muxer or a demuxer needs to open an IO stream (typically from
* avformat_open_input() for demuxers, but for certain formats can happen at
* other times as well), it will call this callback to obtain an IO context.
*/
s->io_open = io_open_default;
/**
* A callback for closing the streams opened with AVFormatContext.io_open().
*/
s->io_close = io_close_default; av_opt_set_defaults(s);
}

首先,s->av_class 指向一个全局静态结构体变量 av_format_context_class,给结构体变量的定义如下.

2.1 av_format_context_class

static const AVClass av_format_context_class = {
/**
* 类的名字,通常它与 AVClass 关联的上下文结构体类型的名字相同。
* 这里类名为"AVFormatContext",说明该 AVClass 关联的上下文结构体为
* AVFormatContext.
*/
.class_name = "AVFormatContext",
/**
* 这里这个函数返回的是 AVFormatContext 中 iformat->name
* 或者 oformat->name 字符串.
*/
.item_name = format_to_name,
/**
* avformat_options 是一个 AVOption 结构体类的数组,
* 该数组中的元素为 AVFormatContext 中的一个个字段,
* 以后可以通过 av_opt_* 系列函数对 AVFormatContext
* 中的字段进行操作。
*/
.option = avformat_options,
.version = LIBAVUTIL_VERSION_INT,
/**
* 返回下一个启用 AVOption 的子项
*/
.child_next = format_child_next,
.child_class_next = format_child_class_next,
.category = AV_CLASS_CATEGORY_MUXER,
.get_category = get_category,
};

2.1.1 format_to_name

static const char* format_to_name(void* ptr)
{
AVFormatContext* fc = (AVFormatContext*) ptr;
if(fc->iformat) return fc->iformat->name;
else if(fc->oformat) return fc->oformat->name;
else return "NULL";
}

返回输入容器格式 iformat 或者输出容器格式 oformat 的名称,若两者都不存在则返回 NULL。

2.1.2

#define OFFSET(x) offsetof(AVFormatContext,x)
/**
* should be NAN but it does not work as it is
* not a constant in glibc as required by ANSI/ISO C
*/
#define DEFAULT 0
// these names are too long to be readable
#define E AV_OPT_FLAG_ENCODING_PARAM
#define D AV_OPT_FLAG_DECODING_PARAM static const AVOption avformat_options[] = {
/**
* AVOption:
* name: 该选项的名称
* help: 该选项对应的一些简短的描述
* offset: 对于命名常量,该值为0;否则为该选项在 AVFormatContext 中的偏移值
* type: 该选项的类型,为 bool,或者常量 const
* default_val:该字段是一个联合体类型,存放的是该选项的默认值
* min: 该选项的最小值
* max:该选项的最大值
* flags:标志该选项的用途,如encoding
* unit: 该选项所属的逻辑单元。非常量选项和相应的命名常量选项共享
* 同一个单元。该字段可能为 NULL。
*/ {"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS,
{.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"},
{"direct", "reduce buffering", 0, AV_OPT_TYPE_CONST,
{.i64 = AVIO_FLAG_DIRECT }, INT_MIN, INT_MAX, D|E, "avioflags"},
{"probesize", "set probing size", OFFSET(probesize),
AV_OPT_TYPE_INT64, {.i64 = 5000000 }, 32, INT64_MAX, D},
{"formatprobesize", "number of bytes to probe file format",
OFFSET(format_probesize), AV_OPT_TYPE_INT, {.i64 = PROBE_BUF_MAX}, 0, INT_MAX-1, D},
{"packetsize", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT,
{.i64 = DEFAULT }, 0, INT_MAX, E},
{"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS,
{.i64 = AVFMT_FLAG_FLUSH_PACKETS | AVFMT_FLAG_AUTO_BSF },
INT_MIN, INT_MAX, D|E, "fflags"},
{"flush_packets", "reduce the latency by flushing out packets immediately",
0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FLUSH_PACKETS },
INT_MIN, INT_MAX, E, "fflags"},
{"ignidx", "ignore index", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_IGNIDX }, INT_MIN, INT_MAX, D, "fflags"},
{"genpts", "generate pts", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_GENPTS }, INT_MIN, INT_MAX, D, "fflags"},
{"nofillin", "do not fill in missing values that can be exactly calculated",
0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOFILLIN }, INT_MIN, INT_MAX, D, "fflags"},
{"noparse", "disable AVParsers, this needs nofillin too", 0,
AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOPARSE }, INT_MIN, INT_MAX, D, "fflags"},
{"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNDTS },
INT_MIN, INT_MAX, D, "fflags"},
{"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"},
{"sortdts", "try to interleave outputted packets by dts", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_SORT_DTS }, INT_MIN, INT_MAX, D, "fflags"},
#if FF_API_LAVF_KEEPSIDE_FLAG
{"keepside", "don't merge side data", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"},
#endif
{"fastseek", "fast but inaccurate seeks", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_FAST_SEEK }, INT_MIN, INT_MAX, D, "fflags"},
{"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST,
{.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"},
{"nobuffer", "reduce the latency introduced by optional buffering", 0,
AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"},
{"seek2any", "allow seeking to non-keyframes on demuxer level when supported",
OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D},
{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST,
{ .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
{"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST,
{ .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" },
{"autobsf", "add needed bsfs automatically (delays header until each "
"stream's first packet is written)", 0, AV_OPT_TYPE_CONST,
{ .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" },
{"analyzeduration", "specify how many microseconds are analyzed to probe the input",
OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
{"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
{"indexmem", "max memory used for timestamp index (per stream)",
OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D},
/* defaults to 1s of 15fps 352x288 YUYV422 video */
{"rtbufsize", "max memory used for buffering real-time frames",
OFFSET(max_picture_buffer), AV_OPT_TYPE_INT, {.i64 = 3041280 }, 0, INT_MAX, D},
{"fdebug", "print specific debug info", OFFSET(debug),
AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, E|D, "fdebug"},
{"ts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_FDEBUG_TS },
INT_MIN, INT_MAX, E|D, "fdebug"},
{"max_delay", "maximum muxing or demuxing delay in microseconds",
OFFSET(max_delay), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, E|D},
{"start_time_realtime", "wall-clock time when stream begins (PTS==0)",
OFFSET(start_time_realtime), AV_OPT_TYPE_INT64,
{.i64 = AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, E},
{"fpsprobesize", "number of frames used to probe fps",
OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX-1, D},
{"audio_preload", "microseconds by which audio packets should be interleaved earlier",
OFFSET(audio_preload), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},
{"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},
{"chunk_size", "size in bytes for each chunk", OFFSET(max_chunk_size),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},
/* this is a crutch for avconv, since it cannot deal with identically
* named options in different contexts. to be removed when avconv is fixed */
{"f_err_detect", "set error detection flags (deprecated; use err_detect, save via avconv)",
OFFSET(error_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK },
INT_MIN, INT_MAX, D, "err_detect"},
{"err_detect", "set error detection flags", OFFSET(error_recognition),
AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST,
{.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, D, "err_detect"},
{"bitstream", "detect bitstream specification deviations", 0,
AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, D, "err_detect"},
{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST,
{.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, D, "err_detect"},
{"explode", "abort decoding on minor error detection", 0,
AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"},
{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST,
{.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, D, "err_detect"},
{"careful", "consider things that violate the spec, are fast to check and "
"have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST,
{.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"},
{"compliant", "consider all spec non compliancies as errors", 0,
AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"},
{"aggressive", "consider things that a sane encoder shouldn't do as an error",
0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE },
INT_MIN, INT_MAX, D, "err_detect"},
{"use_wallclock_as_timestamps", "use wallclock as timestamps",
OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D},
{"skip_initial_bytes", "set number of bytes to skip before reading header and frames",
OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX-1, D},
{"correct_ts_overflow", "correct single timestamp overflows",
OFFSET(correct_ts_overflow), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, D},
{"flush_packets", "enable flushing of the I/O context after each packet",
OFFSET(flush_packets), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E},
{"metadata_header_padding", "set number of bytes to be written as "
"padding in a metadata header", OFFSET(metadata_header_padding),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, E},
{"output_ts_offset", "set output timestamp offset",
OFFSET(output_ts_offset), AV_OPT_TYPE_DURATION,
{.i64 = 0}, -INT64_MAX, INT64_MAX, E},
{"max_interleave_delta", "maximum buffering duration for interleaving",
OFFSET(max_interleave_delta), AV_OPT_TYPE_INT64,
{ .i64 = 10000000 }, 0, INT64_MAX, E },
{"f_strict", "how strictly to follow the standards (deprecated; "
"use strict, save via avconv)", OFFSET(strict_std_compliance),
AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"},
{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance),
AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"},
{"very", "strictly conform to a older more strict version of the spec or reference software",
0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT },
INT_MIN, INT_MAX, D|E, "strict"},
{"strict", "strictly conform to all the things in the spec "
"no matter what the consequences",
0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, D|E, "strict"},
{"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL },
INT_MIN, INT_MAX, D|E, "strict"},
{"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST,
{.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, D|E, "strict"},
{"experimental", "allow non-standardized experimental variants", 0, AV_OPT_TYPE_CONST,
{.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, D|E, "strict"},
{"max_ts_probe", "maximum number of packets to read while waiting "
"for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT,
{ .i64 = 50 }, 0, INT_MAX, D },
{"avoid_negative_ts", "shift timestamps so they start at 0",
OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT,
{.i64 = -1}, -1, 2, E, "avoid_negative_ts"},
{"auto", "enabled when required by target format",
0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_AUTO },
INT_MIN, INT_MAX, E, "avoid_negative_ts"},
{"disabled", "do not change timestamps",
0, AV_OPT_TYPE_CONST, {.i64 = 0 },
INT_MIN, INT_MAX, E, "avoid_negative_ts"},
{"make_non_negative", "shift timestamps so they are non negative",
0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE },
INT_MIN, INT_MAX, E, "avoid_negative_ts"},
{"make_zero", "shift timestamps so they start at 0",
0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_ZERO },
INT_MIN, INT_MAX, E, "avoid_negative_ts"},
{"dump_separator", "set information dump field separator",
OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "},
CHAR_MIN, CHAR_MAX, D|E},
{"codec_whitelist", "List of decoders that are allowed to be used",
OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },
CHAR_MIN, CHAR_MAX, D },
{"format_whitelist", "List of demuxers that are allowed to be used",
OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },
CHAR_MIN, CHAR_MAX, D },
{"protocol_whitelist", "List of protocols that are allowed to be used",
OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING,
{ .str = NULL }, CHAR_MIN, CHAR_MAX, D },
{"protocol_blacklist", "List of protocols that are not allowed to be used",
OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING,
{ .str = NULL }, CHAR_MIN, CHAR_MAX, D },
{"max_streams", "maximum number of streams", OFFSET(max_streams),
AV_OPT_TYPE_INT, { .i64 = 1000 }, 0, INT_MAX, D },
{NULL},
};

2.1.3 format_child_next

/**
* Return next AVOptions-enabled child or NULL
*/
static void *format_child_next(void *obj, void *prev)
{
AVFormatContext *s = obj;
/**
* s->priv_data: 这是一个支持 AVOption 的结构体,
* 当且仅当 iformat/oformat.priv_class 不为 NULL 的时候.
*/
if (!prev && s->priv_data &&
((s->iformat && s->iformat->priv_class) ||
s->oformat && s->oformat->priv_class))
return s->priv_data;
if (s->pb && s->pb->av_class && prev != s->pb)
return s->pb;
return NULL;
}

2.1.4 format_child_class_next

/**
* Return an AVClass corresponding to the next potential
* AVOptions-enabled child.
*
* The difference between child_next and this is that
* child_next iterates over _already existing_ objects, while
* child_class_next iterates over _all possible_ children.
*/
static const AVClass *format_child_class_next(const AVClass *prev)
{
AVInputFormat *ifmt = NULL;
AVOutputFormat *ofmt = NULL; if (!prev)
return &ff_avio_class; /* 遍历 AVInputFormat 链表,找到与 prev 相等的
* ifmt->priv_class */
while ((ifmt = av_iformat_next(ifmt)))
if (ifmt->priv_class == prev)
break; /* 若遍历完 AVInputFormat 链表都没有直到与 prev 相等的一个
* ifmt,则遍历 AVOutputFormat 链表 */
if (!ifmt)
while ((ofmt = av_oformat_next(ofmt)))
if (ofmt->priv_class == prev)
break;
if (!ofmt)
while (ifmt = av_iformat_next(ifmt))
if (ifmt->priv_class)
return ifmt->priv_class; while (ofmt = av_oformat_next(ofmt))
if (ofmt->priv_class)
return ofmt->priv_class; return NULL;
}

2.1.5 get_category

static AVClassCategory get_category(void *ptr)
{
AVFormatContext* s = ptr;
if(s->iformat) return AV_CLASS_CATEGORY_DEMUXER;
else return AV_CLASS_CATEGORY_MUXER;
}

回到 avformat_get_context_defaults 函数中,接着使 s->io_open 指向 io_open_default 函数。

2.2 io_open_default

/*
* A callback for opening new IO streams.
*
* Whenever a muxer or a demuxer needs to open an IO stream (typically from
* avformat_open_input() for demuxers, but for certain formats can happen at
* other times as well), it will call this callback to obtain an IO context.
*
* @param s the format context
* @param pb on success, the newly opened IO context should be returned here
* @param url the url to open
* @param flags a combination of AVIO_FLAG_*
* @param options a dictionary of additional options, with the same
* semantics as in avio_open2()
* @return 0 on success, a negative AVERROR code on failure
*
* @note Certain muxers and demuxers do nesting, i.e. they open one or more
* additional internal format contexts. Thus the AVFormatContext pointer
* passed to this callback may be different from the one facing the caller.
* It will, however, have the same 'opaque' field.
*/
static int io_open_default(AVFormatContext *s, AVIOContext **pb,
const char *url, int flags, AVDictionary **options)
{
int loglevel; if (!strcmp(url, s->filename) ||
s->iformat && !strcmp(s->iformat->name, "image2") ||
s->oformat && !strcmp(s->oformat->name, "image2")
) {
loglevel = AV_LOG_DEBUG;
} else
loglevel = AV_LOG_INFO; av_log(s, loglevel, "Opening \'%s\' for %s\n",
url, flags & AVIO_FLAG_WRITE ? "writing" : "reading"); #if FF_API_OLD_OPEN_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
if (s->open_cb)
return s->open_cb(s, pb, url, flags, &s->interrupt_callback, options);
FF_ENABLE_DEPRECATION_WARNINGS
#endif return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback,
options, s->protocol_whitelist, s->protocol_blacklist);
}

2.3 io_close_default

/**
* A callback for closing the streams opened with AVFormatContext.io_open().
*/
static void io_close_default(AVFormatContext *s, AVIOContext *pb)
{
avio_close(pb);
}

2.4 av_opt_set_defaults

该函数是将 s->av_class 中的成员 options 数组中保存的默认值设置到该 s(这里即 AVFormatContext)中的对应字段。具体分析可参考 FFmpeg之AVClass与AVOption

FFmpeg之avformat_alloc_context()的更多相关文章

  1. ffmpeg 内存读写相关

    需要的解码的视频数据在一段内存中.例如,通过其他系统送来的视频数据.同样,有的时候编码后的视频数据也未必要保存成一个文件.例如,要求将编码后的视频数据送给其他的系统进行下一步的处理.以上两种情况就要求 ...

  2. 学习FFmpeg API

    ffmpeg是编解码的利器,用了很久,以前看过dranger 的教程,非常精彩,受益颇多,是学习ffmpeg api很好的材料.可惜的是其针对的ffmpeg版本已经比较老了,而ffmpeg的更新又很快 ...

  3. ffmpeg入门

    总入口 http://blog.csdn.net/leixiaohua1020/article/details/15811977 各结构体介绍 http://blog.csdn.net/leixiao ...

  4. [原]如何在Android用FFmpeg+SDL2.0解码声音

    关于如何在Android上用FFmpeg+SDL2.0解码显示图像参考[原]如何在Android用FFmpeg+SDL2.0解码显示图像 ,本文是基于上述文章和[原]零基础学习视频解码之解码声音 来移 ...

  5. [原]如何在Android用FFmpeg+SDL2.0解码显示图像

    如何在Android上使用FFmpeg解码图像参考文章[原]如何在Android用FFmpeg解码图像 ,如何在Android上使用SDL2.0来显示图像参考[原]零基础学习SDL开发之在Androi ...

  6. [原]如何在Android用FFmpeg解码图像

    前一篇[原]如何用Android NDK编译FFmpeg 我们知道了如何使用NDK来编译Android平台下使用的FFmpeg动态库.这篇文章我们就可以使用Android下的JNI来调用FFMpeg进 ...

  7. FFmpeg源代码结构图

    转自:http://blog.csdn.net/leixiaohua1020/article/details/44220151 FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码 ...

  8. ffmpeg 发布hls流

    本来主要讲述如何利用ffmpeg将输入视频流通过转码的方式转成m3u8文件.如何通过http的方法将切边推送给客户端,不在本文中讲述. 输入视频流可以是rtsp流,也可以是http,还可以是文件等等. ...

  9. [转载] ffmpeg超详细综合教程——摄像头直播

    本文的示例将实现:读取PC摄像头视频数据并以RTMP协议发送为直播流.示例包含了 1.ffmpeg的libavdevice的使用 2.视频解码.编码.推流的基本流程 具有较强的综合性. 要使用liba ...

随机推荐

  1. Django中 auto_now_add 和 auto_now 的区别

    auto_now_add = True #创建时添加的时间 修改数据时,不会发生改变 auto_now = True #修改数据的时间,每次修改都会有变动 ........

  2. JavaScript 的查询机制——LHS 与 RHS

    JavaScript 引擎在查找一个变量的时候,有两种查找机制:LHS 和 RHS. RHS 的查询是简单地查找到某个变量的值,而 LHS 则是试图找到变量的容器的本身. 一个简单的例子:当我们执行 ...

  3. 十三:MVC-HTML辅助方法-输出表单

    ASP.NET MVC框架内置多个表单相关的HTML辅助方法 HTML辅助方法 说明 Html.BeginForm() 输出<form>标签 Html.CheckBox() 输出<i ...

  4. Hadoop_29_MapReduce_计数器应用

    在实际生产代码中,常常需要将数据处理过程中遇到的不合规数据行进行全局计数,类似这种需求可以借助mapreduce框架中 提供的全局计数器来实现 示例代码如下: public class MultiOu ...

  5. [Abp vNext微服务实践] - vue-element-admin登录二

    简介: Vue Element Admin是基于vue.element ui开发的后台管理ui,abp vNext是abp新一代微服务框架.本篇将会介绍如何改造Vue Element Admin权限验 ...

  6. rdb和aof二种持久化方式对比(Redis)

    我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的 企业级redis集群架构:海量数据.高并发.高可用 持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面去 比如你re ...

  7. vue-cli3项目中使用CDN

    1.html 中引入 echarts         html中添加script标签如下:         <script src="//cdn.bootcss.com/echarts ...

  8. Mysql的mysqldump详解

    一.导出 1.1 导出表结构及数据 mysqldump -uroot -p --set-gtid-purged=OFF database table1 table2 > mysqldump.sq ...

  9. 实用:Java基础流计算

    java的流不常用,每次学习完都懂,过了一段时间就全忘了... 记录下一点实用的东西... 需求: 截取文件的前250kb内容 public static void main(String[] arg ...

  10. PHP判断是否有Get参数的方法

    PHP如何判断是否有Get参数,方法很简单,一个函数就可以搞定,需要的朋友可以参考下 if(is_array($_GET)&&count($_GET)>0)//判断是否有Get参 ...