rework pts/dts of audio stream. Spacing. Fix crash

This commit is contained in:
Isaac Connor 2018-12-04 18:23:08 -05:00
commit bc5f8d0d8d
14 changed files with 336 additions and 318 deletions

View File

@ -32,6 +32,7 @@ configure_file(httpd/com.zoneminder.systemctl.rules.httpd.in ${CMAKE_CURRENT_SOU
# Configure the Nginx zoneminder files # Configure the Nginx zoneminder files
configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COPYONLY) configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COPYONLY)
configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY)
configure_file(nginx/redirect.nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/redirect.nginx.conf COPYONLY)
configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY) configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY)
configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY) configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY)
configure_file(nginx/zoneminder.php-fpm.conf ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf COPYONLY) configure_file(nginx/zoneminder.php-fpm.conf ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf COPYONLY)
@ -62,6 +63,7 @@ install(FILES com.zoneminder.systemctl.rules.httpd DESTINATION /etc/zm/www PERMI
# Install the Nginx zoneminder files # Install the Nginx zoneminder files
install(FILES zm-nginx.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zm-nginx.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES redirect.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zoneminder.nginx.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.nginx.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES com.zoneminder.systemctl.rules.nginx DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES com.zoneminder.systemctl.rules.nginx DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
install(FILES zm-web-user.conf DESTINATION /etc/zm/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zm-web-user.conf DESTINATION /etc/zm/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)

View File

@ -0,0 +1,2 @@
# Auto redirect to https
return 301 https://$host$request_uri;

View File

@ -1,38 +1,40 @@
listen 443 ssl; server {
listen [::]:443 ssl; listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name = localhost $hostname;
ssl_certificate "/etc/pki/tls/certs/localhost.crt"; ssl_certificate "/etc/pki/tls/certs/localhost.crt";
ssl_certificate_key "/etc/pki/tls/private/localhost.key"; ssl_certificate_key "/etc/pki/tls/private/localhost.key";
ssl_session_cache shared:SSL:1m; ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m; ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM; ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers on;
# Auto-redirect HTTP requests to HTTPS # Auto redirect to server/zm when no url suffix was given
if ($scheme != "https") { location = / {
rewrite ^/?(zm)(.*)$ https://$host/$1$2 permanent; return 301 zm;
} }
location /cgi-bin-zm { location /cgi-bin-zm {
gzip off; gzip off;
alias "@ZM_CGIDIR@"; alias "@ZM_CGIDIR@";
include /etc/nginx/fastcgi_params; include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/fcgiwrap.sock; fastcgi_pass unix:/run/fcgiwrap.sock;
} }
location /zm/cache { location /zm/cache {
alias "@ZM_CACHEDIR@"; alias "@ZM_CACHEDIR@";
} }
location /zm { location /zm {
gzip off; gzip off;
alias "@ZM_WEBDIR@"; alias "@ZM_WEBDIR@";
index index.php; index index.php;
location ~ \.php$ { location ~ \.php$ {
if (!-f $request_filename) { return 404; } try_files $uri =404;
expires epoch; expires epoch;
include /etc/nginx/fastcgi_params; include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;
@ -49,5 +51,7 @@ location /zm {
alias "@ZM_WEBDIR@"; alias "@ZM_WEBDIR@";
rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last; rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last;
} }
}
} }

View File

@ -61,8 +61,7 @@ New installs
6. Configure the web server 6. Configure the web server
This package uses the HTTPS protocol by default to access the web portal, This package uses the HTTPS protocol by default to access the web portal,
using the default self signed certificate on your system. Requests using using the default self signed certificate on your system.
HTTP will auto-redirect to HTTPS.
Inspect the web server configuration file and verify it meets your needs: Inspect the web server configuration file and verify it meets your needs:
@ -71,9 +70,13 @@ New installs
If you are running other web enabled services then you may need to edit If you are running other web enabled services then you may need to edit
this file to suite. See README.https to learn about other alternatives. this file to suite. See README.https to learn about other alternatives.
If you wish http requests to auto-redirect to https requests, then link or
copy /etc/zm/www/redirect.nginx.conf into /etc/nginx/default.d folder.
When in doubt, proceed with the default: When in doubt, proceed with the default:
sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/conf.d/
sudo ln -sf /etc/zm/www/redirect.nginx.conf /etc/nginx/default.d/
7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of 7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of
simulatneous streams the server should support. Generally, a good minimum simulatneous streams the server should support. Generally, a good minimum

View File

@ -390,6 +390,7 @@ EOF
%config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/*.conf %config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/*.conf
%ghost %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/zmcustom.conf %ghost %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/zmcustom.conf
%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.nginx.conf %config(noreplace) %{_sysconfdir}/zm/www/zoneminder.nginx.conf
%config(noreplace) %{_sysconfdir}/zm/www/redirect.nginx.conf
%ghost %{_sysconfdir}/zm/www/zoneminder.conf %ghost %{_sysconfdir}/zm/www/zoneminder.conf
%config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx
%ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules

View File

@ -2,6 +2,7 @@
# Create files from the .in files # Create files from the .in files
configure_file(apache.conf.in "${CMAKE_CURRENT_BINARY_DIR}/apache.conf" @ONLY) configure_file(apache.conf.in "${CMAKE_CURRENT_BINARY_DIR}/apache.conf" @ONLY)
configure_file(nginx.conf.in "${CMAKE_CURRENT_BINARY_DIR}/nginx.conf" @ONLY)
configure_file(logrotate.conf.in "${CMAKE_CURRENT_BINARY_DIR}/logrotate.conf" @ONLY) configure_file(logrotate.conf.in "${CMAKE_CURRENT_BINARY_DIR}/logrotate.conf" @ONLY)
configure_file(syslog.conf.in "${CMAKE_CURRENT_BINARY_DIR}/syslog.conf" @ONLY) configure_file(syslog.conf.in "${CMAKE_CURRENT_BINARY_DIR}/syslog.conf" @ONLY)
configure_file(com.zoneminder.systemctl.policy.in "${CMAKE_CURRENT_BINARY_DIR}/com.zoneminder.systemctl.policy" @ONLY) configure_file(com.zoneminder.systemctl.policy.in "${CMAKE_CURRENT_BINARY_DIR}/com.zoneminder.systemctl.policy" @ONLY)

61
misc/nginx.conf.in Normal file
View File

@ -0,0 +1,61 @@
#
# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION
#
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name = localhost $hostname;
ssl_certificate "/etc/pki/tls/certs/localhost.crt";
ssl_certificate_key "/etc/pki/tls/private/localhost.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
# Auto redirect to server/zm when no url suffix was given
location = / {
return 301 zm;
}
location /cgi-bin-zm {
gzip off;
alias "@ZM_CGIDIR@";
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/fcgiwrap.sock;
}
location /zm/cache {
alias "@ZM_CACHEDIR@";
}
location /zm {
gzip off;
alias "@ZM_WEBDIR@";
index index.php;
location ~ \.php$ {
try_files $uri =404;
expires epoch;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_index index.php;
fastcgi_pass unix:/run/php-fpm/www.sock;
}
location ~ \.(jpg|jpeg|gif|png|ico)$ {
access_log off;
expires 33d;
}
location /zm/api/ {
alias "@ZM_WEBDIR@";
rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last;
}
}
}

View File

@ -208,7 +208,7 @@ sub zmDbGetMonitor {
return undef; return undef;
} }
my $res = $sth->execute($id); my $res = $sth->execute($id);
if ( $res ) { if ( !$res ) {
Error("Can't execute '$sql': ".$sth->errstr()); Error("Can't execute '$sql': ".$sth->errstr());
return undef; return undef;
} }

View File

@ -507,7 +507,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
//if ( errno != EAGAIN ) //if ( errno != EAGAIN )
{ {
Error("Can't sendto on sd %d: %s", sd, strerror(errno)); Error("Can't sendto on sd %d: %s", sd, strerror(errno));
exit(-1); //exit(-1);
} }
} }
// quit after sending a status, if this was a quit request // quit after sending a status, if this was a quit request
@ -844,7 +844,7 @@ Debug(3,"cur_frame_id (%d-1) mod frame_mod(%d)",curr_frame_id, frame_mod);
// so if it is 2, then we send every other frame, if is it 4 then every fourth frame, etc. // so if it is 2, then we send every other frame, if is it 4 then every fourth frame, etc.
if ( (frame_mod == 1) || (((curr_frame_id-1)%frame_mod) == 0) ) { if ( (frame_mod == 1) || (((curr_frame_id-1)%frame_mod) == 0) ) {
delta_us = (unsigned int)(frame_data->delta * 1000000); delta_us = (unsigned int)(frame_data->delta * 1000000);
Debug(3,"frame delta %u ", delta_us); Debug(3,"frame delta %uus ", delta_us);
// if effective > base we should speed up frame delivery // if effective > base we should speed up frame delivery
delta_us = (unsigned int)((delta_us * base_fps)/effective_fps); delta_us = (unsigned int)((delta_us * base_fps)/effective_fps);
Debug(3,"delta %u = base_fps(%f)/effective fps(%f)", delta_us, base_fps, effective_fps); Debug(3,"delta %u = base_fps(%f)/effective fps(%f)", delta_us, base_fps, effective_fps);

View File

@ -815,6 +815,7 @@ unsigned int Monitor::GetLastWriteIndex() const {
} }
uint64_t Monitor::GetLastEventId() const { uint64_t Monitor::GetLastEventId() const {
#if 0
Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%" PRIu64 ")", Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%" PRIu64 ")",
mem_ptr, mem_ptr,
shared_data->state, shared_data->state,
@ -822,6 +823,7 @@ uint64_t Monitor::GetLastEventId() const {
shared_data->last_read_time, shared_data->last_read_time,
shared_data->last_event shared_data->last_event
); );
#endif
return shared_data->last_event; return shared_data->last_event;
} }

View File

@ -64,7 +64,8 @@ void StreamBase::updateFrameRate(double fps) {
base_fps = fps; base_fps = fps;
effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE;
frame_mod = 1; frame_mod = 1;
Debug(3, "FPS:%.2f, MaxFPS:%.2f, BaseFPS:%.2f, EffectiveFPS:%.2f, FrameMod:%d", fps, maxfps, base_fps, effective_fps, frame_mod); Debug(3, "FPS:%.2f, MaxFPS:%.2f, BaseFPS:%.2f, EffectiveFPS:%.2f, FrameMod:%d, replay_rate(%d)",
fps, maxfps, base_fps, effective_fps, frame_mod, replay_rate);
// Min frame repeat? // Min frame repeat?
while( effective_fps > maxfps ) { while( effective_fps > maxfps ) {
effective_fps /= 2.0; effective_fps /= 2.0;

View File

@ -31,10 +31,15 @@ extern "C" {
#include "libavutil/time.h" #include "libavutil/time.h"
} }
VideoStore::VideoStore(const char *filename_in, const char *format_in, VideoStore::VideoStore(
const char *filename_in,
const char *format_in,
AVStream *p_video_in_stream, AVStream *p_video_in_stream,
AVStream *p_audio_in_stream, int64_t nStartTime, AVStream *p_audio_in_stream,
Monitor *monitor) { int64_t nStartTime,
Monitor *monitor
) {
video_in_stream = p_video_in_stream; video_in_stream = p_video_in_stream;
audio_in_stream = p_audio_in_stream; audio_in_stream = p_audio_in_stream;
@ -54,7 +59,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Info("Opening video storage stream %s format: %s", filename, format); Info("Opening video storage stream %s format: %s", filename, format);
ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename); ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
if (ret < 0) { if ( ret < 0 ) {
Warning( Warning(
"Could not create video storage stream %s as no out ctx" "Could not create video storage stream %s as no out ctx"
" could be assigned based on filename: %s", " could be assigned based on filename: %s",
@ -66,7 +71,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
// Couldn't deduce format from filename, trying from format name // Couldn't deduce format from filename, trying from format name
if ( !oc ) { if ( !oc ) {
avformat_alloc_output_context2(&oc, NULL, format, filename); avformat_alloc_output_context2(&oc, NULL, format, filename);
if (!oc) { if ( !oc ) {
Error( Error(
"Could not create video storage stream %s as no out ctx" "Could not create video storage stream %s as no out ctx"
" could not be assigned based on filename or format %s", " could not be assigned based on filename or format %s",
@ -80,12 +85,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVDictionary *pmetadata = NULL; AVDictionary *pmetadata = NULL;
int dsr = int dsr =
av_dict_set(&pmetadata, "title", "Zoneminder Security Recording", 0); av_dict_set(&pmetadata, "title", "Zoneminder Security Recording", 0);
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__); if ( dsr < 0 ) Warning("%s:%d: title set failed", __FILE__, __LINE__);
oc->metadata = pmetadata; oc->metadata = pmetadata;
out_format = oc->oformat; out_format = oc->oformat;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
video_out_stream = avformat_new_stream(oc, NULL); video_out_stream = avformat_new_stream(oc, NULL);
if ( !video_out_stream ) { if ( !video_out_stream ) {
@ -96,8 +100,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} }
// Since we are not re-encoding, all we have to do is copy the parameters // Since we are not re-encoding, all we have to do is copy the parameters
video_out_ctx = video_out_stream->codec; video_out_ctx = video_out_stream->codec;
//video_out_ctx = avcodec_alloc_context3(NULL);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Copy params from instream to ctx // Copy params from instream to ctx
ret = avcodec_parameters_to_context(video_out_ctx, ret = avcodec_parameters_to_context(video_out_ctx,
video_in_stream->codecpar); video_in_stream->codecpar);
@ -126,12 +130,12 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
zm_dump_codecpar(video_in_stream->codecpar); zm_dump_codecpar(video_in_stream->codecpar);
zm_dump_codecpar(video_out_stream->codecpar); zm_dump_codecpar(video_out_stream->codecpar);
AVCodec *video_out_codec = avcodec_find_encoder( video_out_ctx->codec_id ); AVCodec *video_out_codec = avcodec_find_encoder(video_out_ctx->codec_id);
if ( !video_out_codec ) { if ( !video_out_codec ) {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Fatal( "Could not find encoder for '%s'", avcodec_get_name( video_out_ctx->codec_id ) ); Fatal("Could not find encoder for '%s'", avcodec_get_name(video_out_ctx->codec_id));
#else #else
Fatal( "Could not find encoder for '%d'", video_out_ctx->codec_id ); Fatal("Could not find encoder for '%d'", video_out_ctx->codec_id);
#endif #endif
} }
@ -146,36 +150,26 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVDictionaryEntry *e = NULL; AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Encoder Option %s not recognized by ffmpeg codec", e->key); Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
} }
#else #else
video_out_stream =
avformat_new_stream(oc, NULL);
//(AVCodec *)(video_in_ctx->codec));
//avformat_new_stream(oc,(const AVCodec *)(video_in_ctx->codec));
if ( !video_out_stream ) {
Fatal("Unable to create video out stream");
} else {
Debug(2, "Success creating video out stream");
}
video_out_ctx = video_out_stream->codec;
ret = avcodec_copy_context(video_out_ctx, video_in_ctx); ret = avcodec_copy_context(video_out_ctx, video_in_ctx);
if (ret < 0) { if ( ret < 0 ) {
Fatal("Unable to copy in video ctx to out video ctx %s\n", Fatal("Unable to copy in video ctx to out video ctx %s",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} else { } else {
Debug(3, "Success copying ctx"); Debug(3, "Success copying ctx");
} }
if (!video_out_ctx->codec_tag) { if ( !video_out_ctx->codec_tag ) {
Debug(2, "No codec_tag"); Debug(2, "No codec_tag");
if (!oc->oformat->codec_tag || if (
av_codec_get_id(oc->oformat->codec_tag, !oc->oformat->codec_tag
video_in_ctx->codec_tag) == ||
video_out_ctx->codec_id || av_codec_get_id(oc->oformat->codec_tag, video_in_ctx->codec_tag) == video_out_ctx->codec_id
av_codec_get_tag(oc->oformat->codec_tag, ||
video_in_ctx->codec_id) <= 0) { av_codec_get_tag(oc->oformat->codec_tag, video_in_ctx->codec_id) <= 0
) {
Warning("Setting codec tag"); Warning("Setting codec tag");
video_out_ctx->codec_tag = video_in_ctx->codec_tag; video_out_ctx->codec_tag = video_in_ctx->codec_tag;
} }
@ -199,7 +193,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_out_ctx->time_base.num, video_out_ctx->time_base.num,
video_out_ctx->time_base.den); video_out_ctx->time_base.den);
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else #else
@ -238,7 +232,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
if ( audio_in_stream ) { if ( audio_in_stream ) {
Debug(3, "Have audio stream"); Debug(3, "Have audio stream");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_in_ctx = avcodec_alloc_context3(NULL); audio_in_ctx = avcodec_alloc_context3(NULL);
ret = avcodec_parameters_to_context(audio_in_ctx, ret = avcodec_parameters_to_context(audio_in_ctx,
audio_in_stream->codecpar); audio_in_stream->codecpar);
@ -246,16 +239,16 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
audio_in_ctx = audio_in_stream->codec; audio_in_ctx = audio_in_stream->codec;
#endif #endif
if (audio_in_ctx->codec_id != AV_CODEC_ID_AAC) { if ( audio_in_ctx->codec_id != AV_CODEC_ID_AAC ) {
static char error_buffer[256]; static char error_buffer[256];
avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0); avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0);
Debug(2, "Got something other than AAC (%s)", error_buffer); Debug(2, "Got something other than AAC (%s)", error_buffer);
if (!setup_resampler()) { if ( !setup_resampler() ) {
return; return;
} }
} else { } else {
Debug(3, "Got AAC"); Debug(2, "Got AAC");
audio_out_stream = audio_out_stream =
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -264,22 +257,20 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec); avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec);
#endif #endif
if ( !audio_out_stream ) { if ( !audio_out_stream ) {
Error("Unable to create audio out stream\n"); Error("Unable to create audio out stream");
audio_out_stream = NULL; audio_out_stream = NULL;
} else { } else {
Debug(2, "setting parameters");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_out_ctx = avcodec_alloc_context3(audio_out_codec); audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
// Copy params from instream to ctx // Copy params from instream to ctx
ret = avcodec_parameters_to_context(audio_out_ctx, ret = avcodec_parameters_to_context(
audio_in_stream->codecpar); audio_out_ctx, audio_in_stream->codecpar);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("Unable to copy audio params to ctx %s", Error("Unable to copy audio params to ctx %s",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} }
ret = avcodec_parameters_from_context(audio_out_stream->codecpar, ret = avcodec_parameters_from_context(
audio_out_ctx); audio_out_stream->codecpar, audio_out_ctx);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("Unable to copy audio params to stream %s", Error("Unable to copy audio params to stream %s",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
@ -291,7 +282,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Debug(2, "Setting audio codec tag to %d", Debug(2, "Setting audio codec tag to %d",
audio_out_ctx->codec_tag); audio_out_ctx->codec_tag);
} }
#else #else
audio_out_ctx = audio_out_stream->codec; audio_out_ctx = audio_out_stream->codec;
ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx); ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx);
@ -313,7 +303,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} // end if is AAC } // end if is AAC
if ( audio_out_stream ) { if ( audio_out_stream ) {
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else #else
@ -323,7 +313,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} }
} // end if audio_in_stream } // end if audio_in_stream
video_first_pts = 0; video_first_pts = 0;
video_first_dts = 0; video_first_dts = 0;
video_last_pts = 0; video_last_pts = 0;
@ -340,19 +329,15 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
bool VideoStore::open() { bool VideoStore::open() {
/* open the out file, if needed */ /* open the out file, if needed */
if (!(out_format->flags & AVFMT_NOFILE)) { if ( !(out_format->flags & AVFMT_NOFILE) ) {
ret = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL); ret = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL);
if (ret < 0) { if ( ret < 0 ) {
Error("Could not open out file '%s': %s\n", filename, Error("Could not open out file '%s': %s", filename,
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
return false; return false;
} }
} }
// os->ctx_inited = 1;
// avio_flush(ctx->pb);
// av_dict_free(&opts);
zm_dump_stream_format(oc, 0, 0, 1); zm_dump_stream_format(oc, 0, 0, 1);
if (audio_out_stream) zm_dump_stream_format(oc, 1, 0, 1); if (audio_out_stream) zm_dump_stream_format(oc, 1, 0, 1);
@ -361,17 +346,17 @@ bool VideoStore::open() {
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); // av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
// av_dict_set(&opts, "movflags", // av_dict_set(&opts, "movflags",
// "frag_keyframe+empty_moov+default_base_moof", 0); // "frag_keyframe+empty_moov+default_base_moof", 0);
if ((ret = avformat_write_header(oc, &opts)) < 0) { if ( (ret = avformat_write_header(oc, &opts)) < 0 ) {
// if ((ret = avformat_write_header(oc, &opts)) < 0) { // if ((ret = avformat_write_header(oc, &opts)) < 0) {
Warning("Unable to set movflags to frag_custom+dash+delay_moov"); Warning("Unable to set movflags to frag_custom+dash+delay_moov");
/* Write the stream header, if any. */ /* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL); ret = avformat_write_header(oc, NULL);
} else if (av_dict_count(opts) != 0) { } else if (av_dict_count(opts) != 0) {
Warning("some options not set\n"); Warning("some options not set");
} }
if (opts) av_dict_free(&opts); if ( opts ) av_dict_free(&opts);
if (ret < 0) { if ( ret < 0 ) {
Error("Error occurred when writing out file header to %s: %s\n", Error("Error occurred when writing out file header to %s: %s",
filename, av_make_error_string(ret).c_str()); filename, av_make_error_string(ret).c_str());
/* free the stream */ /* free the stream */
avio_closep(&oc->pb); avio_closep(&oc->pb);
@ -419,7 +404,7 @@ VideoStore::~VideoStore() {
ret = ret =
avcodec_encode_audio2(audio_out_ctx, &pkt, NULL, &got_packet); avcodec_encode_audio2(audio_out_ctx, &pkt, NULL, &got_packet);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("ERror encoding audio while flushing (%d) (%s)", ret, Error("Error encoding audio while flushing (%d) (%s)", ret,
av_err2str(ret)); av_err2str(ret));
break; break;
} }
@ -470,6 +455,7 @@ VideoStore::~VideoStore() {
Debug(3, "Not closing avio because we are not writing to a file."); Debug(3, "Not closing avio because we are not writing to a file.");
} }
} // end if ( oc->pb ) } // end if ( oc->pb )
// I wonder if we should be closing the file first. // I wonder if we should be closing the file first.
// I also wonder if we really need to be doing all the ctx // I also wonder if we really need to be doing all the ctx
// allocation/de-allocation constantly, or whether we can just re-use it. // allocation/de-allocation constantly, or whether we can just re-use it.
@ -488,17 +474,19 @@ VideoStore::~VideoStore() {
#endif #endif
video_out_ctx = NULL; video_out_ctx = NULL;
Debug(4, "Success freeing video_out_ctx"); Debug(4, "Success freeing video_out_ctx");
} } // end if video_out_stream
if ( audio_out_stream ) { if ( audio_out_stream ) {
if ( audio_in_codec ) { if ( audio_in_codec ) {
avcodec_close(audio_in_ctx); avcodec_close(audio_in_ctx);
audio_in_codec = NULL;
} // end if audio_in_codec
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it // We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&audio_in_ctx); avcodec_free_context(&audio_in_ctx);
#endif #endif
audio_in_ctx = NULL; audio_in_ctx = NULL;
audio_in_codec = NULL;
} // end if audio_in_codec
avcodec_close(audio_out_ctx); avcodec_close(audio_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -523,7 +511,7 @@ VideoStore::~VideoStore() {
converted_in_samples = NULL; converted_in_samples = NULL;
} }
#endif #endif
} } // end if audio_out_stream
/* free the stream */ /* free the stream */
avformat_free_context(oc); avformat_free_context(oc);
@ -542,31 +530,27 @@ bool VideoStore::setup_resampler() {
avcodec_find_decoder(audio_in_ctx->codec_id); avcodec_find_decoder(audio_in_ctx->codec_id);
#endif #endif
ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL); ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL);
if (ret < 0) { if ( ret < 0 ) {
Error("Can't open in codec!"); Error("Can't open in codec!");
return false; return false;
} }
audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC); audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!audio_out_codec) { if ( !audio_out_codec ) {
Error("Could not find codec for AAC"); Error("Could not find codec for AAC");
return false; return false;
} }
Debug(2, "Have audio out codec");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// audio_out_ctx = audio_out_stream->codec; // audio_out_ctx = audio_out_stream->codec;
audio_out_ctx = avcodec_alloc_context3(audio_out_codec); audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
if ( !audio_out_ctx ) { if ( !audio_out_ctx ) {
Error("could not allocate codec ctx for AAC"); Error("could not allocate codec ctx for AAC");
audio_out_stream = NULL; audio_out_stream = NULL;
return false; return false;
} }
Debug(2, "Have audio_out_ctx"); audio_out_stream = avformat_new_stream(oc, audio_out_codec);
// Now copy them to the out stream
audio_out_stream = avformat_new_stream(oc, NULL);
#else #else
audio_out_stream = avformat_new_stream(oc, NULL); audio_out_stream = avformat_new_stream(oc, NULL);
audio_out_ctx = audio_out_stream->codec; audio_out_ctx = audio_out_stream->codec;
@ -582,7 +566,7 @@ bool VideoStore::setup_resampler() {
#else #else
audio_out_ctx->refcounted_frames = 1; audio_out_ctx->refcounted_frames = 1;
#endif #endif
if ( ! audio_out_ctx->channel_layout ) { if ( !audio_out_ctx->channel_layout ) {
Debug(3, "Correcting channel layout from (%d) to (%d)", Debug(3, "Correcting channel layout from (%d) to (%d)",
audio_out_ctx->channel_layout, audio_out_ctx->channel_layout,
av_get_default_channel_layout(audio_out_ctx->channels) av_get_default_channel_layout(audio_out_ctx->channels)
@ -590,28 +574,27 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels); audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels);
} }
if (audio_out_codec->supported_samplerates) { if ( audio_out_codec->supported_samplerates ) {
int found = 0; int found = 0;
for (unsigned int i = 0; audio_out_codec->supported_samplerates[i]; for ( unsigned int i = 0; audio_out_codec->supported_samplerates[i]; i++) {
i++) { if ( audio_out_ctx->sample_rate ==
if (audio_out_ctx->sample_rate == audio_out_codec->supported_samplerates[i] ) {
audio_out_codec->supported_samplerates[i]) {
found = 1; found = 1;
break; break;
} }
} }
if (found) { if ( found ) {
Debug(3, "Sample rate is good"); Debug(3, "Sample rate is good");
} else { } else {
audio_out_ctx->sample_rate = audio_out_ctx->sample_rate =
audio_out_codec->supported_samplerates[0]; audio_out_codec->supported_samplerates[0];
Debug(1, "Sampel rate is no good, setting to (%d)", Debug(1, "Sample rate is no good, setting to (%d)",
audio_out_codec->supported_samplerates[0]); audio_out_codec->supported_samplerates[0]);
} }
} }
/* check that the encoder supports s16 pcm in */ /* check that the encoder supports s16 pcm in */
if (!check_sample_fmt(audio_out_codec, audio_out_ctx->sample_fmt)) { if ( !check_sample_fmt(audio_out_codec, audio_out_ctx->sample_fmt) ) {
Debug(3, "Encoder does not support sample format %s, setting to FLTP", Debug(3, "Encoder does not support sample format %s, setting to FLTP",
av_get_sample_fmt_name(audio_out_ctx->sample_fmt)); av_get_sample_fmt_name(audio_out_ctx->sample_fmt));
audio_out_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; audio_out_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
@ -620,16 +603,6 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->time_base = audio_out_ctx->time_base =
(AVRational){1, audio_out_ctx->sample_rate}; (AVRational){1, audio_out_ctx->sample_rate};
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_parameters_from_context(audio_out_stream->codecpar,
audio_out_ctx);
if (ret < 0) {
Error("Could not initialize stream parameteres");
return false;
}
#endif
AVDictionary *opts = NULL; AVDictionary *opts = NULL;
if ( (ret = av_dict_set(&opts, "strict", "experimental", 0)) < 0 ) { if ( (ret = av_dict_set(&opts, "strict", "experimental", 0)) < 0 ) {
Error("Couldn't set experimental"); Error("Couldn't set experimental");
@ -637,13 +610,23 @@ bool VideoStore::setup_resampler() {
ret = avcodec_open2(audio_out_ctx, audio_out_codec, &opts); ret = avcodec_open2(audio_out_ctx, audio_out_codec, &opts);
av_dict_free(&opts); av_dict_free(&opts);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("could not open codec (%d) (%s)\n", ret, av_make_error_string(ret).c_str()); Error("could not open codec (%d) (%s)",
ret, av_make_error_string(ret).c_str());
audio_out_codec = NULL; audio_out_codec = NULL;
audio_out_ctx = NULL; audio_out_ctx = NULL;
audio_out_stream = NULL; audio_out_stream = NULL;
return false; return false;
} }
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_parameters_from_context(
audio_out_stream->codecpar, audio_out_ctx);
if ( ret < 0 ) {
Error("Could not initialize stream parameteres");
return false;
}
#endif
Debug(1, Debug(1,
"Audio out bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) " "Audio out bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) "
"layout(%d) frame_size(%d)", "layout(%d) frame_size(%d)",
@ -652,13 +635,13 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->channel_layout, audio_out_ctx->frame_size); audio_out_ctx->channel_layout, audio_out_ctx->frame_size);
/** Create a new frame to store the audio samples. */ /** Create a new frame to store the audio samples. */
if (!(in_frame = zm_av_frame_alloc())) { if ( !(in_frame = zm_av_frame_alloc()) ) {
Error("Could not allocate in frame"); Error("Could not allocate in frame");
return false; return false;
} }
/** Create a new frame to store the audio samples. */ /** Create a new frame to store the audio samples. */
if (!(out_frame = zm_av_frame_alloc())) { if ( !(out_frame = zm_av_frame_alloc()) ) {
Error("Could not allocate out frame"); Error("Could not allocate out frame");
av_frame_free(&in_frame); av_frame_free(&in_frame);
return false; return false;
@ -666,20 +649,20 @@ bool VideoStore::setup_resampler() {
// Setup the audio resampler // Setup the audio resampler
resample_ctx = avresample_alloc_context(); resample_ctx = avresample_alloc_context();
if (!resample_ctx) { if ( !resample_ctx ) {
Error("Could not allocate resample ctx\n"); Error("Could not allocate resample ctx");
return false; return false;
} }
// Some formats (i.e. WAV) do not produce the proper channel layout // Some formats (i.e. WAV) do not produce the proper channel layout
if (audio_in_ctx->channel_layout == 0) {
uint64_t layout = av_get_channel_layout("mono"); uint64_t layout = av_get_channel_layout("mono");
av_opt_set_int(resample_ctx, "in_channel_layout", if ( audio_in_ctx->channel_layout == 0 ) {
av_get_channel_layout("mono"), 0); av_opt_set_int(resample_ctx, "in_channel_layout", layout, 0);
Debug(1, "Bad channel layout. Need to set it to mono (%d).", layout); Debug(1, "Bad in channel layout. Need to set it to mono (%d).", layout);
} else { } else {
av_opt_set_int(resample_ctx, "in_channel_layout", av_opt_set_int(resample_ctx, "in_channel_layout",
audio_in_ctx->channel_layout, 0); audio_in_ctx->channel_layout, 0);
layout = audio_in_ctx->channel_layout;
} }
av_opt_set_int(resample_ctx, "in_sample_fmt", av_opt_set_int(resample_ctx, "in_sample_fmt",
@ -691,7 +674,7 @@ bool VideoStore::setup_resampler() {
// av_opt_set_int( resample_ctx, "out_channel_layout", // av_opt_set_int( resample_ctx, "out_channel_layout",
// audio_out_ctx->channel_layout, 0); // audio_out_ctx->channel_layout, 0);
av_opt_set_int(resample_ctx, "out_channel_layout", av_opt_set_int(resample_ctx, "out_channel_layout",
av_get_channel_layout("mono"), 0); layout, 0);
av_opt_set_int(resample_ctx, "out_sample_fmt", av_opt_set_int(resample_ctx, "out_sample_fmt",
audio_out_ctx->sample_fmt, 0); audio_out_ctx->sample_fmt, 0);
av_opt_set_int(resample_ctx, "out_sample_rate", av_opt_set_int(resample_ctx, "out_sample_rate",
@ -700,38 +683,13 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->channels, 0); audio_out_ctx->channels, 0);
ret = avresample_open(resample_ctx); ret = avresample_open(resample_ctx);
if (ret < 0) { if ( ret < 0 ) {
Error("Could not open resample ctx\n"); Error("Could not open resample ctx");
return false; return false;
} else {
Debug(2, "Success opening resampler");
} }
#if 0
/**
* Allocate as many pointers as there are audio channels.
* Each pointer will later point to the audio samples of the corresponding
* channels (although it may be NULL for interleaved formats).
*/
if (!( converted_in_samples = reinterpret_cast<uint8_t *>calloc( audio_out_ctx->channels, sizeof(*converted_in_samples))) ) {
Error("Could not allocate converted in sample pointers\n");
return;
}
/**
* Allocate memory for the samples of all channels in one consecutive
* block for convenience.
*/
if ( (ret = av_samples_alloc( &converted_in_samples, NULL,
audio_out_ctx->channels,
audio_out_ctx->frame_size,
audio_out_ctx->sample_fmt, 0)) < 0 ) {
Error("Could not allocate converted in samples (error '%s')\n",
av_make_error_string(ret).c_str());
av_freep(converted_in_samples);
free(converted_in_samples);
return;
}
#endif
out_frame->nb_samples = audio_out_ctx->frame_size; out_frame->nb_samples = audio_out_ctx->frame_size;
out_frame->format = audio_out_ctx->sample_fmt; out_frame->format = audio_out_ctx->sample_fmt;
out_frame->channel_layout = audio_out_ctx->channel_layout; out_frame->channel_layout = audio_out_ctx->channel_layout;
@ -739,21 +697,24 @@ bool VideoStore::setup_resampler() {
// The codec gives us the frame size, in samples, we calculate the size of the // The codec gives us the frame size, in samples, we calculate the size of the
// samples buffer in bytes // samples buffer in bytes
unsigned int audioSampleBuffer_size = av_samples_get_buffer_size( unsigned int audioSampleBuffer_size = av_samples_get_buffer_size(
NULL, audio_out_ctx->channels, audio_out_ctx->frame_size, NULL, audio_out_ctx->channels,
audio_out_ctx->frame_size,
audio_out_ctx->sample_fmt, 0); audio_out_ctx->sample_fmt, 0);
converted_in_samples = (uint8_t *)av_malloc(audioSampleBuffer_size); converted_in_samples = (uint8_t *)av_malloc(audioSampleBuffer_size);
if (!converted_in_samples) { if ( !converted_in_samples ) {
Error("Could not allocate converted in sample pointers\n"); Error("Could not allocate converted in sample pointers");
return false; return false;
} else {
Debug(2, "Frame Size %d, sample buffer size %d", audio_out_ctx->frame_size, audioSampleBuffer_size);
} }
// Setup the data pointers in the AVFrame // Setup the data pointers in the AVFrame
if (avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels, if ( avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels,
audio_out_ctx->sample_fmt, audio_out_ctx->sample_fmt,
(const uint8_t *)converted_in_samples, (const uint8_t *)converted_in_samples,
audioSampleBuffer_size, 0) < 0) { audioSampleBuffer_size, 0) < 0) {
Error("Could not allocate converted in sample pointers\n"); Error("Could not allocate converted in sample pointers");
return false; return false;
} }
@ -788,8 +749,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
video_out_stream->time_base.den video_out_stream->time_base.den
); );
} else { } else {
duration = duration = av_rescale_q(
av_rescale_q(
ipkt->pts - video_last_pts, ipkt->pts - video_last_pts,
video_in_stream->time_base, video_in_stream->time_base,
video_out_stream->time_base); video_out_stream->time_base);
@ -800,27 +760,24 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
duration duration
); );
if ( duration <= 0 ) { if ( duration <= 0 ) {
duration = ipkt->duration ? ipkt->duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base); // Why are we setting the duration to 1?
duration = av_rescale_q(1, video_in_stream->time_base, video_out_stream->time_base);
} }
} }
opkt.duration = duration; opkt.duration = duration;
//Scale the PTS of the outgoing packet to be the correct time base // Scale the PTS of the outgoing packet to be the correct time base
if ( ipkt->pts != AV_NOPTS_VALUE ) { if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( !video_first_pts ) { // ffmpeg has a bug where it screws up the pts to massively negative.
if ( (!video_first_pts) && (ipkt->pts >= 0) ) {
// This is the first packet. // This is the first packet.
opkt.pts = 0; opkt.pts = 0;
Debug(2, "Starting video first_pts will become %" PRId64, ipkt->pts); Debug(2, "Starting video first_pts will become %" PRId64, ipkt->pts);
video_first_pts = ipkt->pts; video_first_pts = ipkt->pts;
} else { } else {
if ( 0 && ipkt->pts < video_first_pts ) {
Debug(1, "Resetting first_pts from %" PRId64 " to %" PRId64, video_last_pts, ipkt->pts);
video_first_pts -= video_last_pts;
// wrap around, need to figure out the distance FIXME having this wrong should cause a jump, but then play ok?
}
opkt.pts = av_rescale_q( opkt.pts = av_rescale_q(
ipkt->pts-video_first_pts, ipkt->pts - video_first_pts,
video_in_stream->time_base, video_in_stream->time_base,
video_out_stream->time_base video_out_stream->time_base
); );
@ -833,19 +790,14 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
} }
// Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap. // Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
if ( ipkt->dts != AV_NOPTS_VALUE ) { if ( ipkt->dts != AV_NOPTS_VALUE ) {
if ( !video_first_dts ) { if ( (!video_first_dts) && ( ipkt->dts >= 0 ) ) {
// This is the first packet. // This is the first packet.
opkt.dts = 0; opkt.dts = 0;
Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts); Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
video_first_dts = ipkt->dts; video_first_dts = ipkt->dts;
} else { } else {
if ( 0 && ipkt->dts < video_first_dts ) {
Debug(1, "Resetting first_dts from (%" PRId64 ") to (%" PRId64")",
video_first_dts, ipkt->dts);
video_first_dts -= video_last_dts;
}
opkt.dts = av_rescale_q( opkt.dts = av_rescale_q(
ipkt->dts-video_first_dts, ipkt->dts - video_first_dts,
video_in_stream->time_base, video_in_stream->time_base,
video_out_stream->time_base video_out_stream->time_base
); );
@ -858,7 +810,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.dts = AV_NOPTS_VALUE; opkt.dts = AV_NOPTS_VALUE;
} }
if (opkt.dts > opkt.pts) { if ( opkt.dts > opkt.pts ) {
Debug(1, Debug(1,
"opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 "). Decompression must happen " "opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 "). Decompression must happen "
"before presentation.", "before presentation.",
@ -868,34 +820,22 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.flags = ipkt->flags; opkt.flags = ipkt->flags;
opkt.pos = -1; opkt.pos = -1;
opkt.data = ipkt->data; opkt.data = ipkt->data;
opkt.size = ipkt->size; opkt.size = ipkt->size;
opkt.stream_index = video_out_stream->index; opkt.stream_index = video_out_stream->index;
dumpPacket(video_out_stream, &opkt, "writing video packet"); dumpPacket(video_out_stream, &opkt, "writing video packet");
if ((opkt.data == NULL) || (opkt.size < 1)) { if ( (opkt.data == NULL) || (opkt.size < 1) ) {
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__); Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__);
dumpPacket(video_in_stream, ipkt,"In Packet"); dumpPacket(video_in_stream, ipkt,"In Packet");
dumpPacket(video_out_stream, &opkt); dumpPacket(video_out_stream, &opkt);
#if 0
} else if ((video_next_dts > 0) && (video_next_dts > opkt.dts)) {
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame",
__FILE__, __LINE__, video_next_dts, opkt.dts);
video_next_dts = opkt.dts;
dumpPacket(&opkt);
#endif
} else { } else {
ret = av_interleaved_write_frame(oc, &opkt); ret = av_interleaved_write_frame(oc, &opkt);
if (ret < 0) { if ( ret < 0 ) {
// There's nothing we can really do if the frame is rejected, just drop it // There's nothing we can really do if the frame is rejected, just drop it
// and get on with the next // and get on with the next
Warning( Warning(
"%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d) " "%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d)",
" ",
__FILE__, __LINE__, av_make_error_string(ret).c_str(), ret); __FILE__, __LINE__, av_make_error_string(ret).c_str(), ret);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
zm_dump_codecpar(video_in_stream->codecpar); zm_dump_codecpar(video_in_stream->codecpar);
@ -910,7 +850,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) } // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
Debug(4, "writeAudioFrame");
if ( !audio_out_stream ) { if ( !audio_out_stream ) {
Debug(1, "Called writeAudioFramePacket when no audio_out_stream"); Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
@ -947,45 +886,44 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
* to flush it. * to flush it.
*/ */
int data_present; int data_present;
if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame, if ( (ret = avcodec_decode_audio4(audio_in_ctx, in_frame,
&data_present, ipkt)) < 0) { &data_present, ipkt)) < 0 ) {
Error("Could not decode frame (error '%s')\n", Error("Could not decode frame (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
dumpPacket(video_in_stream, ipkt); dumpPacket(video_in_stream, ipkt);
// I'm not sure if we should be freeing the frame.
av_frame_free(&in_frame); av_frame_free(&in_frame);
return 0; return 0;
} }
if (!data_present) { if ( !data_present ) {
Debug(2, "Not ready to transcode a frame yet."); Debug(2, "Not ready to transcode a frame yet.");
return 0; return 0;
} }
#endif #endif
int frame_size = out_frame->nb_samples; int frame_size = out_frame->nb_samples;
// Resample the in into the audioSampleBuffer until we proceed the whole // Resample the in into the audioSampleBuffer until we process the whole
// decoded data // decoded data
if ((ret = ret = avresample_convert(resample_ctx, NULL, 0, 0,
avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, in_frame->data, 0, in_frame->nb_samples);
0, in_frame->nb_samples)) < 0) {
Error("Could not resample frame (error '%s')\n",
av_make_error_string(ret).c_str());
av_frame_unref(in_frame); av_frame_unref(in_frame);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0; return 0;
} }
av_frame_unref(in_frame);
int samples_available = avresample_available(resample_ctx); int samples_available = avresample_available(resample_ctx);
if ( samples_available < frame_size ) {
if (samples_available < frame_size) {
Debug(1, "Not enough samples yet (%d)", samples_available); Debug(1, "Not enough samples yet (%d)", samples_available);
return 0; return 0;
} }
Debug(3, "Output_frame samples (%d)", out_frame->nb_samples); Debug(3, "Output_frame samples (%d)", out_frame->nb_samples);
// Read a frame audio data from the resample fifo // Read a frame audio data from the resample fifo
if (avresample_read(resample_ctx, out_frame->data, frame_size) != if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
frame_size) { frame_size) {
Warning("Error reading resampled audio: "); Warning("Error reading resampled audio.");
return 0; return 0;
} }
Debug(2, Debug(2,
@ -997,18 +935,16 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
Debug(5, "after init packet"); Debug(5, "after init packet");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ((ret = avcodec_send_frame(audio_out_ctx, out_frame)) < 0) { if ( (ret = avcodec_send_frame(audio_out_ctx, out_frame)) < 0 ) {
Error("Could not send frame (error '%s')", Error("Could not send frame (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
return 0; return 0;
} }
// av_frame_unref( out_frame ); if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) {
if ((ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0) { // The codec may need more samples than it has, perfectly valid
if (AVERROR(EAGAIN) == ret) {
// THe codec may need more samples than it has, perfectly valid
Debug(3, "Could not recieve packet (error '%s')", Debug(3, "Could not recieve packet (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} else { } else {
@ -1016,19 +952,18 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} }
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
av_frame_unref(in_frame);
// av_frame_unref( out_frame ); // av_frame_unref( out_frame );
return 0; return 0;
} }
#else #else
if ((ret = avcodec_encode_audio2(audio_out_ctx, &opkt, out_frame, if ( (ret = avcodec_encode_audio2(
&data_present)) < 0) { audio_out_ctx, &opkt, out_frame, &data_present)) < 0 ) {
Error("Could not encode frame (error '%s')", Error("Could not encode frame (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
return 0; return 0;
} }
if (!data_present) { if ( !data_present ) {
Debug(2, "Not ready to out a frame yet."); Debug(2, "Not ready to out a frame yet.");
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
return 0; return 0;
@ -1043,25 +978,36 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.size = ipkt->size; opkt.size = ipkt->size;
} }
if ( out_frame ) {
opkt.duration = out_frame->nb_samples;
} else if ( ipkt->duration != AV_NOPTS_VALUE ) {
opkt.duration = av_rescale_q(
ipkt->duration,
audio_in_stream->time_base,
audio_out_stream->time_base);
} else {
// calculate it?
}
dumpPacket(audio_out_stream, &opkt);
// PTS is difficult, because of the buffering of the audio packets in the // PTS is difficult, because of the buffering of the audio packets in the
// resampler. So we have to do it once we actually have a packet... // resampler. So we have to do it once we actually have a packet...
// audio_last_pts is the pts of ipkt, audio_next_pts is the last pts of the // audio_last_pts is the pts of ipkt, audio_next_pts is the last pts of the
// out // out
// Scale the PTS of the outgoing packet to be the correct time base // Scale the PTS of the outgoing packet to be the correct time base
#if 0 #if 1
if ( ipkt->pts != AV_NOPTS_VALUE ) { if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( !audio_last_pts ) { if ( !audio_first_pts ) {
opkt.pts = 0; opkt.pts = 0;
Debug(1, "No audio_last_pts"); audio_first_pts = ipkt->pts;
Debug(1, "No audio_first_pts");
} else { } else {
if ( audio_last_pts > ipkt->pts ) { opkt.pts = av_rescale_q(
Debug(1, "Resetting audio_start_pts from (%d) to (%d)", audio_last_pts, ipkt->pts); ipkt->pts - audio_first_pts,
opkt.pts = audio_next_pts + av_rescale_q(ipkt->pts, audio_in_stream->time_base, audio_out_stream->time_base); audio_in_stream->time_base,
} else { audio_out_stream->time_base);
opkt.pts = audio_next_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_in_stream->time_base, audio_out_stream->time_base); Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - first_pts(%d)",
} opkt.pts, ipkt->pts, audio_first_pts);
Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts);
} }
audio_last_pts = ipkt->pts; audio_last_pts = ipkt->pts;
} else { } else {
@ -1073,59 +1019,52 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.dts = audio_next_dts; opkt.dts = audio_next_dts;
#endif #endif
#if 0 #if 1
if ( ipkt->dts == AV_NOPTS_VALUE ) { if ( ipkt->dts != AV_NOPTS_VALUE ) {
// So if the in has no dts assigned... still need an out dts... so we use cur_dts? // So if the in has no dts assigned... still need an out dts... so we use cur_dts?
#if 0
if ( audio_last_dts >= audio_in_stream->cur_dts ) { if ( audio_last_dts >= audio_in_stream->cur_dts ) {
Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_in_stream->cur_dts); Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_in_stream->cur_dts);
opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts, AV_TIME_BASE_Q, audio_out_stream->time_base); opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts, AV_TIME_BASE_Q, audio_out_stream->time_base);
} else { } else {
opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_out_stream->time_base); opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_out_stream->time_base);
} }
audio_last_dts = audio_in_stream->cur_dts; #endif
Debug(2, "opkt.dts = %d from video_in_stream->cur_dts(%d) - last_dts(%d)", opkt.dts, audio_in_stream->cur_dts, audio_last_dts); if ( !audio_first_dts ) {
opkt.dts = 0;
audio_first_dts = ipkt->dts;
} else { } else {
if ( audio_last_dts >= ipkt->dts ) { opkt.dts = av_rescale_q(
Debug(1, "Resetting audio_last_dts from (%d) to (%d)", audio_last_dts, ipkt->dts ); ipkt->dts - audio_first_dts,
opkt.dts = audio_next_dts + av_rescale_q(ipkt->dts, audio_in_stream->time_base, audio_out_stream->time_base); audio_in_stream->time_base,
audio_out_stream->time_base);
Debug(2, "opkt.dts = %" PRId64 " from ipkt.dts(%" PRId64 ") - first_dts(%" PRId64 ")",
opkt.dts, ipkt->dts, audio_first_dts);
}
audio_last_dts = ipkt->dts;
} else { } else {
opkt.dts = audio_next_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_in_stream->time_base, audio_out_stream->time_base); opkt.dts = AV_NOPTS_VALUE;
Debug(2, "opkt.dts = %d from previous(%d) + ( ipkt->dts(%d) - last_dts(%d) )", opkt.dts, audio_next_dts, ipkt->dts, audio_last_dts );
}
}
} }
#endif #endif
// audio_last_dts = ipkt->dts; // audio_last_dts = ipkt->dts;
if (opkt.dts > opkt.pts) { if ( opkt.dts > opkt.pts ) {
Debug(1, Debug(1,
"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen " "opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 ")."
"before presentation.", "Decompression must happen before presentation.",
opkt.dts, opkt.pts); opkt.dts, opkt.pts);
opkt.dts = opkt.pts; opkt.dts = opkt.pts;
} }
// I wonder if we could just use duration instead of all the hoop jumping
// above?
//
if (out_frame) {
opkt.duration = out_frame->nb_samples;
} else {
opkt.duration = ipkt->duration;
}
// opkt.duration = av_rescale_q(ipkt->duration, audio_in_stream->time_base,
// audio_out_stream->time_base);
dumpPacket( audio_out_stream, &opkt );
// pkt.pos: byte position in stream, -1 if unknown // pkt.pos: byte position in stream, -1 if unknown
opkt.pos = -1; opkt.pos = -1;
opkt.stream_index = audio_out_stream->index; opkt.stream_index = audio_out_stream->index;
audio_next_dts = opkt.dts + opkt.duration; //audio_next_dts = opkt.dts + opkt.duration;
audio_next_pts = opkt.pts + opkt.duration; //audio_next_pts = opkt.pts + opkt.duration;
ret = av_interleaved_write_frame(oc, &opkt); ret = av_interleaved_write_frame(oc, &opkt);
if (ret != 0) { if ( ret != 0 ) {
Error("Error writing audio frame packet: %s\n", Error("Error writing audio frame packet: %s",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} else { } else {
Debug(2, "Success writing audio frame"); Debug(2, "Success writing audio frame");

View File

@ -51,7 +51,8 @@ class Server {
} else if ( $this->Id() ) { } else if ( $this->Id() ) {
return $this->{'Name'}; return $this->{'Name'};
} }
return $_SERVER['SERVER_NAME']; # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity
return $_SERVER['HTTP_HOST'];
} }
public function Protocol( $new = null ) { public function Protocol( $new = null ) {
@ -93,7 +94,8 @@ class Server {
if ( $this->Id() ) { if ( $this->Id() ) {
$url .= $this->Hostname(); $url .= $this->Hostname();
} else { } else {
$url .= $_SERVER['SERVER_NAME']; # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity
$url .= $_SERVER['HTTP_HOST'];
} }
if ( $port ) { if ( $port ) {
$url .= ':'.$port; $url .= ':'.$port;

View File

@ -617,7 +617,7 @@ if ( canEdit('Monitors') ) {
$new_monitor = new Monitor($mid); $new_monitor = new Monitor($mid);
//fixDevices(); //fixDevices();
if ( $monitor['Type'] != 'WebSite' ) { if ( $new_monitor->Type() != 'WebSite' ) {
$new_monitor->zmcControl('start'); $new_monitor->zmcControl('start');
$new_monitor->zmaControl('start'); $new_monitor->zmaControl('start');
} }