* Copyright (c) 2008 GUCAS, Zhentan Feng <spyfeng at gmail dot com>
* Copyright (c) 2008 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavcodec/bytestream.h"
#include "audiointerleave.h"
#include "avformat.h"
+#include "internal.h"
#include "mxf.h"
static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 };
int index; ///< index in mxf_essence_container_uls table
const UID *codec_ul;
int order; ///< interleaving order if dts are equal
- int interlaced; ///< wether picture is interlaced
+ int interlaced; ///< whether picture is interlaced
int temporal_reordering;
AVRational aspect_ratio; ///< display aspect ratio
int closed_gop; ///< gop is closed, used in mpeg-2 frame parsing
} MXFContainerEssenceEntry;
static const struct {
- enum CodecID id;
+ enum AVCodecID id;
int index;
} mxf_essence_mappings[] = {
- { CODEC_ID_MPEG2VIDEO, 0 },
- { CODEC_ID_PCM_S24LE, 1 },
- { CODEC_ID_PCM_S16LE, 1 },
- { CODEC_ID_NONE }
+ { AV_CODEC_ID_MPEG2VIDEO, 0 },
+ { AV_CODEC_ID_PCM_S24LE, 1 },
+ { AV_CODEC_ID_PCM_S16LE, 1 },
+ { AV_CODEC_ID_NONE }
};
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
/*
* Get essence container ul index
*/
-static int mxf_get_essence_container_ul_index(enum CodecID id)
+static int mxf_get_essence_container_ul_index(enum AVCodecID id)
{
int i;
for (i = 0; mxf_essence_mappings[i].id; i++)
{
MXFContext *mxf = s->priv_data;
AVIOContext *pb = s->pb;
- const char *company = "FFmpeg";
+ const char *company = "Libav";
const char *product = "OP1a Muxer";
const char *version;
int length;
static void mxf_write_klv_fill(AVFormatContext *s)
{
- unsigned pad = klv_fill_size(url_ftell(s->pb));
+ unsigned pad = klv_fill_size(avio_tell(s->pb));
if (pad) {
avio_write(s->pb, klv_fill_key, 16);
pad -= 16 + 4;
klv_encode_ber4_length(s->pb, pad);
for (; pad; pad--)
avio_w8(s->pb, 0);
- assert(!(url_ftell(s->pb) & (KAG_SIZE-1)));
+ assert(!(avio_tell(s->pb) & (KAG_SIZE-1)));
}
}
AVIOContext *pb = s->pb;
int64_t header_byte_count_offset;
unsigned index_byte_count = 0;
- uint64_t partition_offset = url_ftell(pb);
+ uint64_t partition_offset = avio_tell(pb);
if (!mxf->edit_unit_byte_count && mxf->edit_units_count)
index_byte_count = 85 + 12+(s->nb_streams+1)*6 +
avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
// set offset
- header_byte_count_offset = url_ftell(pb);
+ header_byte_count_offset = avio_tell(pb);
avio_wb64(pb, 0); // headerByteCount, update later
// indexTable
unsigned header_byte_count;
mxf_write_klv_fill(s);
- start = url_ftell(s->pb);
+ start = avio_tell(s->pb);
mxf_write_primer_pack(s);
mxf_write_header_metadata_sets(s);
- pos = url_ftell(s->pb);
+ pos = avio_tell(s->pb);
header_byte_count = pos - start + klv_fill_size(pos);
// update header_byte_count
avio_seek(pb, pos, SEEK_SET);
}
- put_flush_packet(pb);
+ avio_flush(pb);
}
static const UID mxf_mpeg2_codec_uls[] = {
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, // MP-HL Long GOP
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, // 422P-HL I-Frame
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, // 422P-HL Long GOP
+ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x02,0x00 }, // MP@H-14 I-Frame
+ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x03,0x00 }, // MP@H-14 Long GOP
};
static const UID *mxf_get_mpeg2_codec_ul(AVCodecContext *avctx)
return &mxf_mpeg2_codec_uls[0+long_gop];
else if (avctx->level == 4) // High
return &mxf_mpeg2_codec_uls[4+long_gop];
+ else if (avctx->level == 6) // High 14
+ return &mxf_mpeg2_codec_uls[8+long_gop];
} else if (avctx->profile == 0) { // 422
if (avctx->level == 5) // Main
return &mxf_mpeg2_codec_uls[2+long_gop];
int i;
uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
const int *samples_per_frame = NULL;
+ AVDictionaryEntry *t;
+ int64_t timestamp = 0;
if (!s->nb_streams)
return -1;
av_log(s, AV_LOG_ERROR, "unsupported video frame rate\n");
return -1;
}
- av_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
+ avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
if (s->oformat == &ff_mxf_d10_muxer) {
if (st->codec->bit_rate == 50000000)
if (mxf->time_base.den == 25) sc->index = 3;
av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
return -1;
}
- av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
if (s->oformat == &ff_mxf_d10_muxer) {
if (st->index != 1) {
av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
return -1;
}
- if (st->codec->codec_id != CODEC_ID_PCM_S16LE &&
- st->codec->codec_id != CODEC_ID_PCM_S24LE) {
+ if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE &&
+ st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) {
av_log(s, AV_LOG_ERROR, "MXF D-10 only support 16 or 24 bits le audio\n");
}
sc->index = ((MXFStreamContext*)s->streams[0]->priv_data)->index + 1;
sc->order = AV_RB32(sc->track_essence_element_key+12);
}
- if (s->timestamp)
- mxf->timestamp = mxf_parse_timestamp(s->timestamp);
+ if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
+ timestamp = ff_iso8601_to_unix_time(t->value);
+ if (timestamp)
+ mxf->timestamp = mxf_parse_timestamp(timestamp);
mxf->duration = -1;
mxf->timecode_track = av_mallocz(sizeof(*mxf->timecode_track));
static uint32_t ff_framenum_to_12m_time_code(unsigned frame, int drop, int fps)
{
return (0 << 31) | // color frame flag
- (0 << 30) | // drop frame flag
+ (drop << 30) | // drop frame flag
( ((frame % fps) / 10) << 28) | // tens of frames
( ((frame % fps) % 10) << 24) | // units of frames
(0 << 23) | // field phase (NTSC), b0 (PAL)
((((frame / (fps * 60)) % 60) / 10) << 12) | // tens of minutes
((((frame / (fps * 60)) % 60) % 10) << 8) | // units of minutes
(0 << 7) | // b1
- (0 << 6) | // b2 (NSC), field phase (PAL)
+ (0 << 6) | // b2 (NTSC), field phase (PAL)
((((frame / (fps * 3600) % 24)) / 10) << 4) | // tens of hours
( (frame / (fps * 3600) % 24)) % 10; // units of hours
}
klv_encode_ber4_length(s->pb, pad);
for (; pad; pad--)
avio_w8(s->pb, 0);
- assert(!(url_ftell(s->pb) & (KAG_SIZE-1)));
+ assert(!(avio_tell(s->pb) & (KAG_SIZE-1)));
} else {
av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n");
for (; pad > 0; pad--)
while (samples < end) {
for (i = 0; i < st->codec->channels; i++) {
uint32_t sample;
- if (st->codec->codec_id == CODEC_ID_PCM_S24LE) {
+ if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) {
sample = AV_RL24(samples)<< 4;
samples += 3;
} else {
}
}
- if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) {
+ if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
return -1;
mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
}
- put_flush_packet(pb);
+ avio_flush(pb);
return 0;
}
{
MXFContext *mxf = s->priv_data;
AVIOContext *pb = s->pb;
- uint64_t pos = url_ftell(pb);
+ uint64_t pos = avio_tell(pb);
int i;
avio_write(pb, random_index_pack_key, 16);
avio_wb32(pb, 0); // BodySID of footer partition
avio_wb64(pb, mxf->footer_partition_offset);
- avio_wb32(pb, url_ftell(pb) - pos + 4);
+ avio_wb32(pb, avio_tell(pb) - pos + 4);
}
static int mxf_write_footer(AVFormatContext *s)
mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;
mxf_write_klv_fill(s);
- mxf->footer_partition_offset = url_ftell(pb);
+ mxf->footer_partition_offset = avio_tell(pb);
if (mxf->edit_unit_byte_count) { // no need to repeat index
mxf_write_partition(s, 0, 0, footer_partition_key, 0);
} else {
mxf_write_klv_fill(s);
mxf_write_random_index_pack(s);
- if (!url_is_streamed(s->pb)) {
+ if (s->pb->seekable) {
avio_seek(pb, 0, SEEK_SET);
if (mxf->edit_unit_byte_count) {
mxf_write_partition(s, 1, 2, header_closed_partition_key, 1);
}
}
- put_flush_packet(pb);
-
ff_audio_interleave_close(s);
av_freep(&mxf->index_entries);
}
AVOutputFormat ff_mxf_muxer = {
- "mxf",
- NULL_IF_CONFIG_SMALL("Material eXchange Format"),
- "application/mxf",
- "mxf",
- sizeof(MXFContext),
- CODEC_ID_PCM_S16LE,
- CODEC_ID_MPEG2VIDEO,
- mxf_write_header,
- mxf_write_packet,
- mxf_write_footer,
- AVFMT_NOTIMESTAMPS,
- NULL,
- mxf_interleave,
+ .name = "mxf",
+ .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
+ .mime_type = "application/mxf",
+ .extensions = "mxf",
+ .priv_data_size = sizeof(MXFContext),
+ .audio_codec = AV_CODEC_ID_PCM_S16LE,
+ .video_codec = AV_CODEC_ID_MPEG2VIDEO,
+ .write_header = mxf_write_header,
+ .write_packet = mxf_write_packet,
+ .write_trailer = mxf_write_footer,
+ .flags = AVFMT_NOTIMESTAMPS,
+ .interleave_packet = mxf_interleave,
};
AVOutputFormat ff_mxf_d10_muxer = {
- "mxf_d10",
- NULL_IF_CONFIG_SMALL("Material eXchange Format, D-10 Mapping"),
- "application/mxf",
- NULL,
- sizeof(MXFContext),
- CODEC_ID_PCM_S16LE,
- CODEC_ID_MPEG2VIDEO,
- mxf_write_header,
- mxf_write_packet,
- mxf_write_footer,
- AVFMT_NOTIMESTAMPS,
- NULL,
- mxf_interleave,
+ .name = "mxf_d10",
+ .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
+ .mime_type = "application/mxf",
+ .priv_data_size = sizeof(MXFContext),
+ .audio_codec = AV_CODEC_ID_PCM_S16LE,
+ .video_codec = AV_CODEC_ID_MPEG2VIDEO,
+ .write_header = mxf_write_header,
+ .write_packet = mxf_write_packet,
+ .write_trailer = mxf_write_footer,
+ .flags = AVFMT_NOTIMESTAMPS,
+ .interleave_packet = mxf_interleave,
};