Add ff v5.1.2

This commit is contained in:
Jan Stabenow
2022-11-04 00:55:10 +01:00
parent ff979fcf51
commit 82a2e97175
16 changed files with 768 additions and 235 deletions

View File

@@ -58,7 +58,7 @@ jobs:
context: .
file: ./Dockerfile.alpine.rpi
build-args: |
ALPINE_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
BUILD_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
FREETYPE_VERSION=${{ env.FREETYPE_VERSION }}
XML2_VERSION=${{ env.XML2_VERSION }}
SRT_VERSION=${{ env.SRT_VERSION }}
@@ -70,6 +70,7 @@ jobs:
VORBIS_VERSION=${{ env.VORBIS_VERSION }}
FFMPEG_VERSION=${{ env.FFMPEG_VERSION }}
RPI_VERSION=${{ env.RPI_VERSION }}
ALSA_VERSION=${{ env.ALSA_VERSION }}
platforms: linux/arm64, linux/arm/v7
push: true
tags: |

View File

@@ -58,7 +58,7 @@ jobs:
context: .
file: ./Dockerfile.alpine.vaapi
build-args: |
ALPINE_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
BUILD_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
FREETYPE_VERSION=${{ env.FREETYPE_VERSION }}
XML2_VERSION=${{ env.XML2_VERSION }}
SRT_VERSION=${{ env.SRT_VERSION }}

View File

@@ -51,7 +51,7 @@ jobs:
context: .
file: ./Dockerfile.alpine
build-args: |
ALPINE_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
BUILD_IMAGE=${{ env.OS_NAME }}:${{ env.OS_VERSION }}
FREETYPE_VERSION=${{ env.FREETYPE_VERSION }}
XML2_VERSION=${{ env.XML2_VERSION }}
SRT_VERSION=${{ env.SRT_VERSION }}

View File

@@ -1,15 +1,15 @@
# FFMPEG BASE PACKAGES
OS_NAME=alpine
OS_VERSION=3.15
FREETYPE_VERSION=2.11.1-r2
XML2_VERSION=2.9.14-r0
SRT_VERSION=1.4.2-r1
X264_VERSION=20210613-r0
X265_VERSION=3.5-r0
VPX_VERSION=1.10.0-r0
OS_VERSION=3.16
FREETYPE_VERSION=2.12.1-r0
XML2_VERSION=2.9.14-r2
SRT_VERSION=1.4.4-r0
X264_VERSION=0.163_git20210613-r0
X265_VERSION=3.5-r3
VPX_VERSION=1.11.0-r1
LAME_VERSION=3.100-r0
OPUS_VERSION=1.3.1-r1
VORBIS_VERSION=1.3.7-r0
FBDEV_VERSION=0.5.0-r3
V4L_VERSION=1.22.1-r1
FFMPEG_VERSION=5.0.1
FFMPEG_VERSION=5.1.2

View File

@@ -1,2 +1,4 @@
# FFMPEG RPI PACKAGES
RPI_VERSION=0.20200813-r0
RPI_VERSION=0.20200813-r1
ALSA_VERSION=1.2.7.2-r0

View File

@@ -1,10 +1,10 @@
# FFMPEG VAAPI PACKAGES
LIBAV_VERSION=2.14.0-r0
LIBVDPAU_VERSION=1.5-r0
MESA_VA_GALLIUM_VERSION=21.3.8-r1
MESA_VDPAU_GALLIUM_VERSION=21.3.8-r1
MESA_VA_GALLIUM_VERSION=22.2.2-r2
MESA_VDPAU_GALLIUM_VERSION=22.2.2-r2
LIBVA_VDPAU_DRIVER_VERSION=0.7.4-r2
INTEL_GMMLIB_VERSION=22.1.3-r0
INTEL_MEDIA_DRIVER_VERSION=22.4.2-r0
INTEL_MEDIA_SDK_VERSION=22.4.2-r0
INTEL_MEDIA_DRIVER_VERSION=22.6.1-r0
INTEL_MEDIA_SDK_VERSION=22.5.4-r0
INTEL_VAAPI_DRIVER=2.4.1-r0

132
Build.sh Executable file
View File

@@ -0,0 +1,132 @@
#!/bin/bash
set -au
function source_env() {
env=${1:-.env}
[ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; }
eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}")
}
function build_default() {
source_env ./Build.alpine.env
# "--load" does not support multiple platforms
# use "--push" to publish
# --platform linux/amd64,linux/arm64,linux/arm/v7
docker buildx build \
--load \
--build-arg BUILD_IMAGE=$OS_NAME:$OS_VERSION \
--build-arg FREETYPE_VERSION=$FREETYPE_VERSION \
--build-arg XML2_VERSION=$XML2_VERSION \
--build-arg SRT_VERSION=$SRT_VERSION \
--build-arg X264_VERSION=$X264_VERSION \
--build-arg X265_VERSION=$X265_VERSION \
--build-arg VPX_VERSION=$VPX_VERSION \
--build-arg LAME_VERSION=$LAME_VERSION \
--build-arg OPUS_VERSION=$OPUS_VERSION \
--build-arg VORBIS_VERSION=$VORBIS_VERSION \
--build-arg FFMPEG_VERSION=$FFMPEG_VERSION \
--platform linux/amd64 \
-f Dockerfile.alpine \
-t datarhei/base:$OS_NAME-ffmpeg-$OS_VERSION-$FFMPEG_VERSION .
}
function build_rpi() {
source_env ./Build.alpine.env
source_env ./Build.alpine.rpi.env
# "--load" does not support multiple platforms
# use "--push" to publish
# --platform linux/arm64,linux/arm/v7
docker buildx build \
--load \
--build-arg BUILD_IMAGE=$OS_NAME:$OS_VERSION \
--build-arg FREETYPE_VERSION=$FREETYPE_VERSION \
--build-arg XML2_VERSION=$XML2_VERSION \
--build-arg SRT_VERSION=$SRT_VERSION \
--build-arg X264_VERSION=$X264_VERSION \
--build-arg X265_VERSION=$X265_VERSION \
--build-arg VPX_VERSION=$VPX_VERSION \
--build-arg LAME_VERSION=$LAME_VERSION \
--build-arg OPUS_VERSION=$OPUS_VERSION \
--build-arg VORBIS_VERSION=$VORBIS_VERSION \
--build-arg FFMPEG_VERSION=$FFMPEG_VERSION \
--build-arg RPI_VERSION=$RPI_VERSION \
--build-arg ALSA_VERSION=$ALSA_VERSION \
--platform linux/arm64 \
-f Dockerfile.alpine.rpi \
-t datarhei/base:$OS_NAME-ffmpeg-rpi-$OS_VERSION-$FFMPEG_VERSION .
}
function build_cuda() {
source_env ./Build.ubuntu.env
source_env ./Build.ubuntu.cuda.env
docker buildx build \
--load \
--build-arg BUILD_IMAGE=nvidia/cuda:$CUDA_VERSION-devel-$OS_NAME$OS_VERSION \
--build-arg DEPLOY_IMAGE=nvidia/cuda:$CUDA_VERSION-runtime-$OS_NAME$OS_VERSION \
--build-arg FFNVCODEC_VERSION=$FFNVCODEC_VERSION \
--build-arg FREETYPE_VERSION=$FREETYPE_VERSION \
--build-arg XML2_VERSION=$XML2_VERSION \
--build-arg SRT_VERSION=$SRT_VERSION \
--build-arg X264_VERSION=$X264_VERSION \
--build-arg X265_VERSION=$X265_VERSION \
--build-arg VPX_VERSION=$VPX_VERSION \
--build-arg LAME_VERSION=$LAME_VERSION \
--build-arg OPUS_VERSION=$OPUS_VERSION \
--build-arg VORBIS_VERSION=$VORBIS_VERSION \
--build-arg FFMPEG_VERSION=$FFMPEG_VERSION \
--platform linux/amd64 \
-f Dockerfile.ubuntu.cuda \
-t datarhei/base:$OS_NAME-ffmpeg-cuda-$OS_VERSION-$FFMPEG_VERSION-$CUDA_VERSION .
}
function build_vaapi() {
source_env ./Build.alpine.env
source_env ./Build.alpine.vaapi.env
docker buildx build \
--load \
--build-arg BUILD_IMAGE=$OS_NAME:$OS_VERSION \
--build-arg FREETYPE_VERSION=$FREETYPE_VERSION \
--build-arg XML2_VERSION=$XML2_VERSION \
--build-arg SRT_VERSION=$SRT_VERSION \
--build-arg X264_VERSION=$X264_VERSION \
--build-arg X265_VERSION=$X265_VERSION \
--build-arg VPX_VERSION=$VPX_VERSION \
--build-arg LAME_VERSION=$LAME_VERSION \
--build-arg OPUS_VERSION=$OPUS_VERSION \
--build-arg VORBIS_VERSION=$VORBIS_VERSION \
--build-arg FFMPEG_VERSION=$FFMPEG_VERSION \
--build-arg LIBAV_VERSION=$LIBAV_VERSION \
--build-arg LIBVDPAU_VERSION=$LIBVDPAU_VERSION \
--build-arg MESA_VA_GALLIUM_VERSION=$MESA_VA_GALLIUM_VERSION \
--build-arg MESA_VDPAU_GALLIUM_VERSION=$MESA_VDPAU_GALLIUM_VERSION \
--build-arg LIBVA_VDPAU_DRIVER_VERSION=$LIBVA_VDPAU_DRIVER_VERSION \
--build-arg INTEL_GMMLIB_VERSION=$INTEL_GMMLIB_VERSION \
--build-arg INTEL_MEDIA_DRIVER_VERSION=$INTEL_MEDIA_DRIVER_VERSION \
--build-arg INTEL_MEDIA_SDK_VERSION=$INTEL_MEDIA_SDK_VERSION \
--build-arg INTEL_VAAPI_DRIVER=$INTEL_VAAPI_DRIVER \
--platform linux/amd64 \
-f Dockerfile.alpine.vaapi \
-t datarhei/base:$OS_NAME-ffmpeg-vaapi-$OS_VERSION-$FFMPEG_VERSION .
}
main() {
if [[ $# == 0 ]]; then
echo "Options available: default, rpi, cuda, vaapi"
exit 0
else
if [[ $1 == "default" ]]; then
build_default
elif [[ $1 == "rpi" ]]; then
build_rpi
elif [[ $1 == "cuda" ]]; then
build_cuda
elif [[ $1 == "vaapi" ]]; then
build_vaapi
fi
fi
}
main $@
exit 0

View File

@@ -1,3 +1,3 @@
# FFMPEG CUDA PACKAGES
CUDA_VERSION=11.4.2
FFNVCODEC_VERSION=11.1.5.1
CUDA_VERSION=11.7.1
FFNVCODEC_VERSION=11.1.5.2

View File

@@ -1,14 +1,14 @@
# FFMPEG BASE PACKAGES
OS_NAME=ubuntu
OS_VERSION=20.04
FREETYPE_VERSION=2.10.4
ENV LIBXML2_VERSION=2.9.14
FREETYPE_VERSION=2.12.1
XML2_VERSION=2.9.14
SRT_VERSION=1.4.4
X264_VERSION=stable
X265_VERSION=3.4
VPX_VERSION=1.11.0
VPX_VERSION=1.12.0
LAME_VERSION=3.100
OPUS_VERSION=1.3.1
OGG_VERSION=1.3.5
VORBIS_VERSION=1.3.7
FFMPEG_VERSION=5.0.1
FFMPEG_VERSION=5.1.2

View File

@@ -1,6 +1,6 @@
ARG ALPINE_IMAGE=alpine:3.15
ARG BUILD_IMAGE=alpine:3.15
FROM $ALPINE_IMAGE as builder
FROM $BUILD_IMAGE as builder
ARG FREETYPE_VERSION=2.11.1-r2
ARG XML2_VERSION=2.9.14-r0
@@ -106,10 +106,11 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libpng16.so.16 \
/usr/lib/libxml2.so.2 \
/usr/lib/liblzma.so.5 \
/usr/lib/libsrt.so.1 \
/usr/lib/libsrt.so.1.4 \
/usr/lib/libx264.so.163 \
/usr/lib/libx265.so.199 \
/usr/lib/libvpx.so.6 \
/usr/lib/libnuma.so.1 \
/usr/lib/libvpx.so.7 \
/usr/lib/libmp3lame.so.0 \
/usr/lib/libopus.so.0 \
/usr/lib/libvorbis.so.0 \
@@ -119,7 +120,7 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libstdc++.so.6 \
/ffmpeg/lib
FROM $ALPINE_IMAGE as final
FROM $BUILD_IMAGE as final
COPY --from=builder /usr/bin/ffmpeg /usr/bin/ffmpeg
COPY --from=builder /ffmpeg/lib/* /usr/lib/

View File

@@ -1,8 +1,9 @@
ARG ALPINE_IMAGE=alpine:3.15
ARG BUILD_IMAGE=alpine:3.15
FROM $ALPINE_IMAGE as builder
FROM $BUILD_IMAGE as builder
ARG RPI_VERSION=0.20200813-r0
ARG ALSA_VERSION=1.2.5.1-r1
ARG FREETYPE_VERSION=2.11.1-r1
ARG XML2_VERSION=2.9.13-r0
@@ -13,7 +14,6 @@ ARG VPX_VERSION=1.10.0-r0
ARG LAME_VERSION=3.100-r0
ARG OPUS_VERSION=1.3.1-r1
ARG VORBIS_VERSION=1.3.7-r0
ARG ALSA_VERSION=1.2.5.1-r1
ARG FBDEV_VERSION=0.5.0-r3
ARG V4L_VERSION=1.22.1-r1
ARG FFMPEG_VERSION=4.4.2
@@ -120,10 +120,11 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libpng16.so.16 \
/usr/lib/libxml2.so.2 \
/usr/lib/liblzma.so.5 \
/usr/lib/libsrt.so.1 \
/usr/lib/libsrt.so.1.4 \
/usr/lib/libx264.so.163 \
/usr/lib/libx265.so.199 \
/usr/lib/libvpx.so.6 \
/usr/lib/libnuma.so.1 \
/usr/lib/libvpx.so.7 \
/usr/lib/libmp3lame.so.0 \
/usr/lib/libopus.so.0 \
/usr/lib/libvorbis.so.0 \
@@ -133,7 +134,7 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libstdc++.so.6 \
/ffmpeg/lib
FROM $ALPINE_IMAGE as final
FROM $BUILD_IMAGE as final
COPY --from=builder /usr/bin/ffmpeg /usr/bin/ffmpeg
COPY --from=builder /ffmpeg/lib/* /usr/lib/

View File

@@ -1,6 +1,6 @@
ARG ALPINE_IMAGE=alpine:3.15
ARG BUILD_IMAGE=alpine:3.15
FROM $ALPINE_IMAGE as builder
FROM $BUILD_IMAGE as builder
ARG LIBAV_VERSION=2.14.0-r0
ARG LIBVDPAU_VERSION=1.5-r0
@@ -135,10 +135,11 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libbrotlicommon.so.1 \
/usr/lib/libbz2.so.1 \
/usr/lib/libpng16.so.16 \
/usr/lib/libsrt.so.1 \
/usr/lib/libsrt.so.1.4 \
/usr/lib/libx264.so.163 \
/usr/lib/libx265.so.199 \
/usr/lib/libvpx.so.6 \
/usr/lib/libnuma.so.1 \
/usr/lib/libvpx.so.7 \
/usr/lib/libmp3lame.so.0 \
/usr/lib/libopus.so.0 \
/usr/lib/libvorbis.so.0 \
@@ -164,7 +165,7 @@ RUN mkdir -p /ffmpeg/lib && \
/usr/lib/libva-x11.so.2 \
/ffmpeg/lib
FROM $ALPINE_IMAGE as final
FROM $BUILD_IMAGE as final
COPY --from=builder /usr/bin/ffmpeg /usr/bin/ffmpeg
COPY --from=builder /ffmpeg/lib/* /usr/lib/

View File

@@ -2,7 +2,7 @@
FFmpeg base image for [datarhei/core](https://github.com/datarhei/core).
Branch: 5.0
Branch: 5.1
## Config:
@@ -29,23 +29,26 @@ _Additional informations can be found in the Dockerfiles._
| Dockerimage | OS | Plattform | GPU |
| -------------------------------------------------- | ------------ | ---------------------------------------- | ------------------------------------------- |
| docker.io/datarhei/base:alpine-ffmpeg-latest | Alpine 3.15 | linux/amd64, linux/arm64, linux/arm/v7 | - |
| docker.io/datarhei/base:alpine-ffmpeg-rpi-latest | Alpine 3.15 | Raspberry Pi (linux/arm/v7, linux/arm64) | MMAL/OMX/V4L2-M2M (32bit), V4L2-M2M (64bit) |
| docker.io/datarhei/base:alpine-ffmpeg-vaapi-latest | Alpine 3.15 | linux/amd64 | Intel VAAPI |
| docker.io/datarhei/base:ubuntu-ffmpeg-cuda-latest | Ubuntu 20.03 | linux/amd64 | Nvidia Cuda |
| docker.io/datarhei/base:alpine-ffmpeg-5.1.2 | Alpine 3.16 | linux/amd64, linux/arm64, linux/arm/v7 | - |
| docker.io/datarhei/base:alpine-ffmpeg-rpi-5.1.2 | Alpine 3.16 | Raspberry Pi (linux/arm/v7, linux/arm64) | MMAL/OMX/V4L2-M2M (32bit), V4L2-M2M (64bit) |
| docker.io/datarhei/base:alpine-ffmpeg-vaapi-5.1.2 | Alpine 3.16 | linux/amd64 | Intel VAAPI |
| docker.io/datarhei/base:ubuntu-ffmpeg-cuda-5.1.2 | Ubuntu 20.03 | linux/amd64 | Nvidia Cuda |
More tags: https://hub.docker.com/repository/docker/datarhei/base/general
## Testing
## Build & test
```sh
$ docker buildx create builder
$ docker buildx use builder
$ docker buildx inspect builder --bootstrap
$ docker buildx build --platform linux/amd64 linux/arm64 linux/arm/v7 -f Dockerfile -t ffmpeg:dev --load .
$ docker buildx rm builder
$ git clone github.com/datarhei/ffmpeg
$ ./Build.sh {arg}
```
Args:
- default (alpine-ffmpeg-latest)
- rpi (alpine-ffmpeg-rpi-latest)
- vaapi (alpine-ffmpeg-vaapi-latest)
- cuda (ubuntu-ffmpeg-cuda-latest)
## Known problems:
The libraries are currently not compiled due to errors caused by Docker virtualisation.

98
contrib/README.md Normal file
View File

@@ -0,0 +1,98 @@
# Patches
FFmpeg patches.
## HLS bitrate
Calculate bandwidth estimate for the hls master manifest.
## JSON stats
This repository contains a patch for the FFmpeg program to provide detailed progress information. With this patch, FFmpeg will output
the progress information in a JSON string that contains the data for each input and output stream individually. The JSON output is enabled
by default. It can be enabled with the global `-jsonstats` switch on the command line. Use the `-stats` switch
on the command line for the standard progress output.
Example output with `-stats`:
```
frame= 143 fps= 25 q=-1.0 Lsize= 941kB time=00:00:05.68 bitrate=1357.0kbits/s speed=0.995x
```
Example output with `-jsonstats`:
```
JSONProgress:{"inputs":[{"id":0, "stream":0, "type":"video", "codec":"rawvideo", "coder":"rawvideo", "pix_fmt":"rgb24", "frame":188, "fps":24.95, "width":1280, "height":720, "size_kb":507600, "bitrate_kbps":552960.0},{"id":1, "stream":0, "type":"audio", "codec":"pcm_u8", "coder":"pcm_u8", "frame":314, "sampling_hz":44100, "layout":"stereo", "size_kb":628, "bitrate_kbps":705.6}], "outputs":[{"id":0, "stream":0, "type":"video", "codec":"h264", "coder":"libx264", "pix_fmt":"yuv420p", "frame":188, "fps":24.95, "q":-1.0, "width":1280, "height":720, "size_kb":1247, "bitrate_kbps":1365.6},{"id":0, "stream":1, "type":"audio", "codec":"aac", "coder":"aac", "frame":315, "sampling_hz":44100, "layout":"stereo", "size_kb":2, "bitrate_kbps":2.1}], "frame":188, "fps":24.95, "q":-1.0, "size_kb":1249, "bitrate_kbps":1367.7, "time":"0h0m7.48s", "speed":0.993, "dup":0, "drop":0}
```
The same output but nicely formatted:
```json
{
"bitrate_kbps": 1367.7,
"drop": 0,
"dup": 0,
"fps": 24.95,
"frame": 188,
"inputs": [
{
"bitrate_kbps": 552960.0,
"codec": "rawvideo",
"coder": "rawvideo",
"fps": 24.95,
"frame": 188,
"height": 720,
"id": 0,
"pix_fmt": "rgb24",
"size_kb": 507600,
"stream": 0,
"type": "video",
"width": 1280
},
{
"bitrate_kbps": 705.6,
"codec": "pcm_u8",
"coder": "pcm_u8",
"frame": 314,
"id": 1,
"layout": "stereo",
"sampling_hz": 44100,
"size_kb": 628,
"stream": 0,
"type": "audio"
}
],
"outputs": [
{
"bitrate_kbps": 1365.6,
"codec": "h264",
"coder": "libx264",
"fps": 24.95,
"frame": 188,
"height": 720,
"id": 0,
"pix_fmt": "yuv420p",
"q": -1.0,
"size_kb": 1247,
"stream": 0,
"type": "video",
"width": 1280
},
{
"bitrate_kbps": 2.1,
"codec": "aac",
"coder": "aac",
"frame": 315,
"id": 0,
"layout": "stereo",
"sampling_hz": 44100,
"size_kb": 2,
"stream": 1,
"type": "audio"
}
],
"q": -1.0,
"size_kb": 1249,
"speed": 0.993,
"time": "0h0m7.48s"
}
```

View File

@@ -1,17 +1,17 @@
From 85870fdb0530c8d12faa682bd571060b0fa8fb73 Mon Sep 17 00:00:00 2001
From df74cdced975a6f13fdc24e43e75a7f9b571c661 Mon Sep 17 00:00:00 2001
From: Ingo Oppermann <ingo@datarhei.com>
Date: Wed, 13 Jul 2022 14:26:24 +0200
Subject: [PATCH v1] Calculate bandwidth estimate (ffmpeg 5.0)
Date: Tue, 25 Oct 2022 10:43:45 +0200
Subject: [PATCH v2] Calculate bandwidth estimate (ffmpeg 5.1)
---
libavformat/hlsenc.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index ef8973c..8e437de 100644
index 6f49ae1a..da7c3f21 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -125,6 +125,7 @@ typedef struct VariantStream {
@@ -124,6 +124,7 @@ typedef struct VariantStream {
AVIOContext *out;
AVIOContext *out_single_file;
int packets_written;
@@ -19,7 +19,7 @@ index ef8973c..8e437de 100644
int init_range_length;
uint8_t *temp_buffer;
uint8_t *init_buffer;
@@ -139,6 +140,8 @@ typedef struct VariantStream {
@@ -138,6 +139,8 @@ typedef struct VariantStream {
double dpp; // duration per packet
int64_t start_pts;
int64_t end_pts;
@@ -45,7 +45,7 @@ index ef8973c..8e437de 100644
bandwidth += bandwidth / 10;
ccgroup = NULL;
@@ -2439,6 +2452,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
@@ -2443,6 +2456,19 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
return AVERROR(ENOMEM);
}
@@ -65,7 +65,7 @@ index ef8973c..8e437de 100644
end_pts = hls->recording_time * vs->number;
if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
@@ -2656,6 +2682,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
@@ -2663,6 +2689,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
}
vs->packets_written++;
@@ -73,7 +73,7 @@ index ef8973c..8e437de 100644
if (oc->pb) {
ret = ff_write_chained(oc, stream_index, pkt, s, 0);
vs->video_keyframe_size += pkt->size;
@@ -2949,6 +2976,8 @@ static int hls_init(AVFormatContext *s)
@@ -2956,6 +2983,8 @@ static int hls_init(AVFormatContext *s)
vs->sequence = hls->start_sequence;
vs->start_pts = AV_NOPTS_VALUE;
vs->end_pts = AV_NOPTS_VALUE;
@@ -83,7 +83,7 @@ index ef8973c..8e437de 100644
vs->initial_prog_date_time = initial_program_date_time;
base-commit: 82c775a733a6b3a1a951b7cb1d4fd965bfd2b4dc
base-commit: 2bca71f4986725d7cf0d441e2f82a790d0a0c717
--
2.32.1 (Apple Git-133)

View File

@@ -1,19 +1,20 @@
From 815dc4ce1931ab11baf2fd68986974eafcdd76f1 Mon Sep 17 00:00:00 2001
From ae76cd00ce561f8a22179ffa56e8b1a04afdfae8 Mon Sep 17 00:00:00 2001
From: Ingo Oppermann <ingo@datarhei.com>
Date: Wed, 18 May 2022 21:40:50 +0200
Subject: [PATCH v21] JSON progress report (ffmpeg 5.0)
Date: Tue, 25 Oct 2022 10:45:42 +0200
Subject: [PATCH v23] JSON progress report (ffmpeg 5.1)
---
fftools/ffmpeg.c | 262 +++++++++++++++++++++++++++++++++++++++++--
fftools/ffmpeg.c | 205 ++++++++++++++++++++++++++++--
fftools/ffmpeg.h | 1 +
fftools/ffmpeg_opt.c | 69 ++++++++++++
3 files changed, 322 insertions(+), 10 deletions(-)
fftools/ffmpeg_mux.c | 294 +++++++++++++++++++++++++++++++++++++++++++
fftools/ffmpeg_opt.c | 107 ++++++++++++++++
4 files changed, 597 insertions(+), 10 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index bdeff9a..f8821e1 100644
index e7384f05..f52ff4f1 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1673,12 +1673,11 @@ static void print_final_stats(int64_t total_size)
@@ -1504,12 +1504,11 @@ static void print_final_stats(int64_t total_size)
}
}
@@ -26,9 +27,9 @@ index bdeff9a..f8821e1 100644
- int64_t total_size;
+ int64_t total_size = 0;
AVCodecContext *enc;
int frame_number, vid, i;
int vid, i;
double bitrate;
@@ -1707,13 +1706,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
@@ -1538,13 +1537,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
t = (cur_time-timer_start) / 1000000.0;
@@ -42,7 +43,7 @@ index bdeff9a..f8821e1 100644
vid = 0;
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
@@ -1796,6 +1788,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
@@ -1627,6 +1619,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
if (is_last_report)
nb_frames_drop += ost->last_dropped;
@@ -52,17 +53,24 @@ index bdeff9a..f8821e1 100644
}
secs = FFABS(pts) / AV_TIME_BASE;
@@ -1883,6 +1878,251 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
@@ -1714,6 +1709,196 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
print_final_stats(total_size);
}
+/**
+ * Print progress report in JSON format
+ *
+ * @param is_last_report Whether this is the last report
+ * @param timer_start Time when the processing started
+ * @param cur_time Current processing time of the stream
+ */
+static void print_json_report(int is_last_report, int64_t timer_start, int64_t cur_time)
+{
+ AVBPrint buf;
+ InputStream *ist;
+ OutputStream *ost;
+ uint64_t stream_size, total_size = 0;
+ AVCodecContext *enc, *dec;
+ AVCodecContext *enc;
+ int i, j;
+ uint64_t first_vid, first_frame_number = 0, first_packet_number = 0;
+ double speed;
@@ -73,45 +81,47 @@ index bdeff9a..f8821e1 100644
+ float t, q;
+ float first_q = -1;
+
+ if (!print_jsonstats && !is_last_report && !progress_avio) {
+ if(!print_jsonstats && !is_last_report && !progress_avio) {
+ return;
+ }
+
+ if (!is_last_report) {
+ if (last_time == -1) {
+ if(!is_last_report) {
+ if(last_time == -1) {
+ last_time = cur_time;
+ return;
+ }
+ if ((cur_time - last_time) < 500000) {
+ if((cur_time - last_time) < 500000) {
+ return;
+ }
+ last_time = cur_time;
+ }
+
+ t = (cur_time-timer_start) / 1000000.0;
+ t = (cur_time - timer_start) / 1000000.0;
+
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ av_bprintf(&buf, "ffmpeg.progress:{");
+ av_bprintf(&buf, "\"inputs\":[");
+ for (i = 0; i < nb_input_files; i++) {
+ for(i = 0; i < nb_input_files; i++) {
+ InputFile *f = input_files[i];
+
+ for (j = 0; j < f->nb_streams; j++) {
+ for(j = 0; j < f->nb_streams; j++) {
+ ist = input_streams[f->ist_index + j];
+ dec = ist->dec_ctx;
+
+ av_bprintf(&buf, "{");
+ av_bprintf(&buf, "\"index\":%d,\"stream\":%d,", i, j);
+
+ av_bprintf(&buf, "\"frame\":%"PRIu64",\"packet\":%"PRIu64",", ist->frames_decoded == 0 ? ist->nb_packets : ist->frames_decoded, ist->nb_packets);
+ av_bprintf(&buf,
+ "\"frame\":%" PRIu64 ",\"packet\":%" PRIu64 ",",
+ ist->frames_decoded == 0 ? ist->nb_packets
+ : ist->frames_decoded,
+ ist->nb_packets);
+
+ av_bprintf(&buf, "\"size_kb\":%.0f", ist->data_size / 1024.0);
+
+ if(i == (nb_input_files - 1) && j == (f->nb_streams - 1)) {
+ av_bprintf(&buf, "}");
+ }
+ else {
+ } else {
+ av_bprintf(&buf, "},");
+ }
+ }
@@ -119,35 +129,34 @@ index bdeff9a..f8821e1 100644
+
+ av_bprintf(&buf, "],");
+
+ // check libavcodec/utils.c:avcodec_string
+ // check libavformat/dump.c:av_dump_format
+ // check libavcodec/avcodec.h:struct AVCodec and struct AVCodecContext
+ // check libavformat/avformat.h:struct AVStream
+ // check fftools/ffmpeg.h:struct OutputStream
+
+ first_vid = 1;
+
+ av_bprintf(&buf, "\"outputs\":[");
+ for (i = 0; i < nb_output_streams; i++) {
+ OutputFile *f;
+ for(i = 0; i < nb_output_streams; i++) {
+ q = -1;
+ ost = output_streams[i];
+ f = output_files[ost->file_index];
+ enc = ost->enc_ctx;
+ if (!ost->stream_copy) {
+ q = ost->quality / (float) FF_QP2LAMBDA;
+ if(!ost->stream_copy) {
+ q = ost->quality / (float)FF_QP2LAMBDA;
+ }
+
+ av_bprintf(&buf, "{");
+ av_bprintf(&buf, "\"index\":%d,\"stream\":%d,", ost->file_index, ost->index);
+ av_bprintf(
+ &buf, "\"index\":%d,\"stream\":%d,", ost->file_index, ost->index);
+
+ av_bprintf(&buf, "\"frame\":%"PRIu64",\"packet\":%"PRIu64",", ost->frames_encoded == 0 ? ost->packets_written : ost->frames_encoded, ost->packets_written);
+ av_bprintf(&buf,
+ "\"frame\":%" PRIu64 ",\"packet\":%" PRIu64 ",",
+ ost->frames_encoded == 0 ? ost->packets_written
+ : ost->frames_encoded,
+ ost->packets_written);
+
+ if(enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ av_bprintf(&buf, "\"q\":%.1f,", q);
+
+ if(first_vid == 1) {
+ first_frame_number = ost->frames_encoded == 0 ? ost->packets_written : ost->frames_encoded;
+ first_frame_number = ost->frames_encoded == 0
+ ? ost->packets_written
+ : ost->frames_encoded;
+ first_packet_number = ost->packets_written;
+ first_q = q;
+
@@ -157,12 +166,18 @@ index bdeff9a..f8821e1 100644
+
+ /* compute min output value */
+ pts = INT64_MIN + 1;
+ if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) {
+ pts = FFMAX(pts, av_rescale_q(av_stream_get_end_pts(ost->st), ost->st->time_base, AV_TIME_BASE_Q));
+ min_pts = FFMAX(min_pts, av_rescale_q(av_stream_get_end_pts(ost->st), ost->st->time_base, AV_TIME_BASE_Q));
+ if(av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) {
+ pts = FFMAX(pts,
+ av_rescale_q(av_stream_get_end_pts(ost->st),
+ ost->st->time_base,
+ AV_TIME_BASE_Q));
+ min_pts = FFMAX(min_pts,
+ av_rescale_q(av_stream_get_end_pts(ost->st),
+ ost->st->time_base,
+ AV_TIME_BASE_Q));
+ }
+
+ if (is_last_report) {
+ if(is_last_report) {
+ nb_frames_drop += ost->last_dropped;
+ }
+
@@ -173,15 +188,18 @@ index bdeff9a..f8821e1 100644
+
+ if(i == (nb_output_streams - 1)) {
+ av_bprintf(&buf, "}");
+ }
+ else {
+ } else {
+ av_bprintf(&buf, "},");
+ }
+ }
+
+ av_bprintf(&buf, "],");
+
+ av_bprintf(&buf, "\"frame\":%"PRIu64",\"packet\":%"PRIu64",\"q\":%.1f,", first_frame_number, first_packet_number, first_q);
+ av_bprintf(&buf,
+ "\"frame\":%" PRIu64 ",\"packet\":%" PRIu64 ",\"q\":%.1f,",
+ first_frame_number,
+ first_packet_number,
+ first_q);
+
+ av_bprintf(&buf, "\"size_kb\":%.0f,", total_size / 1024.0);
+
@@ -194,16 +212,22 @@ index bdeff9a..f8821e1 100644
+ hours_sign = (min_pts < 0) ? "-" : "";
+
+ if(min_pts != AV_NOPTS_VALUE) {
+ av_bprintf(&buf, "\"time\":\"%s%dh%dm%d.%ds\",", hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE);
+ av_bprintf(&buf,
+ "\"time\":\"%s%dh%dm%d.%ds\",",
+ hours_sign,
+ hours,
+ mins,
+ secs,
+ (100 * us) / AV_TIME_BASE);
+ }
+
+ speed = t != 0.0 ? (double)min_pts / AV_TIME_BASE / t : -1;
+ av_bprintf(&buf, "\"speed\":%.3g,", speed);
+
+ av_bprintf(&buf, "\"dup\":%d,\"drop\":%d", nb_frames_dup, nb_frames_drop);
+ av_bprintf(&buf, "\"dup\":%"PRId64",\"drop\":%"PRId64, nb_frames_dup, nb_frames_drop);
+ av_bprintf(&buf, "}");
+
+ if (print_jsonstats || is_last_report) {
+ if(print_jsonstats || is_last_report) {
+ fprintf(stderr, "%s\n", buf.str);
+ fflush(stderr);
+ }
@@ -211,113 +235,26 @@ index bdeff9a..f8821e1 100644
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void print_json_outputs() {
+ static int ost_all_initialized = 0;
+ int i;
+ int nb_initialized = 0;
+
+ if(print_jsonstats != 1 && print_stats != -1) {
+ return;
+ }
+
+ if(ost_all_initialized == 1) {
+ return;
+ }
+
+ // check if all outputs are initialized
+ for (i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ if (ost->initialized) {
+ nb_initialized++;
+ }
+ }
+
+ // only if all outputs are initialized, dump the outputs
+ if (nb_initialized == nb_output_streams) {
+ ost_all_initialized = 1;
+
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ av_bprintf(&buf, "ffmpeg.outputs:[");
+ for (i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ OutputFile *f = output_files[ost->file_index];
+ AVFormatContext *ctx = f->ctx;
+ AVStream *st = ost->st;
+ AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
+ AVCodecContext *enc = ost->enc_ctx;
+
+ av_bprintf(&buf, "{");
+ av_bprintf(&buf, "\"url\":\"%s\",\"format\":\"%s\",\"index\":%d,\"stream\":%d,", ctx->url, ctx->oformat->name, ost->file_index, ost->index);
+ av_bprintf(&buf, "\"type\":\"%s\",\"codec\":\"%s\",\"coder\":\"%s\",\"bitrate_kbps\":%"PRId64",", media_type_string(enc->codec_type), avcodec_get_name(enc->codec_id), ost->stream_copy ? "copy" : (enc->codec ? enc->codec->name : "unknown"), enc->bit_rate / 1000);
+ av_bprintf(&buf, "\"duration_sec\":%f,\"language\":\"%s\"", 0.0, lang != NULL ? lang->value : "und");
+
+ if(enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ float fps = 0;
+ if(st->avg_frame_rate.den && st->avg_frame_rate.num) {
+ fps = av_q2d(st->avg_frame_rate);
+ }
+
+ av_bprintf(&buf, ",\"fps\":%f,\"pix_fmt\":\"%s\",\"width\":%d,\"height\":%d", fps, st->codecpar->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(st->codecpar->format), st->codecpar->width, st->codecpar->height);
+ }
+ else if(enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+ char layout[128];
+
+ av_get_channel_layout_string(layout, sizeof(layout), enc->channels, enc->channel_layout);
+
+ av_bprintf(&buf, ",\"sampling_hz\":%d,\"layout\":\"%s\",\"channels\":%d", enc->sample_rate, layout, enc->channels);
+ }
+
+ if(i == (nb_output_streams - 1)) {
+ av_bprintf(&buf, "}");
+ }
+ else {
+ av_bprintf(&buf, "},");
+ }
+ }
+
+ av_bprintf(&buf, "]");
+
+ fprintf(stderr, "%s\n", buf.str);
+
+ av_bprint_clear(&buf);
+ }
+
+ return;
+}
+
+static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
+{
+ if (!print_stats && !print_jsonstats && !is_last_report && !progress_avio)
+ if(!print_stats && !print_jsonstats && !is_last_report && !progress_avio)
+ return;
+
+ if (print_stats == 1) {
+ print_default_report(is_last_report, timer_start, cur_time);
+ }
+ else {
+ if(print_jsonstats == 1) {
+ print_json_report(is_last_report, timer_start, cur_time);
+ } else {
+ print_default_report(is_last_report, timer_start, cur_time);
+ }
+}
+
static void ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par)
static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par)
{
// We never got any input. Set a fake format, which will
@@ -2967,6 +3207,8 @@ static int check_init_output_file(OutputFile *of, int file_index)
av_dump_format(of->ctx, file_index, of->ctx->url, 1);
nb_output_dumped++;
+ print_json_outputs();
+
if (sdp_filename || want_sdp) {
ret = print_sdp();
if (ret < 0) {
int ret;
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 9b200b8..bd053f4 100644
index 391a35cf..179f2d22 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -622,6 +622,7 @@ extern int debug_ts;
@@ -636,6 +636,7 @@ extern int debug_ts;
extern int exit_on_error;
extern int abort_on_flags;
extern int print_stats;
@@ -325,11 +262,330 @@ index 9b200b8..bd053f4 100644
extern int64_t stats_period;
extern int qp_hist;
extern int stdin_interaction;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index a55fd18f..3a09ba08 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -26,6 +26,8 @@
#include "libavutil/log.h"
#include "libavutil/mem.h"
#include "libavutil/timestamp.h"
+#include "libavutil/bprint.h"
+#include "libavutil/pixdesc.h"
#include "libavcodec/packet.h"
@@ -226,6 +228,296 @@ fail:
return ret;
}
+/**
+ * Write a graph as JSON to an initialized buffer
+ *
+ * @param buf Pointer to an initialized AVBPrint buffer
+ * @param graph Pointer to a AVFilterGraph
+ */
+static void print_json_graph(AVBPrint *buf, AVFilterGraph *graph)
+{
+ int i, j;
+
+ if(graph == NULL) {
+ av_bprintf(buf, "null\n");
+ return;
+ }
+
+ av_bprintf(buf, "[");
+
+ for(i = 0; i < graph->nb_filters; i++) {
+ const AVFilterContext *filter_ctx = graph->filters[i];
+
+ for(j = 0; j < filter_ctx->nb_outputs; j++) {
+ AVFilterLink *link = filter_ctx->outputs[j];
+ if(link) {
+ const AVFilterContext *dst_filter_ctx = link->dst;
+
+ av_bprintf(buf,
+ "{\"src_name\":\"%s\",\"src_filter\":\"%s\",\"dst_name\":\"%s\",\"dst_filter\":\"%s\",",
+ filter_ctx->name,
+ filter_ctx->filter->name,
+ dst_filter_ctx->name,
+ dst_filter_ctx->filter->name);
+ av_bprintf(buf,
+ "\"inpad\":\"%s\",\"outpad\":\"%s\",",
+ avfilter_pad_get_name(link->srcpad, 0),
+ avfilter_pad_get_name(link->dstpad, 0));
+ av_bprintf(buf,
+ "\"timebase\": \"%d/%d\",",
+ link->time_base.num,
+ link->time_base.den);
+
+ if(link->type == AVMEDIA_TYPE_VIDEO) {
+ const AVPixFmtDescriptor *desc =
+ av_pix_fmt_desc_get(link->format);
+ av_bprintf(buf,
+ "\"type\":\"video\",\"format\":\"%s\",\"width\":%d,\"height\":%d",
+ desc->name,
+ link->w,
+ link->h);
+ } else if(link->type == AVMEDIA_TYPE_AUDIO) {
+ char layout[255];
+ av_channel_layout_describe(&link->ch_layout, layout, sizeof(layout));
+ av_bprintf(buf,
+ "\"type\":\"audio\",\"format\":\"%s\",\"sampling_hz\":%d,\"layout\":\"%s\"",
+ av_get_sample_fmt_name(link->format),
+ link->sample_rate,
+ layout);
+ }
+
+ if(i == (graph->nb_filters - 1)) {
+ av_bprintf(buf, "}");
+ } else {
+ av_bprintf(buf, "},");
+ }
+ }
+ }
+ }
+
+ av_bprintf(buf, "]");
+}
+
+/**
+ * Print all outputs in JSON format
+ */
+static void print_json_outputs()
+{
+ static int ost_all_initialized = 0;
+ int i, j, k;
+ int nb_initialized = 0;
+ AVBPrint buf;
+
+ if(print_jsonstats != 1) {
+ return;
+ }
+
+ if(ost_all_initialized == 1) {
+ return;
+ }
+
+ // count how many outputs are initialized
+ for(i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ if(ost->initialized) {
+ nb_initialized++;
+ }
+ }
+
+ // only when all outputs are initialized, dump the outputs
+ if(nb_initialized == nb_output_streams) {
+ ost_all_initialized = 1;
+ }
+
+ if(ost_all_initialized != 1) {
+ return;
+ }
+
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ av_bprintf(&buf, "ffmpeg.outputs:[");
+ for(i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ OutputFile *f = output_files[ost->file_index];
+ AVFormatContext *ctx = f->ctx;
+ AVStream *st = ost->st;
+ AVDictionaryEntry *lang =
+ av_dict_get(st->metadata, "language", NULL, 0);
+ AVCodecContext *enc = ost->enc_ctx;
+ char *url = NULL;
+
+ if(av_escape(&url,
+ ctx->url,
+ "\\\"",
+ AV_ESCAPE_MODE_BACKSLASH,
+ AV_UTF8_FLAG_ACCEPT_ALL) < 0) {
+ url = av_strdup("-");
+ }
+
+ av_bprintf(&buf, "{");
+ av_bprintf(&buf,
+ "\"url\":\"%s\",\"format\":\"%s\",\"index\":%d,\"stream\":%d,",
+ url,
+ ctx->oformat->name,
+ ost->file_index,
+ ost->index);
+ av_bprintf(&buf,
+ "\"type\":\"%s\",\"codec\":\"%s\",\"coder\":\"%s\",\"bitrate_kbps\":%" PRId64
+ ",",
+ av_get_media_type_string(enc->codec_type),
+ avcodec_get_name(enc->codec_id),
+ ost->stream_copy ? "copy"
+ : (enc->codec ? enc->codec->name : "unknown"),
+ enc->bit_rate / 1000);
+ av_bprintf(&buf,
+ "\"duration_sec\":%f,\"language\":\"%s\"",
+ 0.0,
+ lang != NULL ? lang->value : "und");
+
+ av_free(url);
+
+ if(enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ float fps = 0;
+ if(st->avg_frame_rate.den && st->avg_frame_rate.num) {
+ fps = av_q2d(st->avg_frame_rate);
+ }
+
+ av_bprintf(&buf,
+ ",\"fps\":%f,\"pix_fmt\":\"%s\",\"width\":%d,\"height\":%d",
+ fps,
+ st->codecpar->format == AV_PIX_FMT_NONE
+ ? "none"
+ : av_get_pix_fmt_name(st->codecpar->format),
+ st->codecpar->width,
+ st->codecpar->height);
+ } else if(enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+ char layout[128];
+ av_channel_layout_describe(&enc->ch_layout, layout, sizeof(layout));
+
+ av_bprintf(&buf,
+ ",\"sampling_hz\":%d,\"layout\":\"%s\",\"channels\":%d",
+ enc->sample_rate,
+ layout,
+ enc->ch_layout.nb_channels);
+ }
+
+ if(i == (nb_output_streams - 1)) {
+ av_bprintf(&buf, "}");
+ } else {
+ av_bprintf(&buf, "},");
+ }
+ }
+
+ av_bprintf(&buf, "]");
+
+ av_log(NULL, AV_LOG_INFO, "%s\n", buf.str);
+
+ av_bprint_clear(&buf);
+
+ av_bprintf(&buf, "ffmpeg.mapping:{");
+ av_bprintf(&buf, "\"graphs\":[");
+
+ for(i = 0; i < nb_filtergraphs; i++) {
+ av_bprintf(&buf, "{\"index\":%d,\"graph\":", i);
+ print_json_graph(&buf, filtergraphs[i]->graph);
+
+ if(i == (nb_filtergraphs - 1)) {
+ av_bprintf(&buf, "}");
+ } else {
+ av_bprintf(&buf, "},");
+ }
+ }
+
+ av_bprintf(&buf, "],");
+
+ // The following is inspired by tools/graph2dot.c
+
+ av_bprintf(&buf, "\"mapping\":[");
+
+ for(i = 0; i < nb_input_streams; i++) {
+ InputStream *ist = input_streams[i];
+
+ for(j = 0; j < ist->nb_filters; j++) {
+ if(ist->filters[j]->graph) {
+ char *name = NULL;
+ for(k = 0; k < ist->filters[j]->graph->nb_inputs; k++) {
+ if(ist->filters[j]->graph->inputs[k]->ist == ist) {
+ name = ist->filters[j]->graph->inputs[k]->filter->name;
+ break;
+ }
+ }
+
+ av_bprintf(&buf,
+ "{\"input\":{\"index\":%d,\"stream\":%d},\"graph\":{\"index\":%d,\"name\":\"%s\"},\"output\":null},",
+ ist->file_index,
+ ist->st->index,
+ ist->filters[j]->graph->index,
+ name);
+ }
+ }
+ }
+
+ for(i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+
+ if(ost->attachment_filename) {
+ av_bprintf(&buf,
+ "{\"input\":null,\"file\":\"%s\",\"output\":{\"index\":%d,\"stream\":%d}},",
+ ost->attachment_filename,
+ ost->file_index,
+ ost->index);
+ goto next_output;
+ }
+
+ if(ost->filter && ost->filter->graph) {
+ char *name = NULL;
+ for(j = 0; j < ost->filter->graph->nb_outputs; j++) {
+ if(ost->filter->graph->outputs[j]->ost == ost) {
+ name = ost->filter->graph->outputs[j]->filter->name;
+ break;
+ }
+ }
+ av_bprintf(&buf,
+ "{\"input\":null,\"graph\":{\"index\":%d,\"name\":\"%s\"},\"output\":{\"index\":%d,\"stream\":%d}}",
+ ost->filter->graph->index,
+ name,
+ ost->file_index,
+ ost->index);
+ goto next_output;
+ }
+
+ av_bprintf(&buf,
+ "{\"input\":{\"index\":%d,\"stream\":%d},\"output\":{\"index\":%d,\"stream\":%d}",
+ input_streams[ost->source_index]->file_index,
+ input_streams[ost->source_index]->st->index,
+ ost->file_index,
+ ost->index);
+ av_bprintf(&buf, ",\"copy\":%s", ost->stream_copy ? "true" : "false");
+
+ if(ost->sync_ist != input_streams[ost->source_index]) {
+ av_bprintf(&buf,
+ ",\"sync\":{\"index\":%d,\"stream\":%d}",
+ ost->sync_ist->file_index,
+ ost->sync_ist->st->index);
+ }
+
+ av_bprintf(&buf, "}");
+
+ next_output:
+ if(i != (nb_output_streams - 1)) {
+ av_bprintf(&buf, ",");
+ }
+ }
+
+ av_bprintf(&buf, "]}");
+
+ av_log(NULL, AV_LOG_INFO, "%s\n", buf.str);
+
+ av_bprint_finalize(&buf, NULL);
+
+ return;
+}
+
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of)
{
@@ -251,6 +543,8 @@ int of_check_init(OutputFile *of)
av_dump_format(of->ctx, of->index, of->ctx->url, 1);
nb_output_dumped++;
+ print_json_outputs();
+
if (sdp_filename || want_sdp) {
ret = print_sdp();
if (ret < 0) {
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 9c820ab..8471dc9 100644
index 6e18a4a2..94064947 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -43,6 +43,7 @@
@@ -52,6 +52,7 @@
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
@@ -337,20 +593,24 @@ index 9c820ab..8471dc9 100644
#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
@@ -160,6 +161,7 @@ int debug_ts = 0;
@@ -171,6 +172,7 @@ int debug_ts = 0;
int exit_on_error = 0;
int abort_on_flags = 0;
int print_stats = -1;
+int print_jsonstats = -1;
+int print_jsonstats = 1;
int qp_hist = 0;
int stdin_interaction = 1;
float max_error_rate = 2.0/3;
@@ -3433,6 +3435,69 @@ static int open_files(OptionGroupList *l, const char *inout,
@@ -3547,6 +3549,108 @@ static int open_files(OptionGroupList *l, const char *inout,
return 0;
}
+static void print_json_inputs() {
+ if(print_jsonstats != 1 && print_stats != -1) {
+/**
+ * Print all inputs in JSON format
+ */
+static void print_json_inputs()
+{
+ if(print_jsonstats != 1) {
+ return;
+ }
+
@@ -360,25 +620,53 @@ index 9c820ab..8471dc9 100644
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ av_bprintf(&buf, "ffmpeg.inputs:[");
+ for (i = 0; i < nb_input_files; i++) {
+ for(i = 0; i < nb_input_files; i++) {
+ InputFile *f = input_files[i];
+ AVFormatContext *ctx = f->ctx;
+
+ float duration = 0;
+ if (ctx->duration != AV_NOPTS_VALUE) {
+ duration = (float)(ctx->duration + (ctx->duration <= INT64_MAX - 5000 ? 5000 : 0)) / (float)AV_TIME_BASE;
+ if(ctx->duration != AV_NOPTS_VALUE) {
+ duration = (float)(ctx->duration +
+ (ctx->duration <= INT64_MAX - 5000 ? 5000 : 0)) /
+ (float)AV_TIME_BASE;
+ }
+
+ for (j = 0; j < f->nb_streams; j++) {
+ for(j = 0; j < f->nb_streams; j++) {
+ InputStream *ist = input_streams[f->ist_index + j];
+ AVCodecContext *dec = ist->dec_ctx;
+ AVStream *st = ist->st;
+ AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
+ AVDictionaryEntry *lang =
+ av_dict_get(st->metadata, "language", NULL, 0);
+ char *url = NULL;
+
+ if(av_escape(&url,
+ ctx->url,
+ "\\\"",
+ AV_ESCAPE_MODE_BACKSLASH,
+ AV_UTF8_FLAG_ACCEPT_ALL) < 0) {
+ url = av_strdup("-");
+ }
+
+ av_bprintf(&buf, "{");
+ av_bprintf(&buf, "\"url\":\"%s\",\"format\":\"%s\",\"index\":%d,\"stream\":%d,", ctx->url, ctx->iformat->name, i, j);
+ av_bprintf(&buf, "\"type\":\"%s\",\"codec\":\"%s\",\"coder\":\"%s\",\"bitrate_kbps\":%"PRId64",", media_type_string(dec->codec_type), avcodec_get_name(dec->codec_id), dec->codec ? dec->codec->name : "unknown", dec->bit_rate / 1000);
+ av_bprintf(&buf, "\"duration_sec\":%f,\"language\":\"%s\"", duration, lang != NULL ? lang->value : "und");
+ av_bprintf(&buf,
+ "\"url\":\"%s\",\"format\":\"%s\",\"index\":%d,\"stream\":%d,",
+ url,
+ ctx->iformat->name,
+ i,
+ j);
+ av_bprintf(&buf,
+ "\"type\":\"%s\",\"codec\":\"%s\",\"coder\":\"%s\",\"bitrate_kbps\":%" PRId64
+ ",",
+ av_get_media_type_string(dec->codec_type),
+ avcodec_get_name(dec->codec_id),
+ dec->codec ? dec->codec->name : "unknown",
+ dec->bit_rate / 1000);
+ av_bprintf(&buf,
+ "\"duration_sec\":%f,\"language\":\"%s\"",
+ duration,
+ lang != NULL ? lang->value : "und");
+
+ av_free(url);
+
+ if(dec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ float fps = 0;
@@ -386,45 +674,51 @@ index 9c820ab..8471dc9 100644
+ fps = av_q2d(st->avg_frame_rate);
+ }
+
+ av_bprintf(&buf, ",\"fps\":%f,\"pix_fmt\":\"%s\",\"width\":%d,\"height\":%d", fps, st->codecpar->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(st->codecpar->format), st->codecpar->width, st->codecpar->height);
+ }
+ else if(dec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ av_bprintf(&buf,
+ ",\"fps\":%f,\"pix_fmt\":\"%s\",\"width\":%d,\"height\":%d",
+ fps,
+ st->codecpar->format == AV_PIX_FMT_NONE
+ ? "none"
+ : av_get_pix_fmt_name(st->codecpar->format),
+ st->codecpar->width,
+ st->codecpar->height);
+ } else if(dec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ char layout[128];
+
+ av_get_channel_layout_string(layout, sizeof(layout), dec->channels, dec->channel_layout);
+ av_channel_layout_describe(&dec->ch_layout, layout, sizeof(layout));
+
+ av_bprintf(&buf, ",\"sampling_hz\":%d,\"layout\":\"%s\",\"channels\":%d", dec->sample_rate, layout, dec->channels);
+ av_bprintf(&buf,
+ ",\"sampling_hz\":%d,\"layout\":\"%s\",\"channels\":%d",
+ dec->sample_rate,
+ layout,
+ dec->ch_layout.nb_channels);
+ }
+
+ if(i == (nb_input_files - 1) && j == (f->nb_streams - 1)) {
+ av_bprintf(&buf, "}");
+ }
+ else {
+ } else {
+ av_bprintf(&buf, "},");
+ }
+ }
+ }
+ }
+
+ av_bprintf(&buf, "]");
+
+ fprintf(stderr, "%s\n", buf.str);
+
+ return;
+ av_log(NULL, AV_LOG_INFO, "%s\n", buf.str);
+}
+
int ffmpeg_parse_options(int argc, char **argv)
{
OptionParseContext octx;
@@ -3466,6 +3531,8 @@ int ffmpeg_parse_options(int argc, char **argv)
@@ -3580,6 +3684,7 @@ int ffmpeg_parse_options(int argc, char **argv)
goto fail;
}
+ print_json_inputs();
+
apply_sync_offsets();
/* create the complex filtergraphs */
ret = init_complex_filters();
if (ret < 0) {
@@ -3674,6 +3741,8 @@ const OptionDef options[] = {
@@ -3806,6 +3911,8 @@ const OptionDef options[] = {
"enable automatic conversion filters globally" },
{ "stats", OPT_BOOL, { &print_stats },
"print progress report during encoding", },
@@ -434,7 +728,7 @@ index 9c820ab..8471dc9 100644
"set the period at which ffmpeg updates stats and -progress output", "time" },
{ "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
base-commit: 71650a0ab9193298b29c86db433f43b2feb62b93
base-commit: 2bca71f4986725d7cf0d441e2f82a790d0a0c717
--
2.32.0 (Apple Git-132)
2.32.1 (Apple Git-133)