Fix single-track HLS MPEG-TS streams

This commit is contained in:
Chris Wiggins 2016-04-13 17:17:21 +12:00
parent 6666d789b5
commit c11797815d
3 changed files with 68 additions and 20 deletions

View file

@ -1049,7 +1049,7 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts,
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (ngx_rtmp_mpegts_open_file(&ctx->file, ctx->stream.data,
s->connection->log, &codec_ctx->audio_codec_id, mpegts_cc)
s->connection->log, codec_ctx, mpegts_cc)
!= NGX_OK)
{
return NGX_ERROR;

View file

@ -173,27 +173,73 @@ ngx_rtmp_mpegts_write_file(ngx_rtmp_mpegts_file_t *file, u_char *in,
static ngx_int_t
ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file, ngx_uint_t *audio_codec_id, ngx_uint_t mpegts_cc)
ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file, ngx_rtmp_codec_ctx_t *codec_ctx, ngx_uint_t mpegts_cc)
{
ngx_int_t rc;
if (*audio_codec_id == NGX_RTMP_AUDIO_AAC) {
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_aac,
sizeof(ngx_rtmp_mpegts_header_aac));
//If there's both audio and video present
if (codec_ctx->audio_codec_id && codec_ctx->video_codec_id)
{
if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_aac,
sizeof(ngx_rtmp_mpegts_header_aac));
}
//if (*audio_codec_id == NGX_RTMP_AUDIO_MP3) {
else {
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_mp3,
sizeof(ngx_rtmp_mpegts_header_mp3));
}
// Truncate counter to 4 bits here
mpegts_cc %= 0x0f;
// And fill headers
ngx_rtmp_mpegts_header[3] = (ngx_rtmp_mpegts_header[3] & 0xf0) + (u_char)mpegts_cc;
ngx_rtmp_mpegts_header[191] = (ngx_rtmp_mpegts_header[191] & 0xf0) + (u_char)mpegts_cc;
rc = ngx_rtmp_mpegts_write_file(file, ngx_rtmp_mpegts_header,
sizeof(ngx_rtmp_mpegts_header));
}
//if (*audio_codec_id == NGX_RTMP_AUDIO_MP3) {
else {
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_mp3,
sizeof(ngx_rtmp_mpegts_header_mp3));
else
{
//Just video or just audio
u_char buf[sizeof(ngx_rtmp_mpegts_header)];
ngx_memcpy(buf, ngx_rtmp_mpegts_header, sizeof(ngx_rtmp_mpegts_header));
/* Fix the section length */
buf[195] = 0x12;
if (codec_ctx->audio_codec_id)
{
/* Set the PCR PID to the audio PID */
buf[202] = 0x01;
/* Move the audio description over the video description */
ngx_memcpy(buf + 205, buf + 210, 5);
/* Fix the CRC partially overwriting the audio description */
buf[210] = 0xec;
buf[211] = 0xe2;
buf[212] = 0xb0;
buf[213] = 0x94;
}
else
{
/* Fix the CRC partially overwriting the audio description */
buf[210] = 0x15;
buf[211] = 0xbd;
buf[212] = 0x4d;
buf[213] = 0x56;
}
/* Clear the last byte of the audio description and the old CRC */
ngx_memset(buf + 214, 0xff, 5);
rc = ngx_rtmp_mpegts_write_file(file, buf, sizeof(buf));
}
// Truncate counter to 4 bits here
mpegts_cc %= 0x0f;
// And fill headers
ngx_rtmp_mpegts_header[3] = (ngx_rtmp_mpegts_header[3] & 0xf0) + (u_char)mpegts_cc;
ngx_rtmp_mpegts_header[191] = (ngx_rtmp_mpegts_header[191] & 0xf0) + (u_char)mpegts_cc;
return ngx_rtmp_mpegts_write_file(file, ngx_rtmp_mpegts_header,
sizeof(ngx_rtmp_mpegts_header));
return rc;
}
@ -383,7 +429,7 @@ ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file,
ngx_int_t
ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
ngx_log_t *log, ngx_uint_t *audio_codec_id, ngx_uint_t mpegts_cc)
ngx_log_t *log, ngx_rtmp_codec_ctx_t *codec_ctx, ngx_uint_t mpegts_cc)
{
file->log = log;
@ -398,7 +444,7 @@ ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
file->size = 0;
if (ngx_rtmp_mpegts_write_header(file, audio_codec_id, mpegts_cc) != NGX_OK) {
if (ngx_rtmp_mpegts_write_header(file, codec_ctx, mpegts_cc) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
"hls: error writing fragment header");
ngx_close_file(file->fd);

View file

@ -12,6 +12,8 @@
#include <ngx_core.h>
#include <openssl/aes.h>
#include <ngx_rtmp_codec_module.h>
typedef struct {
ngx_fd_t fd;
@ -37,7 +39,7 @@ typedef struct {
ngx_int_t ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file,
u_char *key, size_t key_len, uint64_t iv);
ngx_int_t ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
ngx_log_t *log, ngx_uint_t *audio_codec_id, ngx_uint_t mpegts_cc);
ngx_log_t *log, ngx_rtmp_codec_ctx_t *codec_ctx, ngx_uint_t mpegts_cc);
ngx_int_t ngx_rtmp_mpegts_close_file(ngx_rtmp_mpegts_file_t *file);
ngx_int_t ngx_rtmp_mpegts_write_frame(ngx_rtmp_mpegts_file_t *file,
ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b);