
Recherche avancée
Autres articles (98)
-
MediaSPIP 0.1 Beta version
25 avril 2011, parMediaSPIP 0.1 beta is the first version of MediaSPIP proclaimed as "usable".
The zip file provided here only contains the sources of MediaSPIP in its standalone version.
To get a working installation, you must manually install all-software dependencies on the server.
If you want to use this archive for an installation in "farm mode", you will also need to proceed to other manual (...) -
Multilang : améliorer l’interface pour les blocs multilingues
18 février 2011, parMultilang est un plugin supplémentaire qui n’est pas activé par défaut lors de l’initialisation de MediaSPIP.
Après son activation, une préconfiguration est mise en place automatiquement par MediaSPIP init permettant à la nouvelle fonctionnalité d’être automatiquement opérationnelle. Il n’est donc pas obligatoire de passer par une étape de configuration pour cela. -
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;
Sur d’autres sites (9794)
-
Open VideoStream using OpenCV 4.5.1 works on Windows but fails on Docker python:3.9.2-slim-buster for specific IP cam
18 mai 2021, par Qua285I have 2 ip cameras - one of Hikvision and another of Provision ISR. Both use Onvif and work on VLC.
I've written a simple python script to record images every 5 sec from their video stream.
On Windows 10, using VSCode they both work as expected. Once deployed to a Docker container, my script works as expected with the Hikvision but fails with the Provision ISR - it doesn't open the stream.


Running
python -c "import cv2; print(cv2.getBuildInformation())"
on windows (venv 3.9.2) and on docker machine bring slightly different results but it's beyond my understanding to take something out of it...
Here is the Windows one :

General configuration for OpenCV 4.5.1 =====================================
 Version control: 4.5.1

 Platform:
 Timestamp: 2021-01-02T14:30:58Z
 Host: Windows 6.3.9600 AMD64
 CMake: 3.18.4
 CMake generator: Visual Studio 14 2015 Win64
 CMake build tool: C:/Program Files (x86)/MSBuild/14.0/bin/MSBuild.exe
 MSVC: 1900

 CPU/HW features:
 Baseline: SSE SSE2 SSE3
 requested: SSE3
 Dispatched code generation: SSE4_1 SSE4_2 FP16 AVX AVX2
 requested: SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
 SSE4_1 (15 files): + SSSE3 SSE4_1
 SSE4_2 (1 files): + SSSE3 SSE4_1 POPCNT SSE4_2
 FP16 (0 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
 AVX (4 files): + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
 AVX2 (29 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2

 C/C++:
 Built as dynamic libs?: NO
 C++ standard: 11
 C++ Compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe (ver 19.0.24241.7)
 C++ flags (Release): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 
/MP /MT /O2 /Ob2 /DNDEBUG
 C++ flags (Debug): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 
/MP /MTd /Zi /Ob0 /Od /RTC1
 C Compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe
 C flags (Release): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /MP /MT /O2 /Ob2 /DNDEBUG
 C flags (Debug): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /MP /MTd /Zi /Ob0 /Od /RTC1
 Linker flags (Release): /machine:x64 /NODEFAULTLIB:atlthunk.lib /INCREMENTAL:NO /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:libcpmtd.lib /NODEFAULTLIB:msvcrtd.lib
 Linker flags (Debug): /machine:x64 /NODEFAULTLIB:atlthunk.lib /debug /INCREMENTAL /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:msvcrt.lib
 ccache: NO
 Precompiled headers: YES
 Extra dependencies: ade wsock32 comctl32 gdi32 ole32 setupapi ws2_32
 3rdparty dependencies: ittnotify libprotobuf zlib libjpeg-turbo libwebp libpng libtiff libopenjp2 IlmImf quirc ippiw ippicv

 OpenCV modules:
 To be built: calib3d core dnn features2d flann gapi highgui imgcodecs imgproc ml objdetect photo python3 stitching video videoio
 Disabled: world
 Disabled by dependency: -
 Unavailable: java python2 ts
 Applications: -
 Documentation: NO
 Non-free algorithms: NO

 Windows RT support: NO

 GUI:
 Win32 UI: YES
 VTK support: NO

 Media I/O:
 ZLib: build (ver 1.2.11)
 JPEG: build-libjpeg-turbo (ver 2.0.6-62)
 WEBP: build (ver encoder: 0x020f)
 PNG: build (ver 1.6.37)
 TIFF: build (ver 42 - 4.0.10)
 JPEG 2000: build (ver 2.3.1)
 OpenEXR: build (ver 2.3.0)
 HDR: YES
 SUNRASTER: YES
 PXM: YES
 PFM: YES

 Video I/O:
 DC1394: NO
 FFMPEG: YES (prebuilt binaries)
 avcodec: YES (58.91.100)
 avformat: YES (58.45.100)
 avutil: YES (56.51.100)
 swscale: YES (5.7.100)
 avresample: YES (4.0.0)
 GStreamer: NO
 DirectShow: YES
 Media Foundation: YES
 DXVA: NO

 Parallel framework: Concurrency

 Trace: YES (with Intel ITT)

 Other third-party libraries:
 Intel IPP: 2020.0.0 Gold [2020.0.0]
 at: C:/Users/appveyor/AppData/Local/Temp/1/pip-req-build-wvn_it83/_skbuild/win-amd64-3.9/cmake-build/3rdparty/ippicv/ippicv_win/icv
 Intel IPP IW: sources (2020.0.0)
 at: C:/Users/appveyor/AppData/Local/Temp/1/pip-req-build-wvn_it83/_skbuild/win-amd64-3.9/cmake-build/3rdparty/ippicv/ippicv_win/iw
 Lapack: NO
 Eigen: NO
 Custom HAL: NO
 Protobuf: build (3.5.1)

 OpenCL: YES (NVD3D11)
 Include path: C:/Users/appveyor/AppData/Local/Temp/1/pip-req-build-wvn_it83/opencv/3rdparty/include/opencl/1.2
 Link libraries: Dynamic load

 Python 3:
 Interpreter: C:/Python39-x64/python.exe (ver 3.9)
 Libraries: C:/Python39-x64/libs/python39.lib (ver 3.9.0)
 numpy: C:/Users/appveyor/AppData/Local/Temp/1/pip-build-env-sk7r7w_5/overlay/Lib/site-packages/numpy/core/include (ver 1.19.3)
 install path: python

 Python (for build): C:/Python27-x64/python.exe

 Java:
 ant: NO
 JNI: C:/Program Files/Java/jdk1.8.0/include C:/Program Files/Java/jdk1.8.0/include/win32 C:/Program Files/Java/jdk1.8.0/include
 Java wrappers: NO
 Java tests: NO

 Install to: C:/Users/appveyor/AppData/Local/Temp/1/pip-req-build-wvn_it83/_skbuild/win-amd64-3.9/cmake-install
-----------------------------------------------------------------



this is the Docker one (python:3.9.2-slim-buster) :


General configuration for OpenCV 4.5.1 =====================================
 Version control: 4.5.1-dirty

 Platform:
 Timestamp: 2021-01-02T13:04:10Z
 Host: Linux 4.15.0-1077-gcp x86_64
 CMake: 3.18.4
 CMake generator: Unix Makefiles
 CMake build tool: /bin/gmake
 Configuration: Release

 CPU/HW features:
 Baseline: SSE SSE2 SSE3
 requested: SSE3
 Dispatched code generation: SSE4_1 SSE4_2 FP16 AVX AVX2 AVX512_SKX
 requested: SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
 SSE4_1 (15 files): + SSSE3 SSE4_1
 SSE4_2 (1 files): + SSSE3 SSE4_1 POPCNT SSE4_2
 FP16 (0 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
 AVX (4 files): + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
 AVX2 (29 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
 AVX512_SKX (4 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2 AVX_512F AVX512_COMMON AVX512_SKX

 C/C++:
 Built as dynamic libs?: NO
 C++ standard: 11
 C++ Compiler: /usr/lib/ccache/compilers/c++ (ver 9.3.1)
 C++ flags (Release): -Wl,-strip-all -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -DNDEBUG
 C++ flags (Debug): -Wl,-strip-all -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -g -O0 -DDEBUG -D_DEBUG
 C Compiler: /usr/lib/ccache/compilers/cc
 C flags (Release): -Wl,-strip-all -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Wno-comment -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -O3 -DNDEBUG -DNDEBUG
 C flags (Debug): -Wl,-strip-all -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Wno-comment -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -g -O0 -DDEBUG -D_DEBUG
 Linker flags (Release): -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a -L/root/ffmpeg_build/lib -Wl,--gc-sections -Wl,--as-needed
 Linker flags (Debug): -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a -L/root/ffmpeg_build/lib -Wl,--gc-sections -Wl,--as-needed
 ccache: YES
 Precompiled headers: NO
 Extra dependencies: ade Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Test Qt5::Concurrent /lib64/libpng.so /lib64/libz.so dl m pthread rt
 3rdparty dependencies: ittnotify libprotobuf libjpeg-turbo libwebp libtiff libopenjp2 IlmImf quirc ippiw ippicv

 OpenCV modules:
 To be built: calib3d core dnn features2d flann gapi highgui imgcodecs imgproc ml objdetect photo python3 stitching video videoio
 Disabled: world
 Disabled by dependency: -
 Unavailable: java python2 ts
 Applications: -
 Documentation: NO
 Non-free algorithms: NO

 GUI:
 QT: YES (ver 5.15.0)
 QT OpenGL support: NO
 GTK+: NO
 VTK support: NO

 Media I/O:
 ZLib: /lib64/libz.so (ver 1.2.7)
 JPEG: libjpeg-turbo (ver 2.0.6-62)
 WEBP: build (ver encoder: 0x020f)
 PNG: /lib64/libpng.so (ver 1.5.13)
 TIFF: build (ver 42 - 4.0.10)
 JPEG 2000: build (ver 2.3.1)
 OpenEXR: build (ver 2.3.0)
 HDR: YES
 SUNRASTER: YES
 PXM: YES
 PFM: YES

 Video I/O:
 DC1394: NO
 FFMPEG: YES
 avcodec: YES (58.109.100)
 avformat: YES (58.61.100)
 avutil: YES (56.60.100)
 swscale: YES (5.8.100)
 avresample: NO
 GStreamer: NO
 v4l/v4l2: YES (linux/videodev2.h)

 Parallel framework: pthreads

 Trace: YES (with Intel ITT)

 Other third-party libraries:
 Intel IPP: 2020.0.0 Gold [2020.0.0]
 at: /tmp/pip-req-build-ddpkm6fn/_skbuild/linux-x86_64-3.9/cmake-build/3rdparty/ippicv/ippicv_lnx/icv
 Intel IPP IW: sources (2020.0.0)
 at: /tmp/pip-req-build-ddpkm6fn/_skbuild/linux-x86_64-3.9/cmake-build/3rdparty/ippicv/ippicv_lnx/iw
 Lapack: NO
 Eigen: NO
 Custom HAL: NO
 Protobuf: build (3.5.1)

 OpenCL: YES (no extra features)
 Include path: /tmp/pip-req-build-ddpkm6fn/opencv/3rdparty/include/opencl/1.2
 Link libraries: Dynamic load

 Python 3:
 Interpreter: /opt/python/cp39-cp39/bin/python (ver 3.9)
 Libraries: libpython3.9.a (ver 3.9.0)
 numpy: /tmp/pip-build-env-jqrfyj0w/overlay/lib/python3.9/site-packages/numpy/core/include (ver 1.19.3)
 install path: python

 Python (for build): /bin/python2.7

 Java:
 ant: NO
 JNI: NO
 Java wrappers: NO
 Java tests: NO

 Install to: /tmp/pip-req-build-ddpkm6fn/_skbuild/linux-x86_64-3.9/cmake-install
-----------------------------------------------------------------



If relevant, the docker is installed on an Intel NUC with Ubuntu Desktop 20.04


If relevant, this is the dockerfile I've used to build the image :


FROM python:3.9.2-slim-buster as builder

# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE=1
# Without this setting, Python never prints anything out.
ENV PYTHONUNBUFFERED=1

RUN pip install --upgrade pip
COPY ./Cam/requirements.txt .
RUN pip install -r requirements.txt
RUN apt-get update
RUN apt-get install ffmpeg libsm6 libxext6 -y

WORKDIR /app

FROM builder
COPY ./Cam .
CMD ["python", "camStreamer.py"]



and last, this is the script code (simplified) :


import os, logging, threading
from os.path import join
import sys, inspect, datetime, time
from pathlib import Path
import cv2
import imutils
from imutils.video import VideoStream

def StartRecording(showVideoWindow, interval, imagePath):
 key = None
 cam = VideoStream(os.getenv("CAM_RTSP")).start()
 counter = 0
 try:
 while True:
 ## 2 min retry to connect if frame is None
 if counter > 60/interval*2: break

 ts = time.time()
 ## Wait for [interval] seconds
 while ts + interval > time.time():
 continue
 print(f"Counter: {counter}, ts: {str(ts)}")

 frame = cam.read()
 if frame is None:
 counter += 1
 continue
 counter = 0

 print("frame is valid")
 if showVideoWindow:
 frame = imutils.resize(frame, width=1200)
 cv2.imshow('VIDEO', frame)

 imageName = f"{datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%dT%H_%M_%S')}.jpg"
 cv2.imwrite(join(imagePath, imageName), frame)
 print("saved image to disk")

 key = cv2.waitKey(1) & 0xFF
 if key == ord('q') or key == ord('r'):
 break

 except Exception as e:
 exc_tb = sys.exc_info()[2]
 extra = ""
 print(f"{inspect.stack()[0][3]}: {e} (lineno: {exc_tb.tb_lineno}) {extra}")
 finally:
 if showVideoWindow: cv2.destroyAllWindows()
 cam.stop()
 return key


while True:
 log.warning(f"Starting {Name}")
 key = StartRecording(
 showVideoWindow=(Env.startswith("development") and os.getenv("SHOW_VIDEO") == "True"),
 interval=int(os.getenv("SAVE_IMAGE_INTERVAL")),
 imagePath=os.getenv('CAPTURE_FOLDER')
 )
 if key == ord('q'):
 break



I apologize for the very long post. Hopefully someone can put me on the right direction...


-
Buffered encoded images not saved
26 mars 2021, par xyfixI have an issue with the first 12 images not being saved to file. I have attached the relevant files in this issue. I have also attached a log file to show that the first 12 images aren't written to the file that is generated. The frame rate is 24 fps and the recording is 5 sec, so there should be 120 frames written to the output file. This can be seen in the 4th column. The lines in the log files are as follows :


image num [unique num from camera] [temp image num for recording seq] [time in ms]


The image class is actually a simple wrapper around OpenCV's mat class with some additional members. The output file that I currently get is around 10 MB and when I open it in VLC it doesn't run for 5 seconds but more like 1 - 2 seconds but I can see whatever I have recorded. Can anyone explain to me why the files not written and the duration isn't 5 secs (minus 12 frames missing) as expected . As you can see I have tried with "av_interleaved_write_frame" but that didn't help


xcodec.h


#ifndef XCODEC_H
#define XCODEC_H

#include "image/Image.h"

extern "C"
{
 #include "Codec/include/libavcodec/avcodec.h"
 #include "Codec/include/libavdevice/avdevice.h"
 #include "Codec/include/libavformat/avformat.h"
 #include "Codec/include/libavutil/avutil.h"
 #include "Codec/include/libavformat/avio.h"
 #include "Codec/include/libavutil/imgutils.h"
 #include "Codec/include/libavutil/opt.h"
 #include "Codec/include/libswscale/swscale.h"
}


class XCodec
{
public:

 XCodec(const char *filename);

 ~XCodec();

 void encodeImage( const Image& image );

 void encode( AVFrame *frame, AVPacket *pkt );

 void add_stream();

 void openVideoCodec();

 void write_video_frame(const Image &image);

 void createFrame( const Image& image );

 void close();

private:

 static int s_frameCount;

 int m_timeVideo = 0;

 std::string m_filename;


 AVCodec* m_encoder = NULL;

 AVOutputFormat* m_outputFormat = NULL;

 AVFormatContext* m_formatCtx = NULL;

 AVCodecContext* m_codecCtx = NULL;

 AVStream* m_streamOut = NULL;

 AVFrame* m_frame = NULL;

 AVPacket* m_packet = NULL;

};

#endif



xcodec.cpp


#include "XCodec.h"

#include <qdebug>


#define STREAM_DURATION 5.0
#define STREAM_FRAME_RATE 24
#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
#define OUTPUT_CODEC AV_CODEC_ID_H264

int XCodec::s_frameCount = 0;

XCodec::XCodec( const char* filename ) :
 m_filename( filename ),
 m_encoder( avcodec_find_encoder( OUTPUT_CODEC ))
{
 av_log_set_level(AV_LOG_VERBOSE);

 int ret(0);


 // allocate the output media context
 ret = avformat_alloc_output_context2( &m_formatCtx, m_outputFormat, NULL, m_filename.c_str());

 if (!m_formatCtx)
 return;

 m_outputFormat = m_formatCtx->oformat;

 // Add the video stream using H264 codec
 add_stream();

 // Open video codec and allocate the necessary encode buffers
 if (m_streamOut)
 openVideoCodec();

 // Print detailed information about input and output
 av_dump_format( m_formatCtx, 0, m_filename.c_str(), 1);

 // Open the output media file, if needed
 if (!( m_outputFormat->flags & AVFMT_NOFILE))
 {
 ret = avio_open( &m_formatCtx->pb, m_filename.c_str(), AVIO_FLAG_WRITE);

 if (ret < 0)
 {
 char error[255];
 ret = av_strerror( ret, error, 255);
 fprintf(stderr, "Could not open '%s': %s\n", m_filename.c_str(), error);
 return ;
 }
 }
 else
 {
 return;
 }

 // Write media header
 ret = avformat_write_header( m_formatCtx, NULL );

 if (ret < 0)
 {
 char error[255];
 av_strerror(ret, error, 255);
 fprintf(stderr, "Error occurred when opening output file: %s\n", error);
 return;
 }

 if ( m_frame )
 m_frame->pts = 0;
}



XCodec::~XCodec()
{}

/* Add an output stream. */
void XCodec::add_stream()
{
 AVCodecID codecId = OUTPUT_CODEC;

 if (!( m_encoder ))
 {
 fprintf(stderr, "Could not find encoder for '%s'\n",
 avcodec_get_name(codecId));
 return;
 }

 // Get the stream for codec
 m_streamOut = avformat_new_stream(m_formatCtx, m_encoder);

 if (!m_streamOut) {
 fprintf(stderr, "Could not allocate stream\n");
 return;
 }

 m_streamOut->id = m_formatCtx->nb_streams - 1;

 m_codecCtx = avcodec_alloc_context3( m_encoder);

 switch (( m_encoder)->type)
 {
 case AVMEDIA_TYPE_VIDEO:
 m_streamOut->codecpar->codec_id = codecId;
 m_streamOut->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 m_streamOut->codecpar->bit_rate = 400000;
 m_streamOut->codecpar->width = 800;
 m_streamOut->codecpar->height = 640;
 m_streamOut->codecpar->format = STREAM_PIX_FMT;
 m_streamOut->time_base = { 1, STREAM_FRAME_RATE };

 avcodec_parameters_to_context( m_codecCtx, m_streamOut->codecpar);

 m_codecCtx->gop_size = 12; /* emit one intra frame every twelve frames at most */
 m_codecCtx->max_b_frames = 1;
 m_codecCtx->time_base = { 1, STREAM_FRAME_RATE };
 m_codecCtx->framerate = { STREAM_FRAME_RATE, 1 };
 m_codecCtx->pix_fmt = STREAM_PIX_FMT;
 m_codecCtx->profile = FF_PROFILE_H264_HIGH;

 break;

 default:
 break;
 }

 if (m_streamOut->codecpar->codec_id == OUTPUT_CODEC)
 {
 av_opt_set( m_codecCtx, "preset", "ultrafast", 0 );
 }

/
// /* Some formats want stream headers to be separate. */
 if (m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
 m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;


 int ret = avcodec_parameters_from_context( m_streamOut->codecpar, m_codecCtx );

 if (ret < 0)
 {
 char error[255];
 av_strerror(ret, error, 255);
 fprintf(stderr, "avcodec_parameters_from_context returned (%d) - %s", ret, error);
 return;
 }
}


void XCodec::openVideoCodec()
{
 int ret;

 /* open the codec */
 ret = avcodec_open2(m_codecCtx, m_encoder, NULL);

 if (ret < 0)
 {
 char error[255];
 av_strerror(ret, error, 255);
 fprintf(stderr, "Could not open video codec: %s\n", error);
 return;
 }

 /* allocate and init a re-usable frame */
// m_frame = av_frame_alloc();

}


void XCodec::encodeImage(const Image &image)
{
 // Compute video time from last added video frame
 m_timeVideo = image.timeStamp(); //(double)m_frame->pts) * av_q2d(m_streamOut->time_base);

 // Stop media if enough time
 if (!m_streamOut /*|| m_timeVideo >= STREAM_DURATION*/)
 return;


 // Add a video frame
 write_video_frame( image );

}


void XCodec::write_video_frame( const Image& image )
{
 int ret;

qDebug() << "image num " << image.uniqueImageNumber() << " " << s_frameCount;

 if ( s_frameCount >= STREAM_NB_FRAMES)
 {
 /* No more frames to compress. The codec has a latency of a few
 * frames if using B-frames, so we get the last frames by
 * passing the same picture again. */
 int p( 0 ) ;
 }
 else
 {
 createFrame( image );
 }

 // Increase frame pts according to time base
// m_frame->pts += av_rescale_q(1, m_codecCtx->time_base, m_streamOut->time_base);
 m_frame->pts = int64_t( image.timeStamp()) ;


 if (m_formatCtx->oformat->flags & 0x0020 )
 {
 /* Raw video case - directly store the picture in the packet */
 AVPacket pkt;
 av_init_packet(&pkt);

 pkt.flags |= AV_PKT_FLAG_KEY;
 pkt.stream_index = m_streamOut->index;
 pkt.data = m_frame->data[0];
 pkt.size = sizeof(AVPicture);

// ret = av_interleaved_write_frame(m_formatCtx, &pkt);
 ret = av_write_frame( m_formatCtx, &pkt );
 }
 else
 {
 AVPacket pkt;
 av_init_packet(&pkt);

 /* encode the image */
 ret = avcodec_send_frame(m_codecCtx, m_frame);

 if (ret < 0)
 {
 char error[255];
 av_strerror(ret, error, 255);
 fprintf(stderr, "Error encoding video frame: %s\n", error);
 return;
 }

 /* If size is zero, it means the image was buffered. */
 ret = avcodec_receive_packet(m_codecCtx, &pkt);

 if( !ret && pkt.size)
 {
qDebug() << "write frame " << m_frame->display_picture_number;
 pkt.stream_index = m_streamOut->index;

 /* Write the compressed frame to the media file. */
// ret = av_interleaved_write_frame(m_formatCtx, &pkt);
 ret = av_write_frame( m_formatCtx, &pkt );
 }
 else
 {
 ret = 0;
 }
 }

 if (ret != 0)
 {
 char error[255];
 av_strerror(ret, error, 255);
 fprintf(stderr, "Error while writing video frame: %s\n", error);
 return;
 }

 s_frameCount++;
}


void XCodec::createFrame( const Image& image /*, AVFrame *m_frame, int frame_index, int width, int height*/)
{
 /**
 * \note allocate frame
 */
 m_frame = av_frame_alloc();
 int ret = av_frame_make_writable( m_frame );

 m_frame->format = STREAM_PIX_FMT;
 m_frame->width = image.width();
 m_frame->height = image.height();
// m_frame->pict_type = AV_PICTURE_TYPE_I;
 m_frame->display_picture_number = image.uniqueImageNumber();

 ret = av_image_alloc(m_frame->data, m_frame->linesize, m_frame->width, m_frame->height, STREAM_PIX_FMT, 1);

 if (ret < 0)
 {
 return;
 }

 struct SwsContext* sws_ctx = sws_getContext((int)image.width(), (int)image.height(), AV_PIX_FMT_RGB24,
 (int)image.width(), (int)image.height(), STREAM_PIX_FMT, 0, NULL, NULL, NULL);

 const uint8_t* rgbData[1] = { (uint8_t* )image.getData() };
 int rgbLineSize[1] = { 3 * image.width() };

 sws_scale(sws_ctx, rgbData, rgbLineSize, 0, image.height(), m_frame->data, m_frame->linesize);

//cv::Mat yuv420p( m_frame->height + m_frame->height/2, m_frame->width, CV_8UC1, m_frame->data[0]);
//cv::Mat cvmIm;
//cv::cvtColor(yuv420p,cvmIm,CV_YUV420p2BGR);
//std::ostringstream ss;
//ss << "c:\\tmp\\YUVoriginal_" << image.uniqueImageNumber() << ".png";
//cv::imwrite( ss.str().c_str(), cvmIm);
}


void XCodec::close()
{
 /* reset the framecount */
 s_frameCount = 0 ;

 int ret( 0 );

 /* flush the encoder */
 while( ret >= 0 )
 ret = avcodec_send_frame(m_codecCtx, NULL);

 // Write media trailer
 if( m_formatCtx )
 ret = av_write_trailer( m_formatCtx );

 /* Close each codec. */
 if ( m_streamOut )
 {
 if( m_frame )
 {
 av_free( m_frame->data[0]);
 av_frame_free( &m_frame );
 }

 if( m_packet )
 av_packet_free( &m_packet );
 }

 if (!( m_outputFormat->flags & AVFMT_NOFILE))
 /* Close the output file. */
 ret = avio_close( m_formatCtx->pb);


 /* free the stream */
 avformat_free_context( m_formatCtx );

 fflush( stdout );
}
</qdebug>


image.h


#ifndef IMAGE_H
#define IMAGE_H

#include 

class Image 
{
public:

 Image();

 Image( const cv::Mat& mat );

 Image(const Image& other) = default;

 Image(Image&& other) = default;

 ~Image();


 inline const cv::Mat& matrix() const{ return m_matrix; }

 inline const int uniqueImageNumber() const{ return m_uniqueId; }

 inline const int timeStamp() const { return m_timeStamp; }

 inline const int width() const { return m_matrix.cols(); }
 
 inline const int height() const { return m_matrix.rows(); }

private:

 cv::Mat m_matrix;

 int m_timeStamp;

 int m_uniqueId;

};

#endif



logtxt


image num 1725 0 0
 image num 1727 1 40
 image num 1729 2 84
 image num 1730 3 126
 image num 1732 4 169
 image num 1734 5 211
 image num 1736 6 259
 image num 1738 7 297
 image num 1740 8 340
 image num 1742 9 383
 image num 1744 10 425
 image num 1746 11 467
 image num 1748 12 511
 image num 1750 13 553
 write frame 1750
 image num 1752 14 600
 write frame 1752
 image num 1753 15 637
 write frame 1753
 image num 1755 16 680
 write frame 1755
 image num 1757 17 723
 write frame 1757
 image num 1759 18 766
 write frame 1759
 image num 1761 19 808
 write frame 1761
 image num 1763 20 854
 write frame 1763
 image num 1765 21 893
 write frame 1765
 image num 1767 22 937
 write frame 1767
 image num 1769 23 979
 write frame 1769
 image num 1770 24 1022
 write frame 1770
 image num 1772 25 1064
 write frame 1772
 image num 1774 26 1108
 write frame 1774
 image num 1776 27 1150
 write frame 1776
 image num 1778 28 1192
 write frame 1778
 image num 1780 29 1235
 write frame 1780
 image num 1782 30 1277
 write frame 1782
 image num 1784 31 1320
 write frame 1784
 image num 1786 32 1362
 write frame 1786
 image num 1787 33 1405
 write frame 1787
 image num 1789 34 1450
 write frame 1789
 image num 1791 35 1493
 write frame 1791
 image num 1793 36 1536
 write frame 1793
 image num 1795 37 1578
 write frame 1795
 image num 1797 38 1621
 write frame 1797
 image num 1799 39 1663
 write frame 1799
 image num 1801 40 1709
 write frame 1801
 image num 1803 41 1748
 write frame 1803
 image num 1805 42 1791
 write frame 1805
 image num 1807 43 1833
 write frame 1807
 image num 1808 44 1876
 write frame 1808
 image num 1810 45 1920
 write frame 1810
 image num 1812 46 1962
 write frame 1812
 image num 1814 47 2004
 write frame 1814
 image num 1816 48 2048
 write frame 1816
 image num 1818 49 2092
 write frame 1818
 image num 1820 50 2133
 write frame 1820
 image num 1822 51 2175
 write frame 1822
 image num 1824 52 2221
 write frame 1824
 image num 1826 53 2277
 write frame 1826
 image num 1828 54 2319
 write frame 1828
 image num 1830 55 2361
 write frame 1830
 image num 1832 56 2405
 write frame 1832
 image num 1833 57 2447
 write frame 1833
 image num 1835 58 2491
 write frame 1835
 image num 1837 59 2533
 write frame 1837
 image num 1839 60 2576
 write frame 1839
 image num 1841 61 2619
 write frame 1841
 image num 1843 62 2662
 write frame 1843
 image num 1845 63 2704
 write frame 1845
 image num 1847 64 2746
 write frame 1847
 image num 1849 65 2789
 write frame 1849
 image num 1851 66 2831
 write frame 1851
 image num 1852 67 2874
 write frame 1852
 image num 1854 68 2917
 write frame 1854
 image num 1856 69 2959
 write frame 1856
 image num 1858 70 3003
 write frame 1858
 image num 1860 71 3045
 write frame 1860
 image num 1862 72 3088
 write frame 1862
 image num 1864 73 3130
 write frame 1864
 image num 1866 74 3173
 write frame 1866
 image num 1868 75 3215
 write frame 1868
 image num 1870 76 3257
 write frame 1870
 image num 1872 77 3306
 write frame 1872
 image num 1873 78 3347
 write frame 1873
 image num 1875 79 3389
 write frame 1875
 image num 1877 80 3433
 write frame 1877
 image num 1879 81 3475
 write frame 1879
 image num 1883 82 3562
 write frame 1883
 image num 1885 83 3603
 write frame 1885
 image num 1887 84 3660
 write frame 1887
 image num 1889 85 3704
 write frame 1889
 image num 1891 86 3747
 write frame 1891
 image num 1893 87 3789
 write frame 1893
 image num 1895 88 3832
 write frame 1895
 image num 1897 89 3874
 write frame 1897
 image num 1899 90 3917
 write frame 1899
 image num 1900 91 3959
 write frame 1900
 image num 1902 92 4001
 write frame 1902
 image num 1904 93 4044
 write frame 1904
 image num 1906 94 4086
 write frame 1906
 image num 1908 95 4130
 write frame 1908
 image num 1910 96 4174
 write frame 1910
 image num 1912 97 4216
 write frame 1912
 image num 1914 98 4257
 write frame 1914
 image num 1915 99 4303
 write frame 1915
 image num 1918 100 4344
 write frame 1918
 image num 1919 101 4387
 write frame 1919
 image num 1922 102 4451
 write frame 1922
 image num 1924 103 4494
 write frame 1924
 image num 1926 104 4541
 write frame 1926
 image num 1927 105 4588
 write frame 1927
 image num 1931 106 4665
 write frame 1931
 image num 1933 107 4707
 write frame 1933
 image num 1935 108 4750
 write frame 1935
 image num 1937 109 4794
 write frame 1937
 image num 1939 110 4836
 write frame 1939
 image num 1941 111 4879
 write frame 1941
 image num 1943 112 4922
 write frame 1943
 image num 1945 113 4965
 write frame 1945
 image num 1947 114 5007
 write frame 1947
 image num 1948 115 5050
 write frame 1948
 image num 1950 116 5093
 write frame 1950
 image num 1952 117 5136
 write frame 1952
 image num 1954 118 5178
 write frame 1954
 image num 1956 119 5221
 write frame 1956
 MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
0, 8-bit
Not writing 'clli' atom. No content light level info.
Not writing 'mdcv' atom. Missing mastering metadata.
 2 seeks, 41 writeouts



-
Safari on Mac and IOS 14 Won't Play HTML 5 MP4 Video
10 mars 2021, par Glen ElkinsSo i have developed a chat application that uses node for the back-end. When a user selects a video on their iphone it usually is .mov format so when it's sent to the node server it's then converted to mp4 with ffmpeg. All that works fine, then if i load up my chat again in Chrome on my mac the video plays just fine as the mp4.




This screenshot shows the video embed is there, set to mp4 yet it won't play in Safari on my mac or my phone, in fact it just shows the video as 0 seconds long yet i can play it in chrome and also download the mp4 file by accessing the embed url directly.


Any ideas ? I had it convert to mp4 to prevent things like this, but safari doesn't seem to even like mp4 files.


The back-end part that serves the private file is in Symfony 4 (PHP) :


/**
 * @Route("/private/files/download/{base64Path}", name="downloadFile")
 * @param string $base64Path
 * @param Request $request
 * @return Response
 */
 public function downloadFile(string $base64Path, Request $request) : Response
 {


 // get token
 if(!$token = $request->query->get('token')){
 return new Response('Access Denied',403);
 }



 /** @var UserRepository $userRepo */
 $userRepo = $this->getDoctrine()->getRepository(User::class);

 /** @var User $user */
 if(!$user = $userRepo->findOneBy(['deleted'=>false,'active'=>true,'systemUser'=>false,'apiKey'=>$token])){
 return new Response('Access Denied',403);
 }



 // get path
 if($path = base64_decode($base64Path)){

 // make sure the folder we need exists
 $fullPath = $this->getParameter('private_upload_folder') . '/' . $path;



 if(!file_exists($fullPath)){
 return new Response('File Not Found',404);
 }

 

 $response = new Response();
 $response->headers->set('Content-Type', mime_content_type($fullPath));
 $response->headers->set('Content-Disposition', 'inline; filename="' . basename($fullPath) . '"');
 $response->headers->set('Content-Length', filesize($fullPath));
 $response->headers->set('Pragma', "no-cache");
 $response->headers->set('Expires', "0");
 $response->headers->set('Content-Transfer-Encoding', "binary");

 $response->sendHeaders();

 $response->setContent(readfile($fullPath));

 return $response;
 }

 return new Response('Invalid Path',404);
 }



This works fine everywhere except safari when trying to embed the video. It's done like this because the videos are not public and need an access token.


UPDATE : Here is a test link of an mp4, you'll have to allow the insecure certificate as it's on a quick test sub domain. If you open it in chrome, you'll see a 3 second video of my 3d printer curing station, if you load the same link in safari, you'll see it doesn't work




The server runs on cPanel with Apache and i think it might be something to do with the video needs streaming ?


UPDATED CODE THAT WORKS IN SAFARI BUT NOW BROKEN IN CHROME :


Chrome is now giving Content-Length : 0 but it's working fine in safari.


public function downloadFile(string $base64Path, Request $request) : ?Response
 {

 ob_clean();

 // get token
 if(!$token = $request->query->get('token')){
 return new Response('Access Denied',403);
 }


 

 /** @var UserRepository $userRepo */
 $userRepo = $this->getDoctrine()->getRepository(User::class);

 /** @var User $user */
 if(!$user = $userRepo->findOneBy(['deleted'=>false,'active'=>true,'systemUser'=>false,'apiKey'=>$token])){
 return new Response('Access Denied',403);
 }



 // get path
 if($path = base64_decode($base64Path)){

 // make sure the folder we need exists
 $fullPath = $this->getParameter('private_upload_folder') . '/' . $path;



 if(!file_exists($fullPath)){
 return new Response('File Not Found',404);
 }


 $filesize = filesize($fullPath);
 $mime = mime_content_type($fullPath);

 header('Content-Type: ' . $mime);

 if(isset($_SERVER['HTTP_RANGE'])){

 // Parse the range header to get the byte offset
 $ranges = array_map(
 'intval', // Parse the parts into integer
 explode(
 '-', // The range separator
 substr($_SERVER['HTTP_RANGE'], 6) // Skip the `bytes=` part of the header
 )
 );



 // If the last range param is empty, it means the EOF (End of File)
 if(!$ranges[1]){
 $ranges[1] = $filesize - 1;
 }

 header('HTTP/1.1 206 Partial Content');
 header('Accept-Ranges: bytes');
 header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range

 // Send the ranges we offered
 header(
 sprintf(
 'Content-Range: bytes %d-%d/%d', // The header format
 $ranges[0], // The start range
 $ranges[1], // The end range
 $filesize // Total size of the file
 )
 );

 // It's time to output the file
 $f = fopen($fullPath, 'rb'); // Open the file in binary mode
 $chunkSize = 8192; // The size of each chunk to output

 // Seek to the requested start range
 fseek($f, $ranges[0]);

 // Start outputting the data
 while(true){
 // Check if we have outputted all the data requested
 if(ftell($f) >= $ranges[1]){
 break;
 }

 // Output the data
 echo fread($f, $chunkSize);

 // Flush the buffer immediately
 @ob_flush();
 flush();
 }
 }else{

 // It's not a range request, output the file anyway
 header('Content-Length: ' . $filesize);

 // Read the file
 @readfile($filesize);

 // and flush the buffer
 @ob_flush();
 flush();



 }

 }else {

 return new Response('Invalid Path', 404);
 }
 }



I have notice in chrome that it's sending the range header like this :


Range : bytes=611609-


Where safari sends


Range : bytes=611609-61160


So for some reason chrome is missing the second range amount, that obviously means my code can't find a range number for the second one.


Doesn’t matter what I do I can’t get it working in both chrome and safari. Safari wants the byte range part , chrome seems to request it then sends a new request for the full file but even the full file part of the code gives a 500 error. If I take out the byte range bit then it works fine in chrome but not safari.


UPDATE :


Here is some strange things going on in chrome :


For the video i am testing with it makes 3 range requests :


REQUEST 1 HEADERS - asking for bytes 0- (to the end of the file)


GET /private/files/download/Y2hhdC83Nzk1Y2U2MC04MDFmLTExZWItYjkzYy1lZjI4ZGYwMDhkOTMubXA0?token=6ab1720bfe922d44208c25f655d61032 HTTP/1.1

Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36
Accept-Encoding: identity;q=1, *;q=0
Accept: */*
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: video
Referer: https://gofollow.vip/
Accept-Language: en-US,en;q=0.9
Range: bytes=0-



RESPONSE GIVES IT BACK ALL THE BYTES IN THE FILE AS THAT'S WHAT WAS ASKED FOR BY CHROME :


HTTP/1.1 206 Partial Content
Date: Wed, 10 Mar 2021 12:35:54 GMT
Server: Apache
Accept-Ranges: bytes
Content-Length: 611609
Content-Range: bytes 0-611609/611610
Vary: User-Agent
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: video/mp4



SECOND REQUEST HEADERS : NOW IT'S ASKING FOR 589824 to the end of the file :


Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36
Accept-Encoding: identity;q=1, *;q=0
Accept: */*
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: video
Referer: https://gofollow.vip/
Accept-Language: en-US,en;q=0.9
Range: bytes=589824-



RESPONSE OBLIGES :


HTTP/1.1 206 Partial Content
Date: Wed, 10 Mar 2021 12:35:55 GMT
Server: Apache
Accept-Ranges: bytes
Content-Length: 21785
Content-Range: bytes 589824-611609/611610
Vary: User-Agent
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: video/mp4



THEN IT'S MAKING THIS 3rd REQUEST THAT GIVES AN INTERNAL SERVER ERORR, THIS TIME IT'S LITERALLY ASKING FOR THE LAST BYTE :


GET /private/files/download/Y2hhdC83Nzk1Y2U2MC04MDFmLTExZWItYjkzYy1lZjI4ZGYwMDhkOTMubXA0?token=6ab1720bfe922d44208c25f655d61032 HTTP/1.1

Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36
Accept-Encoding: identity;q=1, *;q=0
Accept: */*
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: video
Referer: https://gofollow.vip/
Accept-Language: en-US,en;q=0.9
Range: bytes=611609-



RESPONSE - THE CONTENT LENGTH IS 0 BECAUSE THERE IS NO DIFFERENCE BETWEEN THE REQUESTED BYTES AND THE BYTES RETURNED :


HTTP/1.1 500 Internal Server Error
Date: Wed, 10 Mar 2021 12:35:56 GMT
Server: Apache
Accept-Ranges: bytes
Cache-Control: max-age=0, must-revalidate, private
X-Frame-Options: DENY
X-XSS-Protection: 1
X-Content-Type-Options: nosniff
Referrer-Policy: origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
Expires: Wed, 10 Mar 2021 12:35:56 GMT
Content-Length: 0
Content-Range: bytes 611609-611609/611610
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8