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);
if (!s->is_mpeg2 &&
(st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
st->codecpar->codec_id == AV_CODEC_ID_DTS ||
- st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE))
+ st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ||
+ st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD))
av_log(ctx, AV_LOG_WARNING,
"%s in MPEG-1 system streams is not widely supported, "
"consider using the vob or the dvd muxer "
if (lpcm_freq_tab[j] == st->codecpar->sample_rate)
break;
}
- if (j == 4)
- goto fail;
- if (st->codecpar->channels > 8)
- return -1;
+ if (j == 4) {
+ int sr;
+ av_log(ctx, AV_LOG_ERROR, "Invalid sampling rate for PCM stream.\n");
+ av_log(ctx, AV_LOG_INFO, "Allowed sampling rates:");
+ for (sr = 0; sr < 4; sr++)
+ av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]);
+ av_log(ctx, AV_LOG_INFO, "\n");
+ return AVERROR(EINVAL);
+ }
+ if (st->codecpar->channels > 8) {
+ av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n");
+ 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->max_buffer_size = 6 * 1024 + props->buffer_size / 8;
else {
av_log(ctx, AV_LOG_WARNING,
- "VBV buffer size not set, using default size of 130KB\n"
+ "VBV buffer size not set, using default size of 230KB\n"
"If you want the mpeg file to be compliant to some specification\n"
"Like DVD, VCD or others, make sure you set the correct buffer size\n");
// FIXME: this is probably too small as default
}
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
return AVERROR(ENOMEM);
pkt_desc->pts = pts;
pkt_desc->dts = dts;
+
+ if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) {
+ if (size < 3) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n", size);
+ return AVERROR(EINVAL);
+ }
+
+ /* Skip first 3 bytes of packet data, which comprise PCM header
+ and will be written fresh by this muxer. */
+ buf += 3;
+ size -= 3;
+ }
+
pkt_desc->unwritten_size =
pkt_desc->size = size;
if (!stream->predecode_packet)
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;
+ av_fifo_freep(&stream->fifo);
+ }
+}
+
#define OFFSET(x) offsetof(MpegMuxContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
.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
.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
.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
.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
.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