From patchwork Fri Nov 23 13:10:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 11130 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 14A2B44E0CC for ; Fri, 23 Nov 2018 15:18:21 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8A8B868A1F0; Fri, 23 Nov 2018 15:18:21 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E36C5689F27 for ; Fri, 23 Nov 2018 15:18:14 +0200 (EET) Received: by mail-wr1-f65.google.com with SMTP id z5so8018195wrt.11 for ; Fri, 23 Nov 2018 05:18:18 -0800 (PST) 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; bh=0vK4KLHQuaLiSIk6iafbxo++k5W3UBr7fPVT/9G8+yI=; b=UVT5lunfyVLJXguQGjlwb3FpXVEOICT5BB51q9OQiW6khRqb+qD2xfEZFVXR1kc8ud Zrp1pxiadvJ47YMpYges0eZ4w8G8BHlnFbbJcAIbIEfHSLIhF1IlRUDneOyVd7L3WCYB 7+XTm6zJTXN8YiETSetRHjhghGDQehfemM8nzOxOfueNETRWcanswTkKezcKXUSf4wfr 34Jf8LWw1Lv/7bJW+AlZVjpli6Jc9pIyrvjPL2Zzf5XvC1VRkJHdsV3DOEA2ceoavnSP jq5JQJgt31ukX6i/ZqmOP451S9jsWUfbFm2WHAm8w9dZk+Rg9vQB11U7RiuZIhvbSW2p O4QA== 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; bh=0vK4KLHQuaLiSIk6iafbxo++k5W3UBr7fPVT/9G8+yI=; b=fc/8IlyETeDQU8fbwyls9NzQp95k8YVcCqXNrtINGf7AsXjf8+F46OOJBhLJm2QX08 i05lbBs2qS5/+3VMOeCcrlXkIxgQOZmqESlXUlVBTauUR3GxjAJUwH1puQqRjgnRBD5H dlvv/yaQwhebNa+vour5dT0leB79NvKrmkjPsQzz1nnll2/Q1vjdYMhr3zyMIooYMx+n o15uuvZhhetN8x9l7NXvS7Z5AT0GjFLlhKfQV6SgH6vIz28wIBV072jp4XV9gVX7nLpM LlBYKHr6oK4ZlCF2XWHrdjNc5fj6B2vFHpjPuaC9dOK6QFP/sgBr6whv+cxwjSJ2DsR/ +W4Q== X-Gm-Message-State: AA+aEWZxiRM6bN/XdKbSVObnEL47SXVUR5viTlGtGzfJp4MobJirbxuJ K8OJReo4H+OMSNbuz5Q5a4nmYYES X-Google-Smtp-Source: AFSGD/VvrBBoToi9TYtYX0DY1r6RPDP8pUNVVg7JficYZbzC3lHSEXAuvEWrn+EX5go7XhNK9poNKA== X-Received: by 2002:adf:e247:: with SMTP id n7mr13325484wri.205.1542978739968; Fri, 23 Nov 2018 05:12:19 -0800 (PST) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id 11-v6sm8116709wms.24.2018.11.23.05.10.49 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Nov 2018 05:10:49 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Fri, 23 Nov 2018 14:10:41 +0100 Message-Id: <20181123131041.28622-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181122202423.14452-1-onemda@gmail.com> References: <20181122202423.14452-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH] avformat: add DHAV demuxer 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Timestamps and seeking still broken. Signed-off-by: Paul B Mahol --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/dhav.c | 237 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 libavformat/dhav.c diff --git a/libavformat/Makefile b/libavformat/Makefile index e4d997c4a0..a6c5ea9aa3 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -149,6 +149,7 @@ OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o +OBJS-$(CONFIG_DHAV_DEMUXER) += dhav.o OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddec.o rawdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 498077e1de..5fb5bf17c6 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -110,6 +110,7 @@ extern AVInputFormat ff_daud_demuxer; extern AVOutputFormat ff_daud_muxer; extern AVInputFormat ff_dcstr_demuxer; extern AVInputFormat ff_dfa_demuxer; +extern AVInputFormat ff_dhav_demuxer; extern AVInputFormat ff_dirac_demuxer; extern AVOutputFormat ff_dirac_muxer; extern AVInputFormat ff_dnxhd_demuxer; diff --git a/libavformat/dhav.c b/libavformat/dhav.c new file mode 100644 index 0000000000..0bfd42bdec --- /dev/null +++ b/libavformat/dhav.c @@ -0,0 +1,237 @@ +/* + * DHAV demuxer + * + * Copyright (c) 2018 Paul B Mahol + * + * 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 "libavutil/avassert.h" +#include "avformat.h" +#include "internal.h" + +typedef struct DHAVContext { + unsigned type; + int width, height; + int video_codec; + int frame_rate; + int sample_rate; + int64_t pts; + + int video_stream_index; + int audio_stream_index; +} DHAVContext; + +static int dhav_probe(AVProbeData *p) +{ + if (memcmp(p->buf, "DHAV", 4)) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int dhav_read_header(AVFormatContext *s) +{ + DHAVContext *dhav = s->priv_data; + + s->ctx_flags |= AVFMTCTX_NOHEADER; + dhav->video_stream_index = -1; + dhav->audio_stream_index = -1; + + return 0; +} + +static const uint16_t sample_rates[] = { + 8000, 4000, 8000, 11025, 16000, + 20000, 22050, 32000, 44100, 48000, +}; + +static int parse_ext(AVFormatContext *s, int length) +{ + DHAVContext *dhav = s->priv_data; + int index; + + while (length > 0) { + int type = avio_r8(s->pb); + + switch (type) { + case 0x80: + avio_skip(s->pb, 1); + dhav->width = 8 * avio_r8(s->pb); + dhav->height = 8 * avio_r8(s->pb); + length -= 4; + break; + case 0x81: + avio_skip(s->pb, 1); + dhav->video_codec = avio_r8(s->pb); + dhav->frame_rate = avio_r8(s->pb); + length -= 4; + break; + case 0x82: + avio_skip(s->pb, 3); + dhav->width = avio_rl16(s->pb); + dhav->height = avio_rl16(s->pb); + length -= 8; + break; + case 0x83: + avio_skip(s->pb, 2); + index = avio_r8(s->pb); + if (index < 10) { + dhav->sample_rate = sample_rates[index]; + } else { + dhav->sample_rate = 8000; + } + length -= 4; + break; + case 0x88: + avio_skip(s->pb, 7); + length -= 8; + break; + case 0x91: + case 0x92: + case 0x93: + case 0x95: + case 0x9a: + avio_skip(s->pb, 7); + length -= 8; + break; + case 0x8b: + case 0x94: + case 0x96: + avio_skip(s->pb, 3); + length -= 4; + break; + default: + av_log(s, AV_LOG_INFO, "Unknown type: %X, skipping rest of header.\n", type); + avio_skip(s->pb, length - 1); + length = 0; + } + } + + return 0; +} + +static int read_chunk(AVFormatContext *s) +{ + DHAVContext *dhav = s->priv_data; + unsigned size, skip; + int64_t start, end; + int ret; + + start = avio_tell(s->pb); + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + if (avio_rl32(s->pb) != MKTAG('D','H','A','V')) + return AVERROR_INVALIDDATA; + + dhav->type = avio_r8(s->pb); + avio_skip(s->pb, 3); + dhav->pts = avio_rl32(s->pb); + size = avio_rl32(s->pb); + if (size < 24) + return AVERROR_INVALIDDATA; + if (dhav->type == 0xf1) { + avio_skip(s->pb, size - 16); + return 0; + } + + avio_rl32(s->pb); + avio_skip(s->pb, 2); + skip = avio_r8(s->pb); + avio_skip(s->pb, 1); + + ret = parse_ext(s, skip); + if (ret < 0) + return ret; + + end = avio_tell(s->pb); + + return size - 8 - (end - start); +} + +static int dhav_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DHAVContext *dhav = s->priv_data; + int64_t start; + int ret; + + start = avio_tell(s->pb); + + while ((ret = read_chunk(s)) == 0) + ; + + if (ret < 0) + return ret; + + if (dhav->type == 0xfd && dhav->video_stream_index == -1) { + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + switch (dhav->video_codec) { + case 0x8: st->codecpar->codec_id = AV_CODEC_ID_H264; break; + case 0xc: st->codecpar->codec_id = AV_CODEC_ID_HEVC; break; + } + st->codecpar->width = dhav->width; + st->codecpar->height = dhav->height; + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + dhav->video_stream_index = st->index; + + avpriv_set_pts_info(st, 64, 1, dhav->frame_rate); + } else if (dhav->type == 0xf0 && dhav->audio_stream_index == -1) { + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; + st->codecpar->channels = 1; + st->codecpar->sample_rate = dhav->sample_rate; + dhav->audio_stream_index = st->index; + + avpriv_set_pts_info(st, 64, 320, dhav->sample_rate); + } + + ret = av_get_packet(s->pb, pkt, ret); + if (ret < 0) + return ret; + pkt->stream_index = dhav->type == 0xf0 ? dhav->audio_stream_index : dhav->video_stream_index; + pkt->duration = 1; + pkt->pts = dhav->pts; + pkt->pos = start; + if (avio_rl32(s->pb) != MKTAG('d','h','a','v')) + return AVERROR_INVALIDDATA; + avio_skip(s->pb, 4); + + return ret; +} + +AVInputFormat ff_dhav_demuxer = { + .name = "dhav", + .long_name = NULL_IF_CONFIG_SMALL("DHAV"), + .priv_data_size = sizeof(DHAVContext), + .read_probe = dhav_probe, + .read_header = dhav_read_header, + .read_packet = dhav_read_packet, + .extensions = "dav", + .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, +};