ffmpeg-Zeitbasiskonzept (tbr: Time Base Rate-Videobildrate, tbn: Zeitbasis des Streams, tbc: Zeitbasis der Zeitbasis im Codec-Codec)), DTS und PTS, GOP, I-Frame P-Frame B-Frame-Konzepterklärung

Referenzartikel: Audio- und Videolernbezogene ffmpeg-Zeitstempel (Zeitbasis: TBR, TBN, TBC)

Beispiel:

tbr:25(视频帧率)
tbn:12000(流的时间基)
tbc:50(编解码器的时间基)

1. I-Frame/P-Frame/B-Frame

Ich 帧

Ein I-Frame (intracodiertes Bild, oft auch als Schlüsselbild bezeichnet) enthält vollständige Bildinformationen, ist ein intracodiertes Bild, enthält keine Bewegungsvektoren und muss bei der Dekodierung nicht auf andere Frame-Bilder verweisen. Daher ist es möglich, den Kanal im I-Frame zu wechseln, ohne dass das Bild verloren geht oder nicht dekodiert wird. I-Frame-Bilder werden verwendet, um die Anhäufung und Ausbreitung von Fehlern zu verhindern. In einer geschlossenen GOP (Gruppe von Bildern) muss das erste Bild jeder GOP ein I-Bild sein, und die Daten der aktuellen GOP beziehen sich nicht auf die Daten der vorherigen und vorherigen GOPs.

P-Rahmen

P-Frame (Predictive-coded picture, Predictive-Coding-Image-Frame) ist ein Inter-Frame-Codierungsrahmen, der den vorherigen I-Frame oder P-Frame für die prädiktive Codierung verwendet.

B-Rahmen

B-Frame (Bidirektional vorhergesagtes Bild, bidirektionaler prädiktiver Codierungsbildrahmen) ist ein Inter-Frame-Codierungsrahmen, der den I-Frame oder P-Frame davor und (oder) danach für die bidirektionale Vorhersage verwendet Codierung. B-Frames können nicht als Referenzframes verwendet werden.
B-Frames haben eine höhere Komprimierungsrate, erfordern jedoch mehr Pufferzeit und eine höhere CPU-Auslastung. Daher eignen sich B-Frames für die lokale Speicherung und Video-on-Demand, jedoch nicht für Echtzeitanforderungen . Höheres Live-Streaming-System.

2. DTS und PTS

Konzept

DTS (Decoding Time Stamp, Dekodierungszeitstempel) stellt die Dekodierungszeit des komprimierten Rahmens dar.

Decoding Time Stamp (DTS) wird während des Videokodierungsprozesses generiert. Es wird vom Video-Encoder generiert und in den Videostream eingebettet, um dem Decoder dabei zu helfen, Videobilder richtig zu sequenzieren und zu synchronisieren.
Wenn Sie ffprobe zum Anzeigen von Videoinformationen verwenden, liest dieses Tool den Decodierungszeitstempel, der bereits in der Videodatei vorhanden ist, anstatt ihn während des Decodierungsprozesses selbst zu generieren.
Einfach ausgedrückt wird der Dekodierungszeitstempel vom Encoder generiert und beim Dekodieren oder Abspielen des Videos verwendet. ffprobe wird nur zum Lesen und Anzeigen dieser Informationen verwendet.

PTS (Presentation Time Stamp, Anzeigezeitstempel) stellt die Anzeigezeit des Originalrahmens dar, der nach der Dekodierung des komprimierten Rahmens erhalten wird.
DTS und PTS sind im Audiobereich gleich. In Videos erfordern B-Frames eine bidirektionale Vorhersage und B-Frames hängen von den Frames davor und danach ab. Daher unterscheidet sich die Decodierungsreihenfolge von Videos, die B-Frames enthalten, von der Anzeigereihenfolge, d. h. DTS unterscheidet sich von PTS. Natürlich sind DTS und PTS von Videos ohne B-Frames gleich.

Beispiel

Die folgende Abbildung zeigt als Beispiel ein offenes GOP-Diagramm, um die Dekodierungsreihenfolge und Anzeigereihenfolge von Videostreams zu veranschaulichen:

Fügen Sie hier eine Bildbeschreibung ein

  • Die Erfassungssequenz bezieht sich auf die Reihenfolge, in der der Bildsensor Originalsignale sammelt, um Einzelbilder zu erhalten.
  • Die Codierungsreihenfolge bezieht sich auf die Reihenfolge der vom Encoder codierten Bildrahmen. Die Reihenfolge der Einzelbilder in der lokalen, auf der Festplatte gespeicherten Videodatei ist dieselbe wie die Codierungsreihenfolge. (Hinweis: Kodierungsreihenfolge = Übertragungsreihenfolge = Dekodierungsreihenfolge. Wir verwenden ffprobe, um die Reihenfolge der Videostream-Pakete zu überprüfen, also diese Reihenfolge.
  • Die Übertragungsreihenfolge bezieht sich auf die Reihenfolge der Bildrahmen während der Übertragung des codierten Streams im Netzwerk.
  • Die Decodierungsreihenfolge bezieht sich auf die Reihenfolge, in der der Decoder Bildrahmen decodiert.
  • Die Anzeigereihenfolge bezieht sich auf die Reihenfolge, in der Bildrahmen auf dem Monitor angezeigt werden.

Die Erfassungsreihenfolge ist dieselbe wie die Anzeigereihenfolge. Die Codierungsreihenfolge, Übertragungsreihenfolge und Decodierungsreihenfolge sind gleich.

Nehmen Sie als Beispiel den Rahmen „B[1]“ in der Abbildung. Beim Dekodieren des Rahmens „B[1]“ müssen Sie sich auf den Rahmen „I[0]“ und den Rahmen „P[3]“ beziehen. Daher muss der „P[3]“-Rahmen vor dem „B[1]“-Rahmen dekodiert werden. Dies führt zu einer Inkonsistenz zwischen der Decodierungsreihenfolge und der Anzeigereihenfolge und später angezeigte Frames müssen zuerst decodiert werden.

3. Zeitbasis und Zeitstempel in FFmpeg

3.1 Die Konzepte von Zeitbasis und Zeitstempel

In FFmpeg ist die Zeitbasis (time_base) die Einheit des Zeitstempels (timestamp). Der Zeitstempelwert wird mit der Zeitbasis multipliziert, um den tatsächlichen Zeitwert (in Sekunden usw.) zu erhalten. Wenn beispielsweise die dts eines Videobilds 40, die pts 160 und seine Zeitbasis 1/1000 Sekunden beträgt, kann berechnet werden, dass die Dekodierungszeit dieses Videobilds 40 Millisekunden (40/1000) beträgt Die Anzeigezeit beträgt 160 Millisekunden (160/1000). 1000). Der Typ des Zeitstempels (pts/dts) in FFmpeg ist vom Typ int64_t. Wenn eine Zeitbasis als Taktimpuls betrachtet wird, kann dts/pts als Anzahl von Taktimpulsen betrachtet werden.

3.2 Drei Zeitbasen tbr, tbn und tbc

Konzept

Verschiedene Verpackungsformate haben unterschiedliche Zeitbasen. In verschiedenen Phasen des Audio- und Videoverarbeitungsprozesses von FFmpeg werden auch unterschiedliche Zeitbasen verwendet.
Es gibt drei Zeitbasen in FFmepg. Die gedruckten Werte von tbr, tbn und tbc in der Befehlszeile sind die Kehrwerte dieser drei Zeitbasen:

  • tbn: entspricht der Zeitbasis im Container. Der Wert ist der Kehrwert von AVStream.time_base (am häufigsten verwendet ist er der Kehrwert von AVStream.time_base, der Zeiteinheit von pts und dts in AVPacket, z. B. tbn = 30000).
  • tbc: entspricht der Zeitbasis im Codec. Der Wert ist der Kehrwert von AVCodecContext.time_base
  • tbr: Aus dem Videostream erraten, möglicherweise Bildrate oder Feldrate (zweifache Bildrate)

Testdatei herunterladen (rechtsklicken und speichern unter):tnmil3.flv

Verwenden Sie ffprobe, um das Mediendateiformat wie folgt zu erkennen:

Verwenden Sie ffprobe, um das Mediendateiformat wie folgt zu erkennen:

think@opensuse> ffprobe tnmil3.flv 
ffprobe version 4.1 Copyright (c) 2007-2018 the FFmpeg developers
Input #0, flv, from 'tnmil3.flv':
  Metadata:
    encoder         : Lavf58.20.100
  Duration: 00:00:03.60, start: 0.017000, bitrate: 513 kb/s
    Stream #0:0: Video: h264 (High), yuv420p(progressive), 784x480, 25 fps, 25 tbr, 1k tbn, 50 tbc
    Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 128 kb/s

Anweisungen zu tbr, tbn und tbc, der Originaltext lautet wie folgt aus der FFmpeg-Mailingliste:

Es gibt drei verschiedene Zeitbasen für Zeitstempel in FFmpeg. Die gedruckten
-Werte sind tatsächlich Kehrwerte davon, d. h. 1/tbr, 1/tbn und
1/tbc.
tbn ist meiner Meinung nach die Zeitbasis in AVStream, die aus dem Container stammt. Es wird für alle AVStream-Zeitstempel verwendet. tbc ist die Zeitbasis in AVCodecContext für den Codec, der für einen bestimmten Stream verwendet wird. Es wird für alle AVCodecContext- und zugehörigen Zeitstempel verwendet. tbr wird aus dem Videostream erraten und ist der Wert, den Benutzer sehen möchten wenn sie nach der Videobildrate suchen, außer manchmal, dass sie doppelt so hoch ist wie man aufgrund der Halbbildrate gegenüber der Bildrate erwarten würde.






In FFmpeg gibt es drei verschiedene Zeitbasen für Zeitstempel. Die gedruckten Werte sind tatsächlich die Kehrwerte dieser Zeitbasen, nämlich 1/tbr, 1/tbn und 1/tbc.
tbn ist die Zeitbasis im vom Container abgeleiteten AVStream. Es wird für alle AVStream-Zeitstempel verwendet.
tbc ist die Zeitbasis für den Codec, der im AVCodecContext für den spezifischen Stream verwendet wird. Es wird für alle AVCodecContexts und die zugehörigen Zeitstempel verwendet.
tbr wird aus dem Videostream erraten. Wenn Benutzer die Videobildrate anzeigen, ist dies das, was sie sehen möchten, aber manchmal kann es aufgrund des Unterschieds zwischen Feldrate und Bildrate doppelt so hoch sein viel wie erwartet.

Detaillierte Erläuterung der drei Zeitbasen tbr, tbn und tbc bei der Kapselung und Entkapselung des ffmpeg-Videocodecs

Die folgenden Videoinformationen:

tbr:25(视频帧率)
tbn:12000(流的时间基)
tbc:50(编解码器的时间基)

Fügen Sie hier eine Bildbeschreibung ein

In ffmpeg sind tbr, tbn und tbc Konzepte, die die Videozeitbasis beschreiben. Ihre spezifische Bedeutung ist wie folgt:

  • tbr (Time Base Rate): Dies ist die aus dem Stream abgeleitete Bildrate, die auch als durchschnittliche Bildrate verstanden werden kann. Normalerweise nennen wir dies die Videobildrate.

  • tbn (Zeitbasis in Nanosekunden oder Zeitbasis im Stream): Gibt die Zeitbasis des Streams an, also den Zeitstempel auf Containerebene (z. B. MKV, MP4 usw.). tbn bestimmt, wie Sie den Zeitstempel der Datei in tatsächliche Sekunden konvertieren.

  • tbc (Zeitbasis im Codec): Stellt die Zeitbasis des Codecs dar, also den Zeitstempel auf Codec-Ebene. Beispielsweise können einige Codecs aus Gründen der Komprimierungseffizienz mehrere Frames zusammenpacken. Die Zeitbasis für diese Paketierung wird noch bestätigt.

Der Hauptgrund für den Unterschied zwischen tbr und tbc liegt darin, dass ihr Geltungsbereich und ihre Grundlage unterschiedlich sind. tbr ist die durchschnittliche Bildrate, die aus dem gesamten Stream abgeleitet wird, und tbc ist die Zeitbasis, die der Codec bei der Verarbeitung der Daten verwendet. Die beiden sind möglicherweise nicht genau gleich, da der Codec die Anzahl der verarbeiteten Frames je nach Bedarf ändern kann. In den meisten Fällen ist TBR für Benutzer am wichtigsten, da es die Wiedergabebildrate des Videos darstellt.

3.3 Interne Zeitbasis AV_TIME_BASE

Zusätzlich zu den oben genannten drei Zeitbasen verfügt FFmpeg auch über eine interne Zeitbasis AV_TIME_BASE (und eine gebrochene AV_TIME_BASE_Q).

// Internal time base represented as integer
#define AV_TIME_BASE            1000000

// Internal time base represented as fractional value
#define AV_TIME_BASE_Q          (AVRational){1, AV_TIME_BASE}

AV_TIME_BASE und AV_TIME_BASE_Q werden für die interne Funktionsverarbeitung von FFmpeg verwendet. Der mit dieser Zeitbasis berechnete Zeitwert stellt Mikrosekunden dar.

3.4 Konvertierung der Zeitwertform

av_q2d() konvertiert eine Zeit von der AVRational-Form in die Double-Form. AVRational ist ein Bruchtyp, double ist ein Gleitkommazahlentyp mit doppelter Genauigkeit und die Konvertierungsergebniseinheit ist Sekunden. Den Werten vor und nach der Umrechnung liegt die gleiche Zeitbasis zugrunde, lediglich die Zahlendarstellung ist unterschiedlich.

av_q2d() wird wie folgt implementiert:

/**
 * Convert an AVRational to a `double`.
 * @param a AVRational to convert
 * @return `a` in floating-point form
 * @see av_d2q()
 */
static inline double av_q2d(AVRational a){
    
    
    return a.num / (double) a.den;
}

Die Verwendung von av_q2d() ist wie folgt:

AVStream stream;
AVPacket packet;
packet 播放时刻值:timestamp(单位秒) = packet.pts × av_q2d(stream.time_base);
packet 播放时长值:duration(单位秒) = packet.duration × av_q2d(stream.time_base);

3.5 Zeitbasis-Konvertierungsfunktion

av_rescale_q() wird zur Konvertierung verschiedener Zeitbasen verwendet und dient zum Konvertieren von Zeitwerten von einer Zeitbasis in eine andere.

/**
 * Rescale a 64-bit integer by 2 rational numbers.
 *
 * The operation is mathematically equivalent to `a × bq / cq`.
 *
 * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF.
 *
 * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd()
 */
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;

av_packet_rescale_ts() wird verwendet, um verschiedene Zeitwerte in AVPacket von einer Zeitbasis in eine andere zu konvertieren.

/**
 * Convert valid timing fields (timestamps / durations) in a packet from one
 * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
 * ignored.
 *
 * @param pkt packet on which the conversion will be performed
 * @param tb_src source timebase, in which the timing fields in pkt are
 *               expressed
 * @param tb_dst destination timebase, to which the timing fields will be
 *               converted
 */
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);

3.6 Zeitbasiskonvertierung während der Kapselung (AVStream.time_base, tbn)

Konzept

Die Zeitbasis im Container (AVStream.time_base, tbn in Abschnitt 3.2) ist wie folgt definiert:

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;
    ......
}

AVStream.time_base ist die Zeiteinheit (der Kehrwert von tbn) von pts und dts in AVPacket. Time_base im Eingabestream und Ausgabestream wird wie folgt bestimmt:

  • Für Eingabestreams: Rufen Sie nach dem Öffnen der Eingabedatei avformat_find_stream_info() auf, um die Zeitbasis in jedem Stream abzurufen
  • Für Ausgabestreams: Rufen Sie nach dem Öffnen der Ausgabedatei avformat_write_header() auf, um die Zeitbasis jedes Streams entsprechend dem Kapselungsformat der Ausgabedatei zu ermitteln und in die Ausgabedatei zu schreiben.

Verschiedene Kapselungsformate haben unterschiedliche Zeitbasen. Während des Prozesses der Kapselungsübertragung (Konvertierung eines Kapselungsformats in ein anderes Kapselungsformat) lauten die Codes für die Zeitbasiskonvertierung wie folgt:

av_read_frame(ifmt_ctx, &pkt);
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);

Der folgende Code hat die gleiche Wirkung wie der obige Code:

// 从输入文件中读取 packet
av_read_frame(ifmt_ctx, &pkt);
// 将 packet 中的各时间值从输入流封装格式时间基转换到输出流封装格式时间基
av_packet_rescale_ts(&pkt, in_stream->time_base, out_stream->time_base);

Die Zeitbasen im Stream hierin_stream->time_base und out_stream->time_base sind die Zeitbasen im Container, der in Abschnitt 3.2 beschrieben wird.

Beispiel

Zum Beispiel ist die Zeitbasis des FLV-Verpackungsformats {1,1000} und die Zeitbasis des TS-Verpackungsformats ist {1,90000
Wir schreiben ein Programm zum Konvertieren flv-Verpackungsformat in das ts-Verpackungsformat konvertieren, die ersten vier Frames der Originaldatei (flv) erfassen und den Zeitstempel anzeigen:

think@opensuse> ffprobe -show_frames -select_streams v tnmil3.flv | grep pkt_pts  
ffprobe version 4.1 Copyright (c) 2007-2018 the FFmpeg developers
Input #0, flv, from 'tnmil3.flv':
  Metadata:
    encoder         : Lavf58.20.100
  Duration: 00:00:03.60, start: 0.017000, bitrate: 513 kb/s
    Stream #0:0: Video: h264 (High), yuv420p(progressive), 784x480, 25 fps, 25 tbr, 1k tbn, 50 tbc
    Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 128 kb/s
pkt_pts=80
pkt_pts_time=0.080000
pkt_pts=120
pkt_pts_time=0.120000
pkt_pts=160
pkt_pts_time=0.160000
pkt_pts=200
pkt_pts_time=0.200000

Nehmen Sie dann die ersten vier Frames der konvertierten Datei (ts) und zeigen Sie den Zeitstempel an:

think@opensuse> ffprobe -show_frames -select_streams v tnmil3.ts | grep pkt_pts  
ffprobe version 4.1 Copyright (c) 2007-2018 the FFmpeg developers
Input #0, mpegts, from 'tnmil3.ts':
  Duration: 00:00:03.58, start: 0.017000, bitrate: 619 kb/s
  Program 1 
    Metadata:
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(progressive), 784x480, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x101]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 127 kb/s
pkt_pts=7200
pkt_pts_time=0.080000
pkt_pts=10800
pkt_pts_time=0.120000
pkt_pts=14400
pkt_pts_time=0.160000
pkt_pts=18000
pkt_pts_time=0.200000

Es kann festgestellt werden, dass für dasselbe Videobild die Zeitbasis (tbn) unterschiedlich ist und daher auch der Zeitstempel (pkt_pts) unterschiedlich ist, der berechnete Zeitwert (pkt_pts_time) jedoch derselbe ist.

Schauen Sie sich den Zeitstempel des ersten Frames an und berechnen Sie die Beziehung:80×{1,1000} == 7200×{1,90000} == 0.080000

(Hinweis:{1,1000}Anzeige1/1000)

3.7 Zeitbasiskonvertierung während der Transkodierung (AVCodecContext.time_base, tbc)

Die Zeitbasis im Codec (AVCodecContext.time_base, tbc in Abschnitt 3.2) ist wie folgt definiert:

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.
     * This often, but not always is the inverse of the frame rate or field rate
     * for video. 1/time_base is not the average frame rate if the frame rate is not
     * constant.
     *
     * Like containers, elementary streams also can store timestamps, 1/time_base
     * is the unit in which these timestamps are specified.
     * As example of such codec time base see ISO/IEC 14496-2:2001(E)
     * vop_time_increment_resolution and fixed_vop_rate
     * (fixed_vop_rate == 0 implies that it is different from the framerate)
     *
     * - encoding: MUST be set by user.
     * - decoding: the use of this field for decoding is deprecated.
     *             Use framerate instead.
     */
    AVRational time_base;
    
    ......
}

Der obige Kommentar weist darauf hin, dass AVCodecContext.time_base der Kehrwert der Bildrate (Videobild) ist und der Zeitstempel jedes Bildes um 1 erhöht wird, sodass tbc gleich der Bildrate ist. Während des Kodierungsprozesses sollte dieser Parameter vom Benutzer festgelegt werden. Bei der Dekodierung ist dieser Parameter obsolet und es wird empfohlen, direkt den Kehrwert der Bildrate als Zeitbasis zu verwenden.

Hier ist eine Frage:Laut den Kommentaren hier sollte für einen Videostream mit einer Bildrate von 25 der TBC 25 betragen, der tatsächliche Wert beträgt jedoch 50. Was ist die Erklärung? Ist TBC veraltet und nicht mehr als Referenz nützlich?

Gemäß den Vorschlägen in den Kommentaren verwenden wir im tatsächlichen Gebrauch während des Videodekodierungsprozesses nicht AVCodecContext.time_base, sondern den Kehrwert der Bildrate als Zeitbasis. Während des Videokodierungsprozesses legen wir AVCodecContext.time_base fest zum Kehrwert der Bildrate.

3.7.1 Video-Streaming

Das Video wird Bild für Bild abgespielt, sodass die Zeitbasis des dekodierten ursprünglichen Videobilds 1/Bildrate beträgt.

Verarbeitung der Zeitbasiskonvertierung während der Videodekodierung:

AVFormatContext *ifmt_ctx;
AVStream *in_stream;
AVCodecContext *dec_ctx;
AVPacket packet;
AVFrame *frame;

// 从输入文件中读取编码帧
av_read_frame(ifmt_ctx, &packet);

// 时间基转换
int raw_video_time_base = av_inv_q(dec_ctx->framerate);
av_packet_rescale_ts(packet, in_stream->time_base, raw_video_time_base);

// 解码
avcodec_send_packet(dec_ctx, packet)
avcodec_receive_frame(dec_ctx, frame);

Verarbeitung der Zeitbasiskonvertierung während der Videokodierung:

AVFormatContext *ofmt_ctx;
AVStream *out_stream;
AVCodecContext *dec_ctx;
AVCodecContext *enc_ctx;
AVPacket packet;
AVFrame *frame;

// 编码
avcodec_send_frame(enc_ctx, frame);
avcodec_receive_packet(enc_ctx, packet);

// 时间基转换
packet.stream_index = out_stream_idx;
enc_ctx->time_base = av_inv_q(dec_ctx->framerate);
av_packet_rescale_ts(&opacket, enc_ctx->time_base, out_stream->time_base);

// 将编码帧写入输出媒体文件
av_interleaved_write_frame(o_fmt_ctx, &packet);

3.7.2 Audio-Streaming

Audio wird an Sample-Punkten abgespielt, sodass die Zeitbasis des decodierten Original-Audio-Frames 1/Sample_Rate beträgt

Verarbeitung der Zeitbasiskonvertierung während der Audiodekodierung:

AVFormatContext *ifmt_ctx;
AVStream *in_stream;
AVCodecContext *dec_ctx;
AVPacket packet;
AVFrame *frame;

// 从输入文件中读取编码帧
av_read_frame(ifmt_ctx, &packet);

// 时间基转换
int raw_audio_time_base = av_inv_q(dec_ctx->sample_rate);
av_packet_rescale_ts(packet, in_stream->time_base, raw_audio_time_base);

// 解码
avcodec_send_packet(dec_ctx, packet)
avcodec_receive_frame(dec_ctx, frame);

Verarbeitung der Zeitbasiskonvertierung während der Audiokodierung:

AVFormatContext *ofmt_ctx;
AVStream *out_stream;
AVCodecContext *dec_ctx;
AVCodecContext *enc_ctx;
AVPacket packet;
AVFrame *frame;

// 编码
avcodec_send_frame(enc_ctx, frame);
avcodec_receive_packet(enc_ctx, packet);

// 时间基转换
packet.stream_index = out_stream_idx;
enc_ctx->time_base = av_inv_q(dec_ctx->sample_rate);
av_packet_rescale_ts(&opacket, enc_ctx->time_base, out_stream->time_base);

// 将编码帧写入输出媒体文件
av_interleaved_write_frame(o_fmt_ctx, &packet);

4. Referenzen

[1]. Was bedeutet die Ausgabe von ffmpeg? tbr tbn tbc usw.?
[2]. Grundlegende Konzepte der Videokodierung und -dekodierung, https://www.cnblogs.com/leisure_chn/p/10285829.html
[3]. Hinweise zu ffmpeg zum Verständnis von Zeitstempeln finden Sie unter https://blog.csdn.net/topsluo/article/details/76239136
[4]. Zeit im ffmpeg-Stempel und Zeitbasis, http://www.imooc.com/article/91381
[5]. Detaillierte Erläuterung der Punkte, die an der ffmpeg-Kodierung und -Dekodierung beteiligt sind, http://www.52ffmpeg.com/article/353.html
[6]. PTS- und DTS-Probleme bei Audio- und Videoaufzeichnung, https:/ / blog.csdn.net/zhouyongku/article/details/38510747

Guess you like

Origin blog.csdn.net/Dontla/article/details/127981937