uint8_t id;
int max_buffer_size; /* in bytes */
int buffer_index;
- PacketDesc *predecode_packet;
+ PacketDesc *predecode_packet; /* start of packet queue */
+ PacketDesc *last_packet; /* end of packet queue */
PacketDesc *premux_packet;
- PacketDesc **next_packet;
int packet_number;
uint8_t lpcm_header[3];
int lpcm_align;
int preload;
} MpegMuxContext;
-extern AVOutputFormat ff_mpeg1vcd_muxer;
-extern AVOutputFormat ff_mpeg2dvd_muxer;
-extern AVOutputFormat ff_mpeg2svcd_muxer;
-extern AVOutputFormat ff_mpeg2vob_muxer;
+extern const AVOutputFormat ff_mpeg1vcd_muxer;
+extern const AVOutputFormat ff_mpeg2dvd_muxer;
+extern const AVOutputFormat ff_mpeg2svcd_muxer;
+extern const AVOutputFormat ff_mpeg2vob_muxer;
static int put_pack_header(AVFormatContext *ctx, uint8_t *buf,
int64_t timestamp)
if (ctx->packet_size < 20 || ctx->packet_size > (1 << 23) + 10) {
av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n",
ctx->packet_size);
- goto fail;
+ return AVERROR(EINVAL);
}
s->packet_size = ctx->packet_size;
} else
st = ctx->streams[i];
stream = av_mallocz(sizeof(StreamInfo));
if (!stream)
- goto fail;
+ return AVERROR(ENOMEM);
st->priv_data = stream;
avpriv_set_pts_info(st, 64, 1, 90000);
stream->id = ac3_id++;
} else if (st->codecpar->codec_id == AV_CODEC_ID_DTS) {
stream->id = dts_id++;
- } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ||
- st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) {
- if (st->codecpar->bits_per_coded_sample != 16) {
- av_log(ctx, AV_LOG_ERROR, "Only 16 bit LPCM streams can be muxed.\n");
- goto fail;
- }
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) {
stream->id = lpcm_id++;
for (j = 0; j < 4; j++) {
if (lpcm_freq_tab[j] == st->codecpar->sample_rate)
for (sr = 0; sr < 4; sr++)
av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]);
av_log(ctx, AV_LOG_INFO, "\n");
- goto fail;
+ return AVERROR(EINVAL);
}
if (st->codecpar->channels > 8) {
av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n");
- goto fail;
+ return AVERROR(EINVAL);
}
stream->lpcm_header[0] = 0x0c;
stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4);
stream->lpcm_header[2] = 0x80;
stream->lpcm_align = st->codecpar->channels * 2;
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) {
+ int freq;
+
+ switch (st->codecpar->sample_rate) {
+ case 48000: freq = 0; break;
+ case 96000: freq = 1; break;
+ case 44100: freq = 2; break;
+ case 32000: freq = 3; break;
+ default:
+ av_log(ctx, AV_LOG_ERROR, "Unsupported sample rate.\n");
+ return AVERROR(EINVAL);
+ }
+
+ stream->lpcm_header[0] = 0x0c;
+ stream->lpcm_header[1] = (freq << 4) |
+ (((st->codecpar->bits_per_coded_sample - 16) / 4) << 6) |
+ st->codecpar->channels - 1;
+ stream->lpcm_header[2] = 0x80;
+ stream->id = lpcm_id++;
+ stream->lpcm_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8;
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_MLP ||
+ st->codecpar->codec_id == AV_CODEC_ID_TRUEHD) {
+ av_log(ctx, AV_LOG_ERROR, "Support for muxing audio codec %s not implemented.\n",
+ avcodec_get_name(st->codecpar->codec_id));
+ return AVERROR_PATCHWELCOME;
+ } else if (st->codecpar->codec_id != AV_CODEC_ID_MP1 &&
+ st->codecpar->codec_id != AV_CODEC_ID_MP2 &&
+ st->codecpar->codec_id != AV_CODEC_ID_MP3) {
+ av_log(ctx, AV_LOG_ERROR, "Unsupported audio codec. Must be one of mp1, mp2, mp3, 16-bit pcm_dvd, pcm_s16be, ac3 or dts.\n");
+ return AVERROR(EINVAL);
} else {
stream->id = mpa_id++;
}
}
stream->fifo = av_fifo_alloc(16);
if (!stream->fifo)
- goto fail;
+ return AVERROR(ENOMEM);
}
bitrate = 0;
audio_bitrate = 0;
s->system_header_size = get_system_header_size(ctx);
s->last_scr = AV_NOPTS_VALUE;
return 0;
-
-fail:
- for (i = 0; i < ctx->nb_streams; i++)
- av_freep(&ctx->streams[i]->priv_data);
- return AVERROR(ENOMEM);
}
static inline void put_timestamp(AVIOContext *pb, int id, int64_t timestamp)
for (i = 0; i < zero_trail_bytes; i++)
avio_w8(ctx->pb, 0x00);
- avio_flush(ctx->pb);
+ avio_write_marker(ctx->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
s->packet_number++;
s->vcd_padding_bytes_written += s->packet_size;
- avio_flush(ctx->pb);
+ avio_write_marker(ctx->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
/* increasing the packet number is correct. The SCR of the following packs
* is calculated from the packet_number and it has to include the padding
}
stream->buffer_index -= pkt_desc->size;
stream->predecode_packet = pkt_desc->next;
+ if (!stream->predecode_packet)
+ stream->last_packet = NULL;
av_freep(&pkt_desc);
}
}
StreamInfo *stream = st->priv_data;
int64_t pts, dts;
PacketDesc *pkt_desc;
- int preload;
+ int preload, ret;
const int is_iframe = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
(pkt->flags & AV_PKT_FLAG_KEY);
av_log(ctx, AV_LOG_TRACE, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n",
dts / 90000.0, pts / 90000.0, pkt->flags,
pkt->stream_index, pts != AV_NOPTS_VALUE);
- if (!stream->premux_packet)
- stream->next_packet = &stream->premux_packet;
- *stream->next_packet =
- pkt_desc = av_mallocz(sizeof(PacketDesc));
- if (!pkt_desc)
- return AVERROR(ENOMEM);
- pkt_desc->pts = pts;
- pkt_desc->dts = dts;
if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) {
if (size < 3) {
size -= 3;
}
+ pkt_desc = av_mallocz(sizeof(PacketDesc));
+ if (!pkt_desc)
+ return AVERROR(ENOMEM);
+ if (!stream->predecode_packet) {
+ stream->predecode_packet = pkt_desc;
+ } else
+ stream->last_packet->next = pkt_desc;
+ stream->last_packet = pkt_desc;
+ if (!stream->premux_packet)
+ stream->premux_packet = pkt_desc;
+ pkt_desc->pts = pts;
+ pkt_desc->dts = dts;
pkt_desc->unwritten_size =
pkt_desc->size = size;
- if (!stream->predecode_packet)
- stream->predecode_packet = pkt_desc;
- stream->next_packet = &pkt_desc->next;
- if (av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size) < 0)
- return -1;
+ ret = av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size);
+ if (ret < 0)
+ return ret;
if (s->is_dvd) {
// min VOBU length 0.4 seconds (mpucoder)
if (is_iframe &&
- (s->packet_number == 0 ||
+ (s->packet_number == 0 || pts != AV_NOPTS_VALUE &&
(pts - stream->vobu_start_pts >= 36000))) {
stream->bytes_to_iframe = av_fifo_size(stream->fifo);
stream->align_iframe = 1;
* it as it is usually not needed by decoders and because it
* complicates MPEG stream concatenation. */
// avio_wb32(ctx->pb, ISO_11172_END_CODE);
- // avio_flush(ctx->pb);
for (i = 0; i < ctx->nb_streams; i++) {
stream = ctx->streams[i]->priv_data;
av_assert0(av_fifo_size(stream->fifo) == 0);
- av_fifo_freep(&stream->fifo);
}
return 0;
}
+static void mpeg_mux_deinit(AVFormatContext *ctx)
+{
+ for (int i = 0; i < ctx->nb_streams; i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+ if (!stream)
+ continue;
+ for (PacketDesc *pkt = stream->predecode_packet; pkt; ) {
+ PacketDesc *tmp = pkt->next;
+ av_free(pkt);
+ pkt = tmp;
+ }
+ av_fifo_freep(&stream->fifo);
+ }
+}
+
#define OFFSET(x) offsetof(MpegMuxContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
#if CONFIG_MPEG1SYSTEM_MUXER
MPEGENC_CLASS(mpeg)
-AVOutputFormat ff_mpeg1system_muxer = {
+const AVOutputFormat ff_mpeg1system_muxer = {
.name = "mpeg",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream"),
.mime_type = "video/mpeg",
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &mpeg_class,
};
#endif
#if CONFIG_MPEG1VCD_MUXER
MPEGENC_CLASS(vcd)
-AVOutputFormat ff_mpeg1vcd_muxer = {
+const AVOutputFormat ff_mpeg1vcd_muxer = {
.name = "vcd",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream (VCD)"),
.mime_type = "video/mpeg",
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &vcd_class,
};
#endif
#if CONFIG_MPEG2VOB_MUXER
MPEGENC_CLASS(vob)
-AVOutputFormat ff_mpeg2vob_muxer = {
+const AVOutputFormat ff_mpeg2vob_muxer = {
.name = "vob",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (VOB)"),
.mime_type = "video/mpeg",
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &vob_class,
};
#endif
/* Same as mpeg2vob_mux except that the pack size is 2324 */
#if CONFIG_MPEG2SVCD_MUXER
MPEGENC_CLASS(svcd)
-AVOutputFormat ff_mpeg2svcd_muxer = {
+const AVOutputFormat ff_mpeg2svcd_muxer = {
.name = "svcd",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (SVCD)"),
.mime_type = "video/mpeg",
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &svcd_class,
};
#endif
/* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */
#if CONFIG_MPEG2DVD_MUXER
MPEGENC_CLASS(dvd)
-AVOutputFormat ff_mpeg2dvd_muxer = {
+const AVOutputFormat ff_mpeg2dvd_muxer = {
.name = "dvd",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (DVD VOB)"),
.mime_type = "video/mpeg",
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &dvd_class,
};
#endif