From patchwork Fri Aug 16 21:17:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 14558 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id CAD89449DD1 for ; Sat, 17 Aug 2019 00:18:00 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B2BF768ACDD; Sat, 17 Aug 2019 00:18:00 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qt1-f195.google.com (mail-qt1-f195.google.com [209.85.160.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9306668AC85 for ; Sat, 17 Aug 2019 00:17:53 +0300 (EEST) Received: by mail-qt1-f195.google.com with SMTP id y26so7627341qto.4 for ; Fri, 16 Aug 2019 14:17:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=aeIYtLpwSt0ER0TsmcMxtgbQRPYf/frdrLOQnoutcFw=; b=mRj8KRWybpl4SXpbvio0KcF78gZ7p7WQsj5YeI/X8teQyFHo+ngg3UAWGJGBCJS7FJ /1d8WCYwTf/f2s5HoLw7q8Dhb05AkSJX+TgW3zilOCH+OKK38TLYqfXDtO5CrLV27apu oQif3LeGwdU9QbSDukgjECEu7JINkShPOcXwpHFVnXx2hDaETOzfrdmFr9mx8CxrGoGV nBkhAqdQVKUyBThaM8rAE0I9DgC+wg6k++J1phkgkOWMaxlyn50/4vExompKhoD4oKOn m2r6sUuEC+SVeqMOJuitMbN72Jm1DYXQejorEyjj+Pr4CLSL7UJnAZqOBB0waZwmc2VH Zwtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aeIYtLpwSt0ER0TsmcMxtgbQRPYf/frdrLOQnoutcFw=; b=YR+xEj1PBMiaFpdRcyca6XPGlzpuopGkt3mUXoIEJTFo9faGic7nOOd9oK+oUpX7Bp QsbXYfHVFIGB6GVY9o2ClHgyZGiCJuM+MascYAZz1OOut2NaYfyDlW/+zJ5UO/w+bY87 7ak2UK06aJQjRJvgBoQWk5NG0Z9GGVJyK/ZBle5HzcdLsu/d1cA0R2jawrxQUkd/KCVa 2mxmdFpaENHbVEUFwFlp4uVTIBe0vxg2tpZ94MjTO5uPXxedDhWnQou9na/LNcqBaDK9 1NDFeXEnh86CvWBHY7ObP9JO8RDG0QnluGYFhsFnScdVIju5UA5NPozHqiJuKvIPAOHP 0ZZw== X-Gm-Message-State: APjAAAVZFagYg5hUss6WOrxrtG2rv4CWjjqvxrEXdwXpw9v9lpVeBB8Z eyO8yR7bPUBq3OrBLv1Zsq2Ckci5 X-Google-Smtp-Source: APXvYqyqguf1mlDKkBz50cP0GUoS/pPbrCU+jBiSSCVcC78Phj1kaLH3BQSKbt++z/sZRHsOdiQ7eA== X-Received: by 2002:a0c:d25c:: with SMTP id o28mr3243384qvh.211.1565990272035; Fri, 16 Aug 2019 14:17:52 -0700 (PDT) Received: from localhost.localdomain ([181.23.95.42]) by smtp.gmail.com with ESMTPSA id d9sm3497714qko.20.2019.08.16.14.17.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2019 14:17:51 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Fri, 16 Aug 2019 18:17:12 -0300 Message-Id: <20190816211712.1255-4-jamrial@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190816211712.1255-1-jamrial@gmail.com> References: <20190816211712.1255-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] avformat/movenc: add muxing support for Dolby TrueHD streams X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: James Almer --- libavformat/movenc.c | 61 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a96139077b..adb5cd0e5a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -771,6 +771,35 @@ static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } +static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + int length; + avio_wb32(pb, 0); + ffio_wfourcc(pb, "dmlp"); + + if (track->vos_len < 20) { + av_log(s, AV_LOG_ERROR, + "Cannot write moov atom before TrueHD packets." + " Set the delay_moov flag to fix this.\n"); + return AVERROR(EINVAL); + } + + length = (AV_RB16(track->vos_data) & 0xFFF) * 2; + if (length < 20 || length > track->vos_len) + return AVERROR_INVALIDDATA; + + // Only TrueHD is supported + if (AV_RB32(track->vos_data + 4) != 0xF8726FBA) + return AVERROR_INVALIDDATA; + + avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */ + avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */ + avio_wb32(pb, 0); /* reserved */ + + return update_size(pb, pos); +} + static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { uint32_t layout_tag, bitmap; @@ -1100,10 +1129,14 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb16(pb, 0); /* packet size (= 0) */ if (track->par->codec_id == AV_CODEC_ID_OPUS) avio_wb16(pb, 48000); + else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) + avio_wb32(pb, track->par->sample_rate); else avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ? track->par->sample_rate : 0); - avio_wb16(pb, 0); /* Reserved */ + + if (track->par->codec_id != AV_CODEC_ID_TRUEHD) + avio_wb16(pb, 0); /* Reserved */ } if (version == 1) { /* SoundDescription V1 extended info */ @@ -1145,6 +1178,8 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex ret = mov_write_dfla_tag(pb, track); else if (track->par->codec_id == AV_CODEC_ID_OPUS) ret = mov_write_dops_tag(s, pb, track); + else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) + ret = mov_write_dmlp_tag(s, pb, track); else if (track->vos_len > 0) ret = mov_write_glbl_tag(pb, track); @@ -2456,6 +2491,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext return ret; mov_write_stts_tag(pb, track); if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO || + track->par->codec_id == AV_CODEC_ID_TRUEHD || track->par->codec_tag == MKTAG('r','t','p',' ')) && track->has_keyframes && track->has_keyframes < track->entry) mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); @@ -4963,6 +4999,25 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk) } } +static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk) +{ + int length; + + if (pkt->size < 8) + return; + + length = (AV_RB16(pkt->data) & 0xFFF) * 2; + if (length < 8 || length > pkt->size) + return; + + if (AV_RB32(pkt->data + 4) == 0xF8726FBA) { + trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE; + trk->has_keyframes++; + } + + return; +} + static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track) { MOVMuxContext *mov = s->priv_data; @@ -5400,6 +5455,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } if ((par->codec_id == AV_CODEC_ID_DNXHD || + par->codec_id == AV_CODEC_ID_TRUEHD || par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { /* copy frame to create needed atoms */ trk->vos_len = size; @@ -5509,6 +5565,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_VC1) { mov_parse_vc1_frame(pkt, trk); + } else if (par->codec_id == AV_CODEC_ID_TRUEHD) { + mov_parse_truehd_frame(pkt, trk); } else if (pkt->flags & AV_PKT_FLAG_KEY) { if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO && trk->entry > 0) { // force sync sample for the first key frame @@ -6802,6 +6860,7 @@ const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_AC3 , MKTAG('a', 'c', '-', '3') }, { AV_CODEC_ID_EAC3 , MKTAG('e', 'c', '-', '3') }, { AV_CODEC_ID_DTS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_TRUEHD , MKTAG('m', 'l', 'p', 'a') }, { AV_CODEC_ID_FLAC , MKTAG('f', 'L', 'a', 'C') }, { AV_CODEC_ID_OPUS , MKTAG('O', 'p', 'u', 's') }, { AV_CODEC_ID_VORBIS , MKTAG('m', 'p', '4', 'a') },