92 lines
2.8 KiB
C
92 lines
2.8 KiB
C
/*
|
|
* MXF SMPTE-436M ANC to EIA-608 bitstream filter
|
|
* Copyright (c) 2025 Jacob Lifshay
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include "bsf.h"
|
|
#include "bsf_internal.h"
|
|
#include "codec_id.h"
|
|
#include "libavcodec/smpte_436m.h"
|
|
#include "libavutil/error.h"
|
|
|
|
static av_cold int ff_smpte436m_to_eia608_init(AVBSFContext *ctx)
|
|
{
|
|
ctx->par_out->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
|
ctx->par_out->codec_id = AV_CODEC_ID_EIA_608;
|
|
return 0;
|
|
}
|
|
|
|
static int ff_smpte436m_to_eia608_filter(AVBSFContext *ctx, AVPacket *out)
|
|
{
|
|
AVPacket *in;
|
|
int ret = ff_bsf_get_packet(ctx, &in);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
AVSmpte436mAncIterator iter;
|
|
ret = av_smpte_436m_anc_iter_init(&iter, in->data, in->size);
|
|
if (ret < 0)
|
|
goto fail;
|
|
AVSmpte436mCodedAnc coded_anc;
|
|
while ((ret = av_smpte_436m_anc_iter_next(&iter, &coded_anc)) >= 0) {
|
|
AVSmpte291mAnc8bit anc;
|
|
ret = av_smpte_291m_anc_8bit_decode(
|
|
&anc, coded_anc.payload_sample_coding, coded_anc.payload_sample_count, coded_anc.payload, ctx);
|
|
if (ret < 0)
|
|
goto fail;
|
|
ret = av_smpte_291m_anc_8bit_extract_cta_708(&anc, NULL, ctx);
|
|
if (ret == AVERROR(EAGAIN))
|
|
continue;
|
|
if (ret < 0)
|
|
goto fail;
|
|
int cc_count = ret;
|
|
|
|
ret = av_new_packet(out, 3 * cc_count);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
ret = av_packet_copy_props(out, in);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
// verified it won't fail by running it above
|
|
av_smpte_291m_anc_8bit_extract_cta_708(&anc, out->data, ctx);
|
|
|
|
av_packet_free(&in);
|
|
|
|
return 0;
|
|
}
|
|
if (ret != AVERROR_EOF)
|
|
return ret;
|
|
ret = AVERROR(EAGAIN);
|
|
|
|
fail:
|
|
if (ret < 0)
|
|
av_packet_unref(out);
|
|
av_packet_free(&in);
|
|
return ret;
|
|
}
|
|
|
|
const FFBitStreamFilter ff_smpte436m_to_eia608_bsf = {
|
|
.p.name = "smpte436m_to_eia608",
|
|
.p.codec_ids = (const enum AVCodecID[]){ AV_CODEC_ID_SMPTE_436M_ANC, AV_CODEC_ID_NONE },
|
|
.init = ff_smpte436m_to_eia608_init,
|
|
.filter = ff_smpte436m_to_eia608_filter,
|
|
};
|