Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Add support for the embedded PGS (Presentation Graphic Stream) subtit…

…le format, fix segfault on some HEVC files

Note on compilation:
    - add files output/graphic_subtitle.c, external/plugins/src/png.c to the compilation sources
    - add -lswscale -ldl to the linker
  • Loading branch information...
e2iplayer committed Apr 29, 2019
1 parent acda344 commit 0f7646823aee18e338ad75c1bd856eb2efad393b
@@ -481,7 +481,6 @@ static char* Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extra
case AV_CODEC_ID_DVB_SUBTITLE:
case AV_CODEC_ID_XSUB:
case AV_CODEC_ID_MOV_TEXT:
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
case AV_CODEC_ID_DVB_TELETEXT:
// case CODEC_ID_DVB_TELETEXT:
// return "S_TEXT/SRT"; /* fixme */
@@ -492,7 +491,9 @@ static char* Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extra
case AV_CODEC_ID_SUBRIP:
return "S_TEXT/SUBRIP";
case AV_CODEC_ID_WEBVTT:
return "D_WEBVTT/SUBTITLES";
return "S_TEXT/WEBVTT";
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
return "S_GRAPHIC/PGS";
default:
ffmpeg_err("Codec ID %d (%.8x) not found\n", codec_id, codec_id);
// Default to injected-pcm for unhandled audio types.
@@ -1279,12 +1280,13 @@ static void FFMPEGThread(Context_t *context)
duration = (int64_t)av_rescale(get_packet_duration(&packet), (int64_t)stream->time_base.num * 1000, stream->time_base.den);
}

if (duration > 0)
if (duration > 0 || duration == -1)
{
SubtitleOut_t subOut;
memset(&subOut, 0, sizeof(subOut));
subOut.trackId = pid;
subOut.data = (uint8_t *)packet.data;
subOut.len = packet.size;
subOut.pts = pts;
subOut.durationMS = duration;
if (Write(context->output->subtitle->Write, context, &subOut, pts) < 0)
@@ -1834,7 +1836,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uin

ffmpeg_err("avformat_open_input failed %d (%s)\n", err, filename);
av_strerror(err, error, 512);
fprintf(stderr, "{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err);
E2iSendMsg("{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err);

if(avio_opts != NULL)
{
@@ -2520,7 +2522,8 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
get_codecpar(stream)->codec_id != AV_CODEC_ID_SUBRIP &&
get_codecpar(stream)->codec_id != AV_CODEC_ID_TEXT &&
get_codecpar(stream)->codec_id != AV_CODEC_ID_SRT &&
get_codecpar(stream)->codec_id != AV_CODEC_ID_WEBVTT)
get_codecpar(stream)->codec_id != AV_CODEC_ID_WEBVTT &&
(get_codecpar(stream)->codec_id != AV_CODEC_ID_HDMV_PGS_SUBTITLE || !GetGraphicSubPath() || !GetGraphicSubPath()[0]))
{
ffmpeg_printf(10, "subtitle with not supported codec codec_id[%u]\n", (uint32_t)get_codecpar(stream)->codec_id);
}
@@ -142,13 +142,13 @@ static AVCodecContext *wrapped_avcodec_get_context(uint32_t cAVIdx, AVStream *st
avCodecCtx = avcodec_alloc_context3(NULL);
if (!avCodecCtx)
{
fprintf(stderr, "context3 alloc for stream %d failed\n", (int)stream->id);
ffmpeg_err("context3 alloc for stream %d failed\n", (int)stream->id);
return NULL;
}

if (avcodec_parameters_to_context(avCodecCtx, stream->codecpar) < 0)
{
fprintf(stderr, "parameters to context for stream %d failed\n", (int)stream->id);
ffmpeg_err("parameters to context for stream %d failed\n", (int)stream->id);
avcodec_free_context(&avCodecCtx);
return NULL;
}
@@ -33,6 +33,7 @@
{'name':'wmv', 'lvl':0, 'silent':True},
{'name':'mjpeg', 'lvl':0, 'silent':True},
{'name':'bcma', 'lvl':0, 'silent':True},
{'name':'plugin', 'lvl':0, 'silent':True},
]

lines = ['#include <stdio.h>']
@@ -120,7 +120,6 @@ static void __inline flash_bw(BW* p)
p->buf[p->pos++] = (p->tmp >> 8 ) & 0xff;
break;
default:
// fprintf(stderr, "flash_bw error!(%d)\n", p->bitoffset);
break;
}

@@ -464,23 +464,18 @@ int decode_picture_header(BR* p, PICTURE* picture)

if (get_bits(p, 17) != 1)
{
fprintf(stderr, "start code error\n");
return -1;
}

tmp = get_bits(p, 5);
if (tmp !=0 && tmp != 1)
{
fprintf(stderr, "picture format error\n");
return -1;
}

picture->escape_type = tmp;
picture->frame_number = get_bits(p, 8);

// printf("picture_format: %d\n", tmp);
// printf("picture_number: %d\n", get_bits(p, 8));

tmp = get_bits(p, 3);
switch (tmp)
{
@@ -498,7 +493,6 @@ int decode_picture_header(BR* p, PICTURE* picture)
case 5: width = 320, height = 240; break;
case 6: width = 160, height = 120; break;
default:
fprintf(stderr, "size error\n");
return -1;
}

@@ -0,0 +1,8 @@
#ifndef _exteplayer3_external_plugins_png_
#define _exteplayer3_external_plugins_png_

int PNGPlugin_saveRGBAImage(const char *filename, const unsigned char *data, int width, int height);
int PNGPlugin_init(void);
int PNGPlugin_term(void);

#endif // _exteplayer3_external_plugins_png_
@@ -0,0 +1,76 @@
/*
* Subtitle output to one registered client.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/

/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <dlfcn.h>
#include "plugins/png.h"
#include "debug.h"

static void *handle;
int (*SaveRGBAImage_handle)(const char *filename, const unsigned char *data, int width, int height);


int PNGPlugin_saveRGBAImage(const char *filename, const unsigned char *data, int width, int height)
{
if (SaveRGBAImage_handle != NULL)
return SaveRGBAImage_handle(filename, data, width, height);
return -1;
}

int PNGPlugin_init(void)
{
if (NULL == handle)
{
handle = dlopen("exteplayer3png.so", RTLD_LAZY);
if (handle)
{
char *error = NULL;

dlerror(); /* Clear any existing error */

*(void **) (&SaveRGBAImage_handle) = dlsym(handle, "SaveRGBAImage");

if ((error = dlerror()) != NULL)
{
dlclose(handle);
plugin_err("%s\n", error);
return -2;
}
return 0;
}
plugin_err( "%s\n", dlerror());
}
return -1;
}

int PNGPlugin_term(void)
{
if (handle)
{
dlclose(handle);
handle = NULL;
SaveRGBAImage_handle = NULL;
return 0;
}
return -1;
}
@@ -30,4 +30,13 @@ typedef struct Context_s
} Context_t;

int container_ffmpeg_update_tracks(Context_t *context, char *filename, int initial);

const char* GetGraphicSubPath();
int32_t GetGraphicWindowWidth();
int32_t GetGraphicWindowHeight();

void E2iSendMsg(const char * format, ...);
void E2iStartMsg(void);
void E2iEndMsg(void);

#endif
@@ -559,4 +559,22 @@
#define bcma_err(...) log_error(__VA_ARGS__)
#else
#define bcma_err(...)
#endif

/*******************************************
* plugin
*******************************************/
#define PLUGIN_DEBUG_LEVEL 0
#define PLUGIN_SILENT

#if PLUGIN_DEBUG_LEVEL
#define plugin_printf(...) log_printf(PLUGIN_DEBUG_LEVEL, __VA_ARGS__)
#else
#define plugin_printf(...)
#endif

#ifndef PLUGIN_SILENT
#define plugin_err(...) log_error(__VA_ARGS__)
#else
#define plugin_err(...)
#endif
@@ -57,7 +57,10 @@ typedef struct
uint32_t trackId;
uint8_t *data;
uint32_t len;


uint8_t *extradata;
uint32_t extralen;

int64_t pts;
int64_t durationMS; // duration in miliseconds

@@ -26,8 +26,6 @@ typedef struct {
WriteV_t WriteV;
} WriterAVCallData_t;



typedef struct WriterCaps_s {
char* name;
eWriterType_t type;
@@ -98,4 +96,26 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx, co
void FlushPipe(int pipefd);

ssize_t WriteExt(WriteV_t _call, int fd, void *data, size_t size);

// Subtitles
typedef struct {
uint32_t trackId;
uint8_t *data;
uint32_t len;
int64_t pts;
int64_t dts;
uint8_t *private_data;
uint32_t private_size;
int64_t durationMS; // duration in miliseconds
} WriterSubCallData_t;

typedef struct SubWriter_s {
int32_t (* open) ();
int32_t (* close) ();
int32_t (* reset) ();
int32_t (* write) (WriterSubCallData_t *);
} SubWriter_t;

extern SubWriter_t WriterSubPGS;

#endif

0 comments on commit 0f76468

Please sign in to comment.
You can’t perform that action at this time.