⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mxf.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * MXF demuxer. * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>. * * This file is part of FFmpeg. * * FFmpeg 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, * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//* * References * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value * SMPTE 377M MXF File Format Specifications * SMPTE 378M Operational Pattern 1a * SMPTE 379M MXF Generic Container * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container * * Principle * Search for Track numbers which will identify essence element KLV packets. * Search for SourcePackage which define tracks which contains Track numbers. * Material Package contains tracks with reference to SourcePackage tracks. * Search for Descriptors (Picture, Sound) which contains codec info and parameters. * Assign Descriptors to correct Tracks. * * Metadata reading functions read Local Tags, get InstanceUID(0x3C0A) then add MetaDataSet to MXFContext. * Metadata parsing resolves Strong References to objects. * * Simple demuxer, only OP1A supported and some files might not work at all. * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1 *///#define DEBUG#include "avformat.h"#include "aes.h"#include "bytestream.h"typedef uint8_t UID[16];enum MXFMetadataSetType {    AnyType,    MaterialPackage,    SourcePackage,    SourceClip,    TimecodeComponent,    Sequence,    MultipleDescriptor,    Descriptor,    Track,    CryptoContext,};typedef struct {    UID uid;    enum MXFMetadataSetType type;    UID context_uid;    UID source_container_ul;} MXFCryptoContext;typedef struct {    UID uid;    enum MXFMetadataSetType type;    UID source_package_uid;    UID data_definition_ul;    int64_t duration;    int64_t start_position;    int source_track_id;} MXFStructuralComponent;typedef struct {    UID uid;    enum MXFMetadataSetType type;    UID data_definition_ul;    UID *structural_components_refs;    int structural_components_count;    int64_t duration;} MXFSequence;typedef struct {    UID uid;    enum MXFMetadataSetType type;    MXFSequence *sequence; /* mandatory, and only one */    UID sequence_ref;    int track_id;    uint8_t track_number[4];    AVRational edit_rate;} MXFTrack;typedef struct {    UID uid;    enum MXFMetadataSetType type;    UID essence_container_ul;    UID essence_codec_ul;    AVRational sample_rate;    AVRational aspect_ratio;    int width;    int height;    int channels;    int bits_per_sample;    UID *sub_descriptors_refs;    int sub_descriptors_count;    int linked_track_id;    uint8_t *extradata;    int extradata_size;} MXFDescriptor;typedef struct {    UID uid;    enum MXFMetadataSetType type;    UID package_uid;    UID *tracks_refs;    int tracks_count;    MXFDescriptor *descriptor; /* only one */    UID descriptor_ref;} MXFPackage;typedef struct {    UID uid;    enum MXFMetadataSetType type;} MXFMetadataSet;typedef struct {    UID *packages_refs;    int packages_count;    MXFMetadataSet **metadata_sets;    int metadata_sets_count;    AVFormatContext *fc;    struct AVAES *aesc;} MXFContext;typedef struct {    UID key;    offset_t offset;    uint64_t length;} KLVPacket;enum MXFWrappingScheme {    Frame,    Clip,};typedef struct {    UID uid;    enum CodecID id;    enum MXFWrappingScheme wrapping;} MXFCodecUL;typedef struct {    UID uid;    enum CodecType type;} MXFDataDefinitionUL;typedef struct {    const UID key;    int (*read)();    int ctx_size;    enum MXFMetadataSetType type;} MXFMetadataReadTableEntry;/* partial keys to match */static const uint8_t mxf_header_partition_pack_key[]       = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };static const uint8_t mxf_essence_element_key[]             = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };static const uint8_t mxf_klv_key[]                         = { 0x06,0x0e,0x2b,0x34 };/* complete keys to match */static const uint8_t mxf_encrypted_triplet_key[]           = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 };static const uint8_t mxf_encrypted_essence_container[]     = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 };#define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))#define PRINT_KEY(pc, s, x) dprintf(pc, "%s %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", s, \                             (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15])static int64_t klv_decode_ber_length(ByteIOContext *pb){    uint64_t size = get_byte(pb);    if (size & 0x80) { /* long form */        int bytes_num = size & 0x7f;        /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */        if (bytes_num > 8)            return -1;        size = 0;        while (bytes_num--)            size = size << 8 | get_byte(pb);    }    return size;}static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size){    int i, b;    for (i = 0; i < size && !url_feof(pb); i++) {        b = get_byte(pb);        if (b == key[0])            i = 0;        else if (b != key[i])            i = -1;    }    return i == size;}static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb){    if (!mxf_read_sync(pb, mxf_klv_key, 4))        return -1;    klv->offset = url_ftell(pb) - 4;    memcpy(klv->key, mxf_klv_key, 4);    get_buffer(pb, klv->key + 4, 12);    klv->length = klv_decode_ber_length(pb);    return klv->length == -1 ? -1 : 0;}static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv){    int i;    for (i = 0; i < s->nb_streams; i++) {        MXFTrack *track = s->streams[i]->priv_data;        /* SMPTE 379M 7.3 */        if (!memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number)))            return i;    }    /* return 0 if only one stream, for OP Atom files with 0 as track number */    return s->nb_streams == 1 ? 0 : -1;}/* XXX: use AVBitStreamFilter */static int mxf_get_d10_aes3_packet(ByteIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length){    uint8_t buffer[61444];    uint8_t *buf_ptr, *end_ptr, *data_ptr;    int i;    if (length > 61444) /* worst case PAL 1920 samples 8 channels */        return -1;    get_buffer(pb, buffer, length);    av_new_packet(pkt, length);    data_ptr = pkt->data;    end_ptr = buffer + length;    buf_ptr = buffer + 4; /* skip SMPTE 331M header */    for (; buf_ptr < end_ptr; ) {        for (i = 0; i < st->codec->channels; i++) {            uint32_t sample = bytestream_get_le32(&buf_ptr);            if (st->codec->bits_per_sample == 24)                bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff);            else                bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff);        }        buf_ptr += 32 - st->codec->channels*4; // always 8 channels stored SMPTE 331M    }    pkt->size = data_ptr - pkt->data;    return 0;}static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv){    static const uint8_t checkv[16] = {0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b};    MXFContext *mxf = s->priv_data;    ByteIOContext *pb = &s->pb;    offset_t end = url_ftell(pb) + klv->length;    uint64_t size;    uint64_t orig_size;    uint64_t plaintext_size;    uint8_t ivec[16];    uint8_t tmpbuf[16];    int index;    if (!mxf->aesc && s->key && s->keylen == 16) {        mxf->aesc = av_malloc(av_aes_size);        av_aes_init(mxf->aesc, s->key, 128, 1);    }    // crypto context    url_fskip(pb, klv_decode_ber_length(pb));    // plaintext offset    klv_decode_ber_length(pb);    plaintext_size = get_be64(pb);    // source klv key    klv_decode_ber_length(pb);    get_buffer(pb, klv->key, 16);    if (!IS_KLV_KEY(klv, mxf_essence_element_key))        return -1;    index = mxf_get_stream_index(s, klv);    if (index < 0)        return -1;    // source size    klv_decode_ber_length(pb);    orig_size = get_be64(pb);    if (orig_size < plaintext_size)        return -1;    // enc. code    size = klv_decode_ber_length(pb);    if (size < 32 || size - 32 < orig_size)        return -1;    get_buffer(pb, ivec, 16);    get_buffer(pb, tmpbuf, 16);    if (mxf->aesc)        av_aes_crypt(mxf->aesc, tmpbuf, tmpbuf, 1, ivec, 1);    if (memcmp(tmpbuf, checkv, 16))        av_log(s, AV_LOG_ERROR, "probably incorrect decryption key\n");    size -= 32;    av_get_packet(pb, pkt, size);    size -= plaintext_size;    if (mxf->aesc)        av_aes_crypt(mxf->aesc, &pkt->data[plaintext_size],                     &pkt->data[plaintext_size], size >> 4, ivec, 1);    pkt->size = orig_size;    pkt->stream_index = index;    url_fskip(pb, end - url_ftell(pb));    return 0;}static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt){    KLVPacket klv;    while (!url_feof(&s->pb)) {        if (klv_read_packet(&klv, &s->pb) < 0)            return -1;#ifdef DEBUG        PRINT_KEY(s, "read packet", klv.key);#endif        if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {            int res = mxf_decrypt_triplet(s, pkt, &klv);            if (res < 0) {                av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");                return -1;            }            return 0;        }        if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) {            int index = mxf_get_stream_index(s, &klv);            if (index < 0) {                av_log(s, AV_LOG_ERROR, "error getting stream index\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -