aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mpegtsenc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-07-14 02:22:48 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-07-14 02:24:10 +0200
commit80e4fe4063001d0cf468d5f4c7c02ba5b04484b7 (patch)
treeab237b4967339905110c59f6a118bfda9a5a5433 /libavformat/mpegtsenc.c
parent6b61920ab76dc6d85ef462909951923935dd643f (diff)
parentb5849f77095439e994b11c25e6063d443b36c228 (diff)
downloadffmpeg-80e4fe4063001d0cf468d5f4c7c02ba5b04484b7.tar.gz
Merge commit 'b5849f77095439e994b11c25e6063d443b36c228'
* commit 'b5849f77095439e994b11c25e6063d443b36c228': (21 commits) ac3enc: merge AC3MDCTContext with AC3EncodeContext. ac3enc: prefer passing AC3EncodeContext rather than AVCodecContext ac3enc: fix memleak mpeg1video: add CODEC_CAP_SLICE_THREADS. lavf: fix segfault in av_open_input_stream() mpegtsenc: set Random Access indicator on keyframe start packets lavf: Cleanup try_decode_frame() logic. Replace some gotos that lead to single return statements by direct return. build: move tests/seek_test.c to libavformat and reuse generic build rules mxfenc: include needed header for ff_iso8601_to_unix_time() prototype Add a check for strptime(). lavf: factor out conversion of ISO8601 string to unix time wav: parse 'bext' metadata wav: keep parsing until EOF if the input is seekable and we know the size of the data tag wav: Refactor the tag checking into a switch statement wav: make sure neither data_size nor sample_count is negative. wav: refactor the 'fmt ' tag search and parsing. wav: add an option for writing BEXT chunk ffmpeg: get rid of a pointless limit on number of streams. ffmpeg: remove an unused define. ... Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/mpegtsenc.c')
-rw-r--r--libavformat/mpegtsenc.c67
1 files changed, 56 insertions, 11 deletions
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index a7e13e83d5..d1386aa6fa 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -204,6 +204,7 @@ typedef struct MpegTSWriteStream {
int first_pts_check; ///< first pts check needed
int64_t payload_pts;
int64_t payload_dts;
+ int payload_flags;
uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE];
ADTSContext *adts;
} MpegTSWriteStream;
@@ -621,7 +622,7 @@ static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
ts->first_pcr;
}
-static uint8_t* write_pcr_bits(uint8_t *buf, int64_t pcr)
+static int write_pcr_bits(uint8_t *buf, int64_t pcr)
{
int64_t pcr_low = pcr % 300, pcr_high = pcr / 300;
@@ -632,7 +633,7 @@ static uint8_t* write_pcr_bits(uint8_t *buf, int64_t pcr)
*buf++ = pcr_high << 7 | pcr_low >> 8 | 0x7e;
*buf++ = pcr_low;
- return buf;
+ return 6;
}
/* Write a single null transport stream packet */
@@ -668,7 +669,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
*q++ = 0x10; /* Adaptation flags: PCR present */
/* PCR coded into 6 bytes */
- q = write_pcr_bits(q, get_pcr(ts, s->pb));
+ q += write_pcr_bits(q, get_pcr(ts, s->pb));
/* stuffing bytes */
memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
@@ -689,6 +690,39 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts)
*q++ = val;
}
+/* Set an adaptation field flag in an MPEG-TS packet*/
+static void set_af_flag(uint8_t *pkt, int flag)
+{
+ // expect at least one flag to set
+ assert(flag);
+
+ if ((pkt[3] & 0x20) == 0) {
+ // no AF yet, set adaptation field flag
+ pkt[3] |= 0x20;
+ // 1 byte length, no flags
+ pkt[4] = 1;
+ pkt[5] = 0;
+ }
+ pkt[5] |= flag;
+}
+
+/* Extend the adaptation field by size bytes */
+static void extend_af(uint8_t *pkt, int size)
+{
+ // expect already existing adaptation field
+ assert(pkt[3] & 0x20);
+ pkt[4] += size;
+}
+
+/* Get a pointer to MPEG-TS payload (right after TS packet header) */
+static uint8_t *get_ts_payload_start(uint8_t *pkt)
+{
+ if (pkt[3] & 0x20)
+ return pkt + 5 + pkt[4];
+ else
+ return pkt + 4;
+}
+
/* Add a pes header to the front of payload, and segment into an integer number of
* ts packets. The final ts packet is padded using an over-sized adaptation header
* to exactly fill the last ts packet.
@@ -696,7 +730,7 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts)
*/
static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
const uint8_t *payload, int payload_size,
- int64_t pts, int64_t dts)
+ int64_t pts, int64_t dts, int key)
{
MpegTSWriteStream *ts_st = st->priv_data;
MpegTSWrite *ts = s->priv_data;
@@ -741,8 +775,17 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
*q++ = val;
*q++ = ts_st->pid;
ts_st->cc = (ts_st->cc + 1) & 0xf;
- *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
+ *q++ = 0x10 | ts_st->cc; // payload indicator + CC
+ if (key && is_start && pts != AV_NOPTS_VALUE) {
+ // set Random Access for key frames
+ if (ts_st->pid == ts_st->service->pcr_pid)
+ write_pcr = 1;
+ set_af_flag(buf, 0x40);
+ q = get_ts_payload_start(buf);
+ }
if (write_pcr) {
+ set_af_flag(buf, 0x10);
+ q = get_ts_payload_start(buf);
// add 11, pcr references the last byte of program clock reference base
if (ts->mux_rate > 1)
pcr = get_pcr(ts, s->pb);
@@ -750,9 +793,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
pcr = (dts - delay)*300;
if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
- *q++ = 7; /* AFC length */
- *q++ = 0x10; /* flags: PCR present */
- q = write_pcr_bits(q, pcr);
+ extend_af(buf, write_pcr_bits(q, pcr));
+ q = get_ts_payload_start(buf);
}
if (is_start) {
int pes_extension = 0;
@@ -950,20 +992,22 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
// for video and subtitle, write a single pes packet
- mpegts_write_pes(s, st, buf, size, pts, dts);
+ mpegts_write_pes(s, st, buf, size, pts, dts, pkt->flags & AV_PKT_FLAG_KEY);
av_free(data);
return 0;
}
if (ts_st->payload_index + size > DEFAULT_PES_PAYLOAD_SIZE) {
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
- ts_st->payload_pts, ts_st->payload_dts);
+ ts_st->payload_pts, ts_st->payload_dts,
+ ts_st->payload_flags & AV_PKT_FLAG_KEY);
ts_st->payload_index = 0;
}
if (!ts_st->payload_index) {
ts_st->payload_pts = pts;
ts_st->payload_dts = dts;
+ ts_st->payload_flags = pkt->flags;
}
memcpy(ts_st->payload + ts_st->payload_index, buf, size);
@@ -988,7 +1032,8 @@ static int mpegts_write_end(AVFormatContext *s)
ts_st = st->priv_data;
if (ts_st->payload_index > 0) {
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
- ts_st->payload_pts, ts_st->payload_dts);
+ ts_st->payload_pts, ts_st->payload_dts,
+ ts_st->payload_flags & AV_PKT_FLAG_KEY);
}
av_freep(&ts_st->adts);
}