Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Video][Subtitles] Use ffmpeg A53 sidedata instead of custom demuxer #22333

Merged
merged 6 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ set(HEADERS AudioSinkAE.h
VideoPlayerTeletext.h
VideoPlayerVideo.h
VideoReferenceClock.h
Interface/CaptionBlock.h
Interface/StreamInfo.h
Interface/DemuxPacket.h
Interface/DemuxCrypto.h
Expand Down
108 changes: 54 additions & 54 deletions xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,11 @@ static void cc_decode_EIA608(cc_decoder_t *dec, uint16_t data)
uint8_t c1 = data & 0x7f;
uint8_t c2 = (data >> 8) & 0x7f;

/* control sequences are often repeated. In this case, we should */
/* evaluate it only once. */
if (data == dec->lastcode)
return;

if (c1 & 0x60)
{ /* normal character, 0x20 <= c1 <= 0x7f */
if (dec->style == CC_NOTSET)
Expand All @@ -734,71 +739,66 @@ static void cc_decode_EIA608(cc_decoder_t *dec, uint16_t data)
int channel = (c1 & 0x08) >> 3;
c1 &= ~0x08;

/* control sequences are often repeated. In this case, we should */
/* evaluate it only once. */
if (data != dec->lastcode)
if (c2 & 0x40)
{ /* preamble address code: 0x40 <= c2 <= 0x7f */
cc_decode_PAC(dec, channel, c1, c2);
}
else
{
if (c2 & 0x40)
{ /* preamble address code: 0x40 <= c2 <= 0x7f */
cc_decode_PAC(dec, channel, c1, c2);
}
else
switch (c1)
{
switch (c1)
{
case 0x10: /* extended background attribute code */
cc_decode_ext_attribute(dec, channel);
break;
case 0x10: /* extended background attribute code */
cc_decode_ext_attribute(dec, channel);
break;

case 0x11: /* attribute or special character */
if (dec->style == CC_NOTSET)
return;
case 0x11: /* attribute or special character */
if (dec->style == CC_NOTSET)
return;

if ((c2 & 0x30) == 0x30)
{
/* special char: 0x30 <= c2 <= 0x3f */
/* CCSET_SPECIAL_AMERICAN */
cc_decode_special_char(dec, channel, CCSET_SPECIAL_AMERICAN, c2);
if (dec->style == CC_ROLLUP)
{
ccmem_tobuf(dec);
}
}
else if (c2 & 0x20)
{
/* midrow attribute: 0x20 <= c2 <= 0x2f */
cc_decode_midrow_attr(dec, channel, c2);
}
break;

case 0x12: /* CCSET_EXTENDED_SPANISH_FRENCH_MISC */
cc_decode_special_char(dec, channel, CCSET_EXTENDED_SPANISH_FRENCH_MISC, c2);
if ((c2 & 0x30) == 0x30)
{
/* special char: 0x30 <= c2 <= 0x3f */
/* CCSET_SPECIAL_AMERICAN */
cc_decode_special_char(dec, channel, CCSET_SPECIAL_AMERICAN, c2);
if (dec->style == CC_ROLLUP)
{
ccmem_tobuf(dec);
}
break;
}
else if (c2 & 0x20)
{
/* midrow attribute: 0x20 <= c2 <= 0x2f */
cc_decode_midrow_attr(dec, channel, c2);
}
break;

case 0x13: /* CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH */
cc_decode_special_char(dec, channel, CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH, c2);
if (dec->style == CC_ROLLUP)
{
ccmem_tobuf(dec);
}
break;
case 0x12: /* CCSET_EXTENDED_SPANISH_FRENCH_MISC */
cc_decode_special_char(dec, channel, CCSET_EXTENDED_SPANISH_FRENCH_MISC, c2);
if (dec->style == CC_ROLLUP)
{
ccmem_tobuf(dec);
}
break;

case 0x14: /* possibly miscellaneous control code */
cc_decode_misc_control_code(dec, channel, c2);
break;
case 0x13: /* CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH */
cc_decode_special_char(dec, channel, CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH, c2);
if (dec->style == CC_ROLLUP)
{
ccmem_tobuf(dec);
}
break;

case 0x17: /* possibly misc. control code TAB offset */
/* 0x21 <= c2 <= 0x23 */
if (c2 >= 0x21 && c2 <= 0x23)
{
cc_decode_tab(dec, channel, c2);
}
break;
}
case 0x14: /* possibly miscellaneous control code */
cc_decode_misc_control_code(dec, channel, c2);
break;

case 0x17: /* possibly misc. control code TAB offset */
/* 0x21 <= c2 <= 0x23 */
if (c2 >= 0x21 && c2 <= 0x23)
{
cc_decode_tab(dec, channel, c2);
}
break;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,7 @@ void CDecoderCC708::Init(void (*handler)(int service, void *userdata), void *use
ccx_decoders_708_init(m_cc708decoders, handler, userdata, this);
}

void CDecoderCC708::Decode(const unsigned char *data, int datalength)
void CDecoderCC708::Decode(const std::vector<uint8_t>& data)
{
decode_708(data, datalength, m_cc708decoders);
decode_708(data.data(), data.size(), m_cc708decoders);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <vector>

#include <sys/stat.h>

extern "C"{
Expand Down Expand Up @@ -292,7 +294,7 @@ class CDecoderCC708
CDecoderCC708();
virtual ~CDecoderCC708();
void Init(void (*handler)(int service, void *userdata), void *userdata);
void Decode(const unsigned char *data, int datalength);
void Decode(const std::vector<uint8_t>& data);
bool m_inited;
cc708_service_decoder* m_cc708decoders;
cc_decoder_t *m_cc608decoder;
Expand Down
45 changes: 43 additions & 2 deletions xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,46 @@ VideoPicture& VideoPicture::SetParams(const VideoPicture &pic)
return *this;
}

VideoPicture::VideoPicture(VideoPicture const&) = default;
VideoPicture& VideoPicture::operator=(VideoPicture const&) = default;
VideoPicture& VideoPicture::operator=(VideoPicture const& pic)
{
if (this != &pic)
{
if (videoBuffer)
videoBuffer->Release();
videoBuffer = pic.videoBuffer;
if (videoBuffer)
videoBuffer->Acquire();

pts = pic.pts;
dts = pic.dts;
iFlags = pic.iFlags;
iRepeatPicture = pic.iRepeatPicture;
iDuration = pic.iDuration;
iFrameType = pic.iFrameType;
color_space = pic.color_space;
color_range = pic.color_range;
chroma_position = pic.chroma_position;
color_primaries = pic.color_primaries;
color_transfer = pic.color_transfer;
colorBits = pic.colorBits;
stereoMode = pic.stereoMode;

iWidth = pic.iWidth;
iHeight = pic.iHeight;
iDisplayWidth = pic.iDisplayWidth;
iDisplayHeight = pic.iDisplayHeight;

hasDisplayMetadata = pic.hasDisplayMetadata;
hasLightMetadata = pic.hasLightMetadata;

qp_table = pic.qp_table;
qstride = pic.qstride;
qscale_type = pic.qscale_type;
pict_type = pic.pict_type;

if (pic.HasA53SideData())
SetA53SideData(pic.m_A53SideData.get());
}

return *this;
}
34 changes: 34 additions & 0 deletions xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ class CSetting;
#define FRAME_TYPE_B 3
#define FRAME_TYPE_D 4

/*!
* \brief Deleter for AVBufferRef (ATSC A53 closed captions)
*/
struct AVBufferRefDeleter
{
void operator()(AVBufferRef* ref) { av_buffer_unref(&ref); }
};

// should be entirely filled by all codecs
struct VideoPicture
Expand All @@ -42,6 +49,32 @@ struct VideoPicture
VideoPicture& SetParams(const VideoPicture &pic);
void Reset(); // reinitialize members, videoBuffer will be released if set!

/*!
* \brief Checks if the video picture has A53 side data (closed captions).
*
* \return true if the video picture has A53 side data, false otherwise
*/
bool HasA53SideData() const { return m_A53SideData != nullptr; }

/*!
* \brief Gets the A53 side data of the video picture (closed captions)
* \return the A53 side data, reseting the value
*/
std::unique_ptr<AVBufferRef, AVBufferRefDeleter> GetA53SideData()
{
return std::move(m_A53SideData);
}

/*!
* \brief Set the A53 side data on the video picture
*
* \param[in] sideData the data to store as A53 side data
*/
void SetA53SideData(AVBufferRef* sideData)
{
m_A53SideData = std::unique_ptr<AVBufferRef, AVBufferRefDeleter>(av_buffer_ref(sideData));
}

CVideoBuffer *videoBuffer = nullptr;

double pts; // timestamp in seconds, used in the CVideoPlayer class to keep track of pts
Expand Down Expand Up @@ -78,6 +111,7 @@ struct VideoPicture
private:
VideoPicture(VideoPicture const&);
VideoPicture& operator=(VideoPicture const&);
std::unique_ptr<AVBufferRef, AVBufferRefDeleter> m_A53SideData;
};

#define DVP_FLAG_TOP_FIELD_FIRST 0x00000001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,13 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(VideoPicture* pVideoPicture)
else
pVideoPicture->dts = m_dts;

// ATSC A53 Closed Captions (side data)
sd = av_frame_get_side_data(m_pFrame, AV_FRAME_DATA_A53_CC);
if (sd)
{
pVideoPicture->SetA53SideData(sd->buf);
}

m_dts = DVD_NOPTS_VALUE;

int64_t bpts = m_pFrame->best_effort_timestamp;
Expand Down
Loading