ffmpeg time_base

ffmpeg存在多个时间基准(time_base),对应不同的阶段(结构体),每个time_base具体的值不一样,ffmpeg提供函数在各个time_base中进行切换。搞清楚各个time_base的来源,对于阅读ffmpeg的代码很重要。

一、time_base
1、AVStream(libavformat/avformat.h)

typedef struct AVStream {
    /**
     * This is the fundamental unit of time (in seconds) in terms
     * of which frame timestamps are represented.
     *
     * decoding: set by libavformat
     * encoding: May be set by the caller before avformat_write_header() to
     *           provide a hint to the muxer about the desired timebase. In
     *           avformat_write_header(), the muxer will overwrite this field
     *           with the timebase that will actually be used for the timestamps
     *           written into the file (which may or may not be related to the
     *           user-provided one, depending on the format).
     */
    AVRational time_base;

/**
     * Decoding: pts of the first frame of the stream in presentation order, in stream time base.
     * Only set this if you are absolutely 100% sure that the value you set
     * it to really is the pts of the first frame.
     * This may be undefined (AV_NOPTS_VALUE).
     * @note The ASF header does NOT contain a correct start_time the ASF
     * demuxer must NOT set this.
     */
    int64_t start_time;

/**
     * Decoding: duration of the stream, in stream time base.
     * If a source file does not specify a duration, but does specify
     * a bitrate, this value will be estimated from bitrate and file size.
     */
    int64_t duration;

从上面的信息可以看到,AVStream->time_base单位为秒。

那AVStream->time_base具体的值是多少呢?下面以mpegts_demuxer为例:

static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
                                  uint32_t stream_type, uint32_t prog_reg_desc)
{
avpriv_set_pts_info(st, 33, 1, 90000);

void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
                         unsigned int pts_num, unsigned int pts_den)
{
    AVRational new_tb;
    if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) {
        if (new_tb.num != pts_num)
            av_log(NULL, AV_LOG_DEBUG,
                   "st:%d removing common factor %d from timebase\n",
                   s->index, pts_num / new_tb.num);
    } else
        av_log(NULL, AV_LOG_WARNING,
               "st:%d has too large timebase, reducing\n", s->index);

if (new_tb.num <= 0 || new_tb.den <= 0) {
        av_log(NULL, AV_LOG_ERROR,
               "Ignoring attempt to set invalid timebase %d/%d for st:%d\n",
               new_tb.num, new_tb.den,
               s->index);
        return;
    }
    s->time_base     = new_tb;
    av_codec_set_pkt_timebase(s->codec, new_tb);
    s->pts_wrap_bits = pts_wrap_bits;
}

通过avpriv_set_pts_info(st, 33, 1, 90000)函数,设置AVStream->time_base为1/90000。为什么是90000?因为mpeg的pts、dts都是以90kHz来采样的,所以采样间隔为1/90000秒。

2、AVCodecContext

typedef struct AVCodecContext {
    /**
     * This is the fundamental unit of time (in seconds) in terms
     * of which frame timestamps are represented. For fixed-fps content,
     * timebase should be 1/framerate and timestamp increments should be
     * identically 1.
     * - encoding: MUST be set by user.
     * - decoding: Set by libavcodec.
     */
    AVRational time_base;

从上面的信息可以看到,AVCodecContext->time_base单位同样为秒,不过精度没有AVStream->time_base高,大小为1/framerate。

下面以ffmpeg转码工具为例:

static int transcode_init(void)
{
            if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
                if (ost->filter && !ost->frame_rate.num)
                    ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
                if (ist && !ost->frame_rate.num)
                    ost->frame_rate = ist->framerate;
                if (ist && !ost->frame_rate.num)
                    ost->frame_rate = ist->st->r_frame_rate;
                if (ist && !ost->frame_rate.num) {
                    ost->frame_rate = (AVRational){25, 1};
                    av_log(NULL, AV_LOG_WARNING,
                           "No information "
                           "about the input framerate is available. Falling "
                           "back to a default value of 25fps for output stream #%d:%d. Use the -r option "
                           "if you want a different framerate.\n",
                           ost->file_index, ost->index);
                }
//                    ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
                if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
                    int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
                    ost->frame_rate = ost->enc->supported_framerates[idx];
                }
                if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) {
                    av_reduce(&ost->frame_rate.num, &ost->frame_rate.den,
                              ost->frame_rate.num, ost->frame_rate.den, 65535);
                }
            }

switch (enc_ctx->codec_type) {
            case AVMEDIA_TYPE_VIDEO:
                
                enc_ctx->time_base = av_inv_q(ost->frame_rate);
                if (ost->filter && !(enc_ctx->time_base.num && enc_ctx->time_base.den))
                    enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
                if (   av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
                   && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
                    av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
                                               "Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
                }

首先获取ost->frame_rate,然后计算enc_ctx->time_base = 1/ost->frame_rate。

总结:
    AVStream->time_base比AVCodecContext->time_base精度要高(数值要小),比如AVStream->time_base为1/90000,而AVCodecContext->time_base为1/30(假设frame_rate为30);同样的pts和dts,以AVStream->time_base为单位,数值要比以AVCodecContext->time_base为单位要大。

二、pts、dts
那各个结构下,pts和dts使用哪个time_base来表示呢?

1、AVPacket

typedef struct AVPacket {
    /**
     * Presentation timestamp in AVStream->time_base units; the time at which
     * the decompressed packet will be presented to the user.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     * pts MUST be larger or equal to dts as presentation cannot happen before
     * decompression, unless one wants to view hex dumps. Some formats misuse
     * the terms dts and pts/cts to mean something different. Such timestamps
     * must be converted to true pts/dts before they are stored in AVPacket.
     */
    int64_t pts;
    /**
     * Decompression timestamp in AVStream->time_base units; the time at which
     * the packet is decompressed.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     */
    int64_t dts;

从上面可以看到,AVPacket下的pts和dts以AVStream->time_base为单位(数值比较大)。这也很容易理解,根据mpeg的协议,压缩后或解压前的数据,pts和dts是90kHz时钟的采样值,时间间隔就是AVStream->time_base。

2、AVFrame

typedef struct AVFrame {
    /**
     * Presentation timestamp in time_base units (time when frame should be shown to user).
     */
    int64_t pts;

/**
     * PTS copied from the AVPacket that was decoded to produce this frame.
     */
    int64_t pkt_pts;

/**
     * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used)
     * This is also the Presentation time of this AVFrame calculated from
     * only AVPacket.dts values without pts values.
     */
    int64_t pkt_dts;

注意:
    AVFrame里面的pkt_pts和pkt_dts是拷贝自AVPacket,同样以AVStream->time_base为单位;而pts是为输出(显示)准备的,以AVCodecContex->time_base为单位)。//FIXME

3、InputStream

typedef struct InputStream {
    int file_index;
    AVStream *st;
    AVCodecContext *dec_ctx;
    int64_t       start;     /* time when read started */
    /* predicted dts of the next packet read for this stream or (when there are
     * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */
    int64_t       next_dts;
    int64_t       dts;       ///< dts of the last packet read for this stream (in AV_TIME_BASE units)

int64_t       next_pts;  ///< synthetic pts for the next decode frame (in AV_TIME_BASE units)
    int64_t       pts;       ///< current pts of the decoded frame  (in AV_TIME_BASE units)

从上面可以看到,InputStream下的pts和dts以AV_TIME_BASE为单位(微秒),至于为什么要转化为微妙,可能是为了避免使用浮点数。

4、OutputStream

typedef struct OutputStream {
    int file_index;          /* file index */
    int index;               /* stream index in the output file */
    int source_index;        /* InputStream index */
    AVStream *st;            /* stream in the output file */
    int encoding_needed;     /* true if encoding needed for this stream */
    int frame_number;
    /* input pts and corresponding output pts
       for A/V sync */
    struct InputStream *sync_ist; /* input stream to sync against */
    int64_t sync_opts;       /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number
    /* pts of the first frame encoded for this stream, used for limiting
     * recording time */
    int64_t first_pts;
    /* dts of the last packet sent to the muxer */
    int64_t last_mux_dts;
    AVBitStreamFilterContext *bitstream_filters;
    AVCodecContext *enc_ctx;
    AVCodec *enc;
    int64_t max_frames;
    AVFrame *filtered_frame;

OutputStream涉及音视频同步,结构和InputStream不同,暂时只作记录,不分析。

三、各个time_base之间转换

ffmpeg提供av_rescale_q函数用于time_base之间转换,av_rescale_q(a,b,c)作用相当于执行a*b/c,通过设置b,c的值,可以很方便的实现time_base之间转换。
例如:
1、InputStream(AV_TIME_BASE)到AVPacket(AVStream->time_base)

static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
pkt->dts  = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);

2、AVPacket(AVStream->time_base)到InputStream(AV_TIME_BASE)

static int process_input_packet(InputStream *ist, const AVPacket *pkt)
{

if (pkt->dts != AV_NOPTS_VALUE) {
        ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);

四、后记:
   AVFrame->pts和AVPacket->pts、AVPacket->dts的值,在解码/编码后,会经历短暂的time_base不匹配的情况:

1、解码后

static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
    decoded_frame = ist->decoded_frame;
    pkt->dts  = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);

update_benchmark(NULL);
    ret = avcodec_decode_video2(ist->dec_ctx,
                                decoded_frame, got_output, pkt);

best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame);   
    if(best_effort_timestamp != AV_NOPTS_VALUE)
        ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);

解码后,decoded_frame->pts的值使用AVStream->time_base为单位,后在AVFilter里面转换成以AVCodecContext->time_base为单位。   //FIXME

2、编码后

static void do_video_out(AVFormatContext *s,
                         OutputStream *ost,
                         AVFrame *in_picture)
{
        ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet);    
        if (got_packet) {
            if (debug_ts) {
                av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
                       "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
                       av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base),
                       av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base));
            }

if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
                pkt.pts = ost->sync_opts;

av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);

if (debug_ts) {
                av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
                    "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
                    av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base),
                    av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
            }

frame_size = pkt.size;
            write_frame(s, &pkt, ost);  
            /* if two pass, output log */
            if (ost->logfile && enc->stats_out) {
                fprintf(ost->logfile, "%s", enc->stats_out);
            }
        }

编码后,pkt.pts、pkt.dts使用AVCodecContext->time_base为单位,后通过调用"av_packet_rescale_ts"转换为AVStream->time_base为单位。

转载地址:http://www.cnitblog.com/luofuchong/archive/2014/11/28/89869.html

问题是这样的 用一个 VLC(流媒体客户端) 去请求流媒体服务器上的数据, 但是获得的数据播放速度明显快于1倍速,大概是 timestamp 不对,不知道是服务器的错误,还是客户端解码时出错, 总感觉服务器那边有问题, 由于服务器端是客户端提供的,客户说是我们的问题,我还不知道如何证明是谁的错。

A:RFC3984 规定采用 90000 Hz 的时钟,因此如果编码帧频是 30,那么时间戳间隔就该是 90000 / 30 = 3000,根据抓包来看,似乎时间戳间隔的确是 3000。

时间戳的间隔不固定,比如有的时间戳间隔是 2990 有的是 3002,会导致解析出来的视频快播的效果么

Q:各位大侠好:
我现在正在开发视频实时流播放,简单的过程如下:
采集视频流 -> 视频流转换为Sorenson H.263编码格式   -> 把编码的实时流通过RTMP协议发送 -> flash客户端进行播放。
现在我的时间戳颗粒是这样生成的:
第一帧的时间戳为0;
第二帧的时间戳的算法为:第一个字符编码的当前时间 - 上一帧第一个字符编码的当前时间
根据这个时间颗粒的算法,我在flash客户端播放就会产生延时。
请问各位大侠有什么好的建议或是文档之类的,以前firstime管管建议我看RFC4629文档,但是效果不太明显?
谢谢!

A;时间戳顺序累加就行了,每次加1

Q:最近做了一个捕捉摄像头并保存FLV的小东西,发现转换完毕后的FLV文件,用播放器播放的时候,速度特别快,大概是正常速度的4倍。请问这是怎么回事?网上搜了一下,说是时间戳的问题,可是PTS我跟了,AVPacket的PTS是每帧增长40,time_base为: 25/s.。DTS是个无效值。PTS的计算是根据ffmpeg的例子写的。
pkt.pts= av_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);

1. dts到底需不需要自己计算?
2. 还有播放速度过快的可能原因? 
3. 还有PTS和DTS的具体含义?
int64_t pts;                         ///< presentation time stamp in time_base units
int64_t dts;                         ///< decompression time stamp in time_base units

上面的意思是不是说,播放器根据PTS进行播放。然后DTS是在编码的时候自己设置?

刚用ffmpeg,好些东西不懂,还请大侠多多指教------刚才又试了一下,把time_base降为10帧每秒。播放速度和正常速度接近。但是不知道FLV文件的帧率该设置多少合适。有没有一个权威的说法。

A:我也做摄像头捕捉,跟你出现一样的问题,我自己分析的话,应该是捕捉摄像头的图像的速度只有10帧每秒,但是保存成视频25帧每秒的话播放看起来就非常快,但是我摄像头捕捉设定的是25帧每秒,难道是速度达不到?
反正我还没解决,LZ解决了的话告诉下,

谢谢。暂时认为是摄像头捕捉速率问题。换了一个高清无驱摄像头就好了

Q:在每个音视频数据包中都含有PTS和DTS,一个数据包中应该含有多个数据帧以及音频数据,那么这里的PTS和DTS它是如何来标识数据帧的?PTS和DTS的单位是什么?视频的最小单位是帧,可通过PTS来指定它何时播放,那音频的最小单位是什么?这里的PTS对音频而言它标识的是什么?是这个时间点采样点吗?

在网上找了很久关于音视频编解码的资料,都没有合适的

A:

audio_timebase = av_q2d(fmtctx->streams[audio_index]->time_base);
video_timebase = av_q2d(fmtctx->streams[video_index]->time_base);

last_video_pts = pts * video_timebase;
last_audio_pts = pts * audio_timebase;

timebase就是单位

以audio为基准同步video。只要设置好了 ao 的参数,如sample rate, channels, sample size等, audio驱动就能以正确的速度播放,所以只要程序里write不出大问题的话,这种同步是非常有效的。

在video out里如下做:

pre_time = av_gettime();
gl_vo->vo_display(pic);
after_time = av_gettime();
rest_time = 1000*1000/fps - (after_time - pre_time);

av_diff = last_audio_pts - last_video_pts;

if ( av_diff > 0.2 )
{
            if( av_diff < 0.5 ) rest_time -= rest_time / 4;
            else rest_time -= rest_time / 2;
}
else if ( av_diff < -0.2)
{
            if( av_diff > -0.5 ) rest_time += rest_time / 4;
            else rest_time += rest_time / 2;
}

if ( rest_time > 0 )
    usleep(rest_time);

Q:谢谢kf701的回复,看后明白了不少
这种同步是音频抽样一次就与一帧图像去同步的吗?

A:上面的代码是每display一个picture,就与audio的PTS比较一下,
如果没有audio,只有video,那么video就会以fps显示靠的就是那个 usleep(rest_time)

Q:如何利用AVPacket包里的pts,dts实现音视频同步?声频播放是只管自己播放,视频有一个初始化播放帧率,如何根据AVPacket里的pts,dts还实现两者的同步?
现在我的视频播放一直按原始播放帧率播放,声音有点卡!哪位知道,尽快告知小弟!

A:DTS:decoding time stamp 
PTS:presentation time stamp

Generally the PTS and DTS will only differ when the stream we are playing has B frames in it.

Q:关于b帧和时间戳的问题

我从mpeg2视频中用av_read_frame()读取视频帧并解码,顺序是IPBBPBB...
它们的pts顺序是1423756...现在我要把这个视频再用mpeg2编码,最大b帧数还是2.那么我在编码时是否要将视频数据调整为按显示时间先后的顺序,再交给avcodec_encode_video()编码?即把第2帧放在3、4帧之后,第7帧放在5、6帧之后?

A:你不能这么做,编码器会给你这么做的。如果你有B帧,那么所有的B帧都会被放在缓冲区里直到下一个I/P帧到来

例如:你的输入序列是IBBPBBPBBI

那么输出的序列是

输入I,编码I,输出I

输入B

输入B

输入P,编码P,输出P

编码B,输出B

编码B,输出B

输入P,编码P,输出P

。。。。。。

在解码端所有的P帧都会被放在缓冲力直到下一个I/P真的到来

如:解码I,输出I

解码P,放入缓冲P

解码B,输出B

解码B,输出B

解码P,输出上一次P帧

Q:解码出来的图片的时间戳问题 MPEG一个包中包含有时间戳, 而可能几个包才能解码出一张图象, 也可能一个包能解码出几张图, 请问包中的时间戳与解码出来的图象如何对应上?

A:在ffmpeg中通过parser部件把从 avformat部件取下来的原始包重新“合成”为有仅包含一个完整帧的包。从MPEG2部份的代码中看出,如果“几个包才能解码出一张图象”的话,会取第一个包的PTS和DTS,如果“也可能一个包能解码出几张图”,则会跟据这个包的PTS和DTS通过帧频推算出其它帧的DTS。

Q: ffmpeg的avcodec_decode_video 函数解码时间戳问题?在   VLC 中调用   avcodec_decode_video() 函数进行解码时,AVFrame->pts 时间戳不对,导致我的图像不能够显示?请问有谁知道它的解码原理,这个 PTS 怎么得出的吗?还是外部传入的?

A:     
        is->video_st->codec->reordered_opaque= pkt->pts;
        len1 = avcodec_decode_video(is->video_st->codec,
                                    frame, &got_picture,
                                    pkt->data, pkt->size);

if(   (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
           && frame->reordered_opaque != AV_NOPTS_VALUE)
            pts= frame->reordered_opaque;
        else if(pkt->dts != AV_NOPTS_VALUE)
            pts= pkt->dts;
        else
            pts= 0;
        pts *= av_q2d(is->video_st->time_base);

Q:我贴下   VLC 的代码,(vlc-0.9.8a/modules/codec/avcodec/video.c 文件中)

i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
                                    &b_gotpicture,
                                    p_sys->i_buffer <= 0 && p_sys->b_flush ? NULL : (uint8_t*)p_sys->p_buffer, p_sys-    >i_buffer );

中间省略

取得   PTS ,
       if( p_sys->p_ff_pic->pts )
       {
         printf(" p_sys->p_ff_pic->pts   = %Lx\n",   p_sys->p_ff_pic->pts);
         p_sys->i_pts = p_sys->p_ff_pic->pts;
       }
从   AVFrame 结构中取得   这个 PTS ,但是这个   AVFrame 结构中取得   这个 PTS 从哪里取得的呢?

A:时间戳一般是在编码的时候加入到媒体文件中的,所以在解码时可以从中分析出PTS。

ffmpeg中的时间单位

AV_TIME_BASE

ffmpeg中的内部计时单位(时间基),ffmepg中的所有时间都是于它为一个单位,比如AVStream中的duration即以为着这个流的长度为duration个AV_TIME_BASE。AV_TIME_BASE定义为:

#define         AV_TIME_BASE   1000000

AV_TIME_BASE_Q

ffmpeg内部时间基的分数表示,实际上它是AV_TIME_BASE的倒数。从它的定义能很清楚的看到这点:

#define         AV_TIME_BASE_Q   (AVRational){1, AV_TIME_BASE}

AVRatioal的定义如下:

typedef struct AVRational{
int num; //numerator
int den; //denominator
} AVRational;

ffmpeg提供了一个把AVRatioal结构转换成double的函数:

static inline double av_q2d(AVRational a){
/**
* Convert rational to double.
* @param a rational to convert
**/return a.num / (double) a.den;
}

现在可以根据pts来计算一桢在整个视频中的时间位置:

timestamp(秒) = pts * av_q2d(st->time_base)
 

计算视频长度的方法:

time(秒) = st->duration * av_q2d(st->time_base)
 

这里的st是一个AVStream对象指针。

时间基转换公式

  • timestamp(ffmpeg内部时间戳) = AV_TIME_BASE * time(秒)
  • time(秒) = AV_TIME_BASE_Q * timestamp(ffmpeg内部时间戳)

所以当需要把视频跳转到N秒的时候可以使用下面的方法:

int64_t timestamp = N * AV_TIME_BASE;
2
av_seek_frame(fmtctx, index_of_video, timestamp, AVSEEK_FLAG_BACKWARD);

ffmpeg同样为我们提供了不同时间基之间的转换函数:

int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)

这个函数的作用是计算a * bq / cq,来把时间戳从一个时基调整到另外一个时基。在进行时基转换的时候,我们应该首选这个函数,因为它可以避免溢出的情况发生。

ffmpeg time_base详解相关推荐

  1. FFmpeg入门详解之119:FFmpeg的SDK编程回顾总结并操练

    3.FFmpeg的SDK编程回顾总结并操练 参考课程:"FFmpeg4.3--系列5--SDK二次开发详解与实战" FFmpeg主要框架 FFmpeg骨架:"八大金刚&q ...

  2. 【FFmpeg】ffmpeg命令详解(三)高级选项

    ffmpeg命令详解(三)高级选项 1.-map 2.-ignore_unknown 3.-copy_unknown 4.-map_channel 5.-map_metadata 6.-map_cha ...

  3. 【FFmpeg】ffmpeg命令详解(二)

    ffmpeg命令详解(二) 4.流选择 4.1 自动选择流 4.2 手动选择流 5.命令行选择详解 5.1 命令行选项的值说明: 5.2 流说明符 5.3 通用选项 5.4 主选项 5.5 视频相关选 ...

  4. 【FFmpeg】ffmpeg命令详解(一)

    ffmpeg命令详解(一) 1.命令格式 2.简述 3.详细说明 3.1 过滤器 3.1.1 简单的过滤器图 3.1.2 复杂的过滤器图 3.2 流拷贝 1.命令格式 ffmpeg [global_o ...

  5. ffmpeg命令详解(转)

    一.ffmpeg命令详解 ffmpeg非常强大,轻松几条命令就可以完成你的工作. 把darkdoor.[001-100].jpg序列帧和001.mp3音频文件利用mpeg4编码方式合成视频文件dark ...

  6. FFmpeg入门详解之116:rtsp live555摄像头直播

    rtsp+live555摄像头直播 Live555直播流程简介与演示 第一步,读取摄像头数据 第二步,x264编码 第三步,扩展live555 第四步,vlc或ffplay播放 ffplay -sta ...

  7. FFmpeg入门详解之83:流媒体与直播技术

    流媒体 流媒体又叫流式媒体,它是指商家用一个视频传送服务器(比如:vlc)把节目(比如:ande10.mp4)当成数据包发出,传送到网络上.用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显 ...

  8. FFmpeg入门详解之117:视频监控的架构和流程

    几张架构图带您快速了解视频监控 图一 图二 图三 图四 视频监控系统的简介 视频监控 视频监控是安全防范系统的重要组成部分,英文Cameras and Surveillance.传统的监控系统包括前端 ...

  9. FFmpeg入门详解之121:颜色空间转换RGB和YUV的原理与实战

    5.颜色空间转换RGB和YUV的原理与实战 三种颜色空间模型:RGB.YUV.HSV 一.概述 颜色通常用三个独立的属性来描述,三个独立变量综合作用,自然就构成一个空间坐标,这就是颜色空间. 但被描述 ...

  10. FFmpeg入门详解之122:Qt5 FFmpeg本地摄像头采集预览实战

    6.Qt5+FFmpeg本地摄像头采集预览实战 源码工程:S26_Test2 FFmpeg命令行处理摄像头 ffmpeg -list_devices true -f dshow -i dummy 命令 ...

最新文章

  1. 降低函数之间的耦合度
  2. mac hdmi 不能调整音量_搭配这几个软件,你的 AirPods 在安卓、Mac 上会更好用
  3. 范式青春er,寻找同行的你!
  4. 合工大850参考书_合肥工业大学计算机考研850上岸经验分享
  5. Android开发(4) | 系统权限、MediaPlayer类 和 VideoView类 的应用——播放多媒体文件
  6. mysql5.7 之 sql_mode=only_full_group_by问题
  7. vue中axios的基本使用,天气查询案例
  8. 语音识别数据库成为了人工智能的核心(转发)
  9. 做数据可视化有什么好
  10. 关于快递鸟的顺丰电子面单打印
  11. HTML网页设计结课作业~仿小米商城网站纯HTML模板源码(HTML+CSS)
  12. android 自定义太阳,第一个AOSP安卓10自定义ROM已经可用,并且非常稳定
  13. 火水未濟 (易經大意 韓長庚)
  14. 万彩脑图大师教程 | 万彩脑图大师快捷键指南
  15. uniapp微信小程序实现地图导航
  16. 【AI绘图】来体验了下AI绘图
  17. 组网技术期末预习/复习总结
  18. Unity手游实战:从0开始SLG——本地化篇(二)TMP的优势与缺点
  19. 3.3.3 反相比例运算放大电路
  20. 人生七工具:SWOT、PDCA、6W2H、SMART、WBS、时间管理、OKR

热门文章

  1. 在gfs2中关闭selinux
  2. 使用 SqlDependency 对象缓存数据以提高性能
  3. koa2从搭建项目到实现API
  4. Hexo + coding 博客的搭建和优化
  5. Ubuntu 14.04安装LAMP(Linux,Apache,MySQL,PHP)
  6. Hibernate配置文件,映射文件
  7. 爱不意味这“sorry”
  8. 怀疑Alexa算法调整,清理一批网站
  9. 如何自己实现一个缓存服务
  10. 玩转大数据系列之二:数据分析与处理