[M120 Migration] Support AC-4 audio codec 69/310869/6 submit/tizen/20240521.160018
authoryangzw <zw714.yang@samsung.com>
Thu, 9 May 2024 06:41:05 +0000 (14:41 +0800)
committerBot Blink <blinkbot@samsung.com>
Tue, 21 May 2024 15:44:46 +0000 (15:44 +0000)
HbbTV uses AC-4 encrypted audio stream.
This patch is verified by HbbTV MediaSource/AC-4 TCs.

ref:
https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/299413/

Change-Id: I62876758e84c9f35386f5388466846b76b504c15
Signed-off-by: yangzw <zw714.yang@samsung.com>
12 files changed:
media/base/audio_buffer.cc
media/base/mime_util_internal.cc
media/base/sample_format.cc
media/base/sample_format.h
media/base/supported_types.cc
media/ffmpeg/ffmpeg_common.cc
media/filters/stream_parser_factory.cc
media/formats/mp4/es_descriptor.h
media/formats/mp4/fourccs.h
media/formats/mp4/mp4_stream_parser.cc
media/media_options.gni
tizen_src/chromium_impl/media/filters/esplusplayer_util.cc

index 9c5ca58b8e7adc1ecbdd4b222ccf52330983dfc5..a836fd4e415bfd2eba13585e056043cbffa1124d 100644 (file)
@@ -541,6 +541,7 @@ void AudioBuffer::TrimRange(int start, int end) {
       }
       case kUnknownSampleFormat:
       case kSampleFormatAc3:
+      case kSampleFormatAc4:
       case kSampleFormatEac3:
       case kSampleFormatMpegHAudio:
       case kSampleFormatDts:
index 6bbba7ddcbeb6bbabb20782341b5a9e2cc209c95..7987d4e0a4d423c89cab9347a5c809f71a48ac2b 100644 (file)
@@ -719,7 +719,11 @@ bool MimeUtil::IsCodecSupportedOnAndroid(Codec codec,
 #endif
 
     case AC4:
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+      return true;
+#else
       return false;
+#endif
   }
 
   return false;
@@ -920,7 +924,7 @@ bool MimeUtil::ParseCodecHelper(base::StringPiece mime_type_lower_case,
   }
 #endif
 
-  DVLOG(2) << __func__ << ": Unrecognized codec id \"" << codec_id << "\"";
+  LOG(ERROR) << __func__ << ": Unrecognized codec id \"" << codec_id << "\"";
   return false;
 }
 
index f5545c2d4940b64487dc4cb42fabb7f24dfdb544..ed303927a76630197d7287d59696a29c7c237432 100644 (file)
@@ -22,6 +22,7 @@ int SampleFormatToBytesPerChannel(SampleFormat sample_format) {
     case kSampleFormatDts:
     case kSampleFormatDtsxP2:
     case kSampleFormatDtse:
+    case kSampleFormatAc4:
       return 1;
     case kSampleFormatS16:
     case kSampleFormatPlanarS16:
@@ -79,6 +80,8 @@ const char* SampleFormatToString(SampleFormat sample_format) {
       return "IEC-61937 encapsulated DTS bitstream";
     case kSampleFormatDtse:
       return "Compressed DTS Express bitstream";
+    case kSampleFormatAc4:
+      return "Compressed AC4 bitstream";
   }
   NOTREACHED() << "Invalid sample format provided: " << sample_format;
   return "";
@@ -104,6 +107,7 @@ bool IsPlanar(SampleFormat sample_format) {
     case kSampleFormatDtsxP2:
     case kSampleFormatIECDts:
     case kSampleFormatDtse:
+    case kSampleFormatAc4:
       return false;
   }
 
@@ -125,6 +129,7 @@ bool IsInterleaved(SampleFormat sample_format) {
     case kSampleFormatDtsxP2:
     case kSampleFormatIECDts:
     case kSampleFormatDtse:
+    case kSampleFormatAc4:
       return true;
     case kUnknownSampleFormat:
     case kSampleFormatPlanarU8:
@@ -150,6 +155,7 @@ bool IsBitstream(SampleFormat sample_format) {
       // kSampleFormatS16, so it will return false. If bit-stream passthrough
       // is required, the sample format would already be
       // kSampleFormatDts/DtsxP2. In this case, it should return true as below.
+    case kSampleFormatAc4:
       return true;
     case kUnknownSampleFormat:
     case kSampleFormatU8:
index efea139da56a0b6f0c84df16878e8f3c48dbf403..8e73f8101be0220af3f93e692492e6ebb6c57252 100644 (file)
@@ -31,9 +31,10 @@ enum SampleFormat {
   kSampleFormatDtsxP2,      // Compressed DTSX audio bitstream.
   kSampleFormatIECDts,      // IEC-61937 encapsulated DTS audio bitstream.
   kSampleFormatDtse,        // Compressed DTS Express audio bitstream.
+  kSampleFormatAc4,         // Compressed AC4 bitstream.
 
   // Must always be equal to largest value ever logged.
-  kSampleFormatMax = kSampleFormatDtse,
+  kSampleFormatMax = kSampleFormatAc4,
 };
 
 // Returns the number of bytes used per channel for the specified
index 4b18a883bee14618271337459c2079377b27907a..c92a88756ff9d6f47414f40497bbca4a1c340a80 100644 (file)
@@ -422,6 +422,9 @@ bool IsDefaultSupportedAudioType(const AudioType& type) {
     case AudioCodec::kALAC:
     case AudioCodec::kMpegHAudio:
     case AudioCodec::kAC4:
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+      return true;
+#endif
     case AudioCodec::kUnknown:
       return false;
     case AudioCodec::kDTS:
index a88f613f7c860df82d627613f8ff0747f372c3fb..28eee8035dce30eae02a0216d78b8954b18371a5 100644 (file)
@@ -96,6 +96,10 @@ AudioCodec CodecIDToAudioCodec(AVCodecID codec_id) {
       return AudioCodec::kAC3;
     case AV_CODEC_ID_EAC3:
       return AudioCodec::kEAC3;
+#endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+    case AV_CODEC_ID_AC4:
+      return AudioCodec::kAC4;
 #endif
     case AV_CODEC_ID_MP3:
       return AudioCodec::kMP3;
@@ -361,7 +365,13 @@ bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context,
       sample_format = kSampleFormatMpegHAudio;
       break;
 #endif
-
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+    case AudioCodec::kAC4:
+      // The spec for AC4 audio is ETSI TS 103 190-1. According to sections
+      // E.3 in that spec the sample_format for AC4 must be 16.
+      sample_format = kSampleFormatS16;
+      break;
+#endif
     default:
       break;
   }
@@ -400,6 +410,10 @@ bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context,
   if (codec == AudioCodec::kAC3 || codec == AudioCodec::kEAC3)
     return true;
 #endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+  if (codec == AudioCodec::kAC4)
+    return true;
+#endif
 #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
   if (codec == AudioCodec::kMpegHAudio)
     return true;
index 5ed64e5ef6180c5342f1877aeeb0d1c45ca7393f..a9d14a99a07279e819e023e1c803aaed385915b3 100644 (file)
@@ -71,7 +71,8 @@ struct CodecInfo {
     HISTOGRAM_DTS,
     HISTOGRAM_DTSXP2,
     HISTOGRAM_DTSE,
-    HISTOGRAM_MAX = HISTOGRAM_DTSE  // Must be equal to largest logged entry.
+    HISTOGRAM_AC4,
+    HISTOGRAM_MAX = HISTOGRAM_AC4  // Must be equal to largest logged entry.
   };
 
   const char* pattern;
@@ -257,6 +258,11 @@ static const CodecInfo kMpegHAudioCodecInfo2 = {
     "mha1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO};
 #endif
 
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+static const CodecInfo kAC4CodecInfo1 = {"ac-4*", CodecInfo::AUDIO, nullptr,
+                                         CodecInfo::HISTOGRAM_AC4};
+#endif
+
 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
 
 static const CodecInfo kMP3CodecInfo = {nullptr, CodecInfo::AUDIO, nullptr,
@@ -326,6 +332,9 @@ static const CodecInfo* const kAudioMP4Codecs[] = {&kMPEG4FLACCodecInfo,
                                                    &kEAC3CodecInfo2,
                                                    &kEAC3CodecInfo3,
 #endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+                                                   &kAC4CodecInfo1,
+#endif  // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
                                                    &kDTSCodecInfo1,
                                                    &kDTSCodecInfo2,
@@ -381,6 +390,10 @@ static StreamParser* BuildMP4Parser(base::span<const std::string> codecs,
                base::MatchPattern(codec_id, kEAC3CodecInfo3.pattern)) {
       audio_object_types.insert(mp4::kEAC3);
 #endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+    } else if (base::MatchPattern(codec_id, kAC4CodecInfo1.pattern)) {
+      audio_object_types.insert(mp4::kAC4);
+#endif  // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
     } else if (base::MatchPattern(codec_id, kDTSCodecInfo1.pattern) ||
                base::MatchPattern(codec_id, kDTSCodecInfo2.pattern) ||
index 47ae6cfc828795748465005cc7cd536c43e99f1b..3ea9b114698edbbb655bf4c88be2685551061953 100644 (file)
@@ -28,7 +28,8 @@ enum ObjectType {
   kEAC3 = 0xa6,                // EAC3 / Dolby Digital Plus
   kDTS = 0xa9,                 // DTS
   kDTSE = 0xac,                // DTS Express/LBR
-  kDTSX = 0xb2                 // DTS:X
+  kDTSX = 0xb2,                // DTS:X
+  kAC4 = 0xae                  // AC4
 };
 
 enum Tag {
index 45ea7c54422e974059222838ec3c890ac90868d8..10bde1afbe257305dd46955baf98ea290a765571 100644 (file)
@@ -21,6 +21,9 @@ enum FourCC {
   FOURCC_EAC3 = 0x65632d33,  // "ec-3"
   FOURCC_DEC3 = 0x64656333,  // "dec3"
 #endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+  FOURCC_AC4 = 0x61632d34,  // "ac-4"
+#endif
 #if BUILDFLAG(ENABLE_AV1_DECODER)
   FOURCC_AV01 = 0x61763031,  // "av01"
   FOURCC_AV1C = 0x61763143,  // "av1C"
index d92609b95c9027e59782b27f7d9098be5990fc58..17e4f337c4d84b24a29d1cf140bd1be0d927b417 100644 (file)
@@ -429,6 +429,9 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
           audio_format != FOURCC_AC3 && audio_format != FOURCC_EAC3 &&
 #endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+          audio_format != FOURCC_AC4 &&
+#endif
 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
           audio_format != FOURCC_DTSC && audio_format != FOURCC_DTSX &&
           audio_format != FOURCC_DTSE &&
@@ -437,9 +440,8 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
           audio_format != FOURCC_MHM1 && audio_format != FOURCC_MHA1 &&
 #endif
           audio_format != FOURCC_MP4A) {
-        MEDIA_LOG(ERROR, media_log_)
-            << "Unsupported audio format 0x" << std::hex << entry.format
-            << " in stsd box.";
+        LOG(ERROR) << "Unsupported audio format 0x" << std::hex << entry.format
+                   << " in stsd box.";
         return false;
       }
 
@@ -494,6 +496,12 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
             audio_type = kEAC3;
         }
 #endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+        if (audio_type == kForbidden) {
+          if (audio_format == FOURCC_AC4)
+            audio_type = kAC4;
+        }
+#endif
 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
         if (audio_type == kForbidden) {
           if (audio_format == FOURCC_DTSC)
@@ -540,6 +548,15 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
               GuessChannelLayout(entry.eac3.dec3.GetChannelCount());
           sample_per_second = entry.samplerate;
 #endif
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+        } else if (audio_type == kAC4) {
+          codec = AudioCodec::kAC4;
+          channel_layout = GuessChannelLayout(entry.channelcount);
+          channel_layout = channel_layout == CHANNEL_LAYOUT_UNSUPPORTED
+                               ? CHANNEL_LAYOUT_BITSTREAM
+                               : channel_layout;
+          sample_per_second = entry.samplerate;
+#endif
 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
         } else if (audio_type == kDTS) {
           codec = AudioCodec::kDTS;
@@ -557,9 +574,8 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
           sample_per_second = entry.samplerate;
 #endif
         } else {
-          MEDIA_LOG(ERROR, media_log_)
-              << "Unsupported audio object type 0x" << std::hex
-              << static_cast<int>(audio_type) << " in esds.";
+          LOG(ERROR) << "Unsupported audio object type 0x" << std::hex
+                     << static_cast<int>(audio_type) << " in esds.";
           return false;
         }
 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -1068,6 +1084,16 @@ ParseResult MP4StreamParser::EnqueueSample(BufferQueueMap* buffers) {
   }
 
   if (audio) {
+    FourCC audio_format = (runs_->audio_description().format == FOURCC_ENCA)
+                              ? runs_->audio_description().sinf.format.format
+                              : runs_->audio_description().format;
+    uint8_t audio_type = runs_->audio_description().esds.object_type;
+#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
+    if (audio_type == kForbidden) {
+      if (audio_format == FOURCC_AC4)
+        audio_type = kAC4;
+    }
+#endif
     if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type)) {
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
       if (!PrepareAACBuffer(runs_->audio_description().esds.aac, &frame_buf,
index dbd5220be6d4ab8fd17d80425bfeed4f1cc8259d..b38b561ba6d9383aa8d1b0ba4ae75268b4e9ac7c 100644 (file)
@@ -77,9 +77,9 @@ declare_args() {
 
   # Enables AC4 audio handling in chromium. This includes demuxing,
   # on-device decoding and bitstream passthrough as supported by device.
-  enable_platform_ac4_audio = false
+  enable_platform_ac4_audio = proprietary_codecs && (is_cast_media_device || tizen_product_tv)
 
-  enable_platform_mpeg_h_audio = proprietary_codecs && is_cast_media_device
+  enable_platform_mpeg_h_audio = proprietary_codecs && (is_cast_media_device || tizen_product_tv)
 
   # Enables DTS/DTSX audio handling in chromium. This includes demuxing,
   # on-device decoding and bitstream passthrough as supported by device.
index dce6d2b2474109886f1ea154601a72165c48b05f..637195a237a834c7ed82956721e35c347ea48d97 100644 (file)
@@ -104,6 +104,11 @@ esplusplayer_audio_mime_type ConvertToESPlusAudioMimeType(
     case media::AudioCodec::kAC3:
       audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_AC3;
       break;
+#if BUILDFLAG(IS_TIZEN_TV)
+    case media::AudioCodec::kAC4:
+      audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_AC4;
+      break;
+#endif
 #if BUILDFLAG(IS_TIZEN_TV) && TIZEN_VERSION_AT_LEAST(8, 0, 0)
     case media::AudioCodec::kFLAC:
       audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_FLAC;