New upstream version 18.0.1+dfsg1
This commit is contained in:
parent
6efda2859e
commit
f2cf6cce50
1337 changed files with 41178 additions and 84670 deletions
29
deps/libcaption/examples/add_captions.sh
vendored
Normal file
29
deps/libcaption/examples/add_captions.sh
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "Need at least 2 arguments."
|
||||
echo "$0 InputVideo InputSRT [OutputFilename]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VIDEO=$1
|
||||
SRT=$2
|
||||
|
||||
if [ -z "$3" ]
|
||||
then
|
||||
OUTFILE="out.flv"
|
||||
else
|
||||
OUTFILE="$3"
|
||||
fi
|
||||
|
||||
echo "Video=$VIDEO"
|
||||
echo "Captions=$SRT"
|
||||
echo "Outfile=$OUTFILE"
|
||||
|
||||
# ffmpeg -i $VIDEO -acodec copy -vcodec copy -f flv - | ./flv+srt - $SRT - | ffmpeg -i - -acodec copy -vcodec copy $OUTFILE
|
||||
ffmpeg -i $VIDEO -threads 0 -vcodec libx264 -profile:v main -preset:v medium \
|
||||
-r 30 -g 60 -keyint_min 60 -sc_threshold 0 -b:v 4000k -maxrate 4000k \
|
||||
-bufsize 4000k -filter:v scale="trunc(oh*a/2)*2:720" \
|
||||
-sws_flags lanczos+accurate_rnd -strict -2 -acodec aac -b:a 96k -ar 48000 -ac 2 \
|
||||
-f flv - | ./flv+srt - $SRT - | ffmpeg -i - -acodec copy -vcodec copy -y $OUTFILE
|
||||
117
deps/libcaption/examples/captioner.c
vendored
Normal file
117
deps/libcaption/examples/captioner.c
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "caption.h"
|
||||
#include "flv.h"
|
||||
|
||||
char charcode[] = {
|
||||
0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 0,
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']','\n', 0, 'A', 'S',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`', 0, '\\', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
int data_ready (int fd)
|
||||
{
|
||||
fd_set set;
|
||||
struct timeval timeout = {0,0};
|
||||
FD_ZERO (&set);
|
||||
FD_SET (fd,&set);
|
||||
int cnt = select (fd+1, &set, 0, 0, &timeout);
|
||||
FD_ZERO (&set);
|
||||
return (0 < cnt);
|
||||
}
|
||||
|
||||
#define MAX_CAP_LENGTH (SCREEN_ROWS*SCREEN_COLS)
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
int fd;
|
||||
ssize_t n;
|
||||
flvtag_t tag;
|
||||
struct input_event ev;
|
||||
int has_audio, has_video;
|
||||
const char* dev = argv[1];
|
||||
char text[MAX_CAP_LENGTH+1];
|
||||
memset (text,0,MAX_CAP_LENGTH+1);
|
||||
|
||||
FILE* flv = flv_open_read ("-");
|
||||
FILE* out = flv_open_write ("-");
|
||||
fd = open (dev, O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
fprintf (stderr, "Cannot open %s: %s.\n", dev, strerror (errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!flv_read_header (flv,&has_audio,&has_video)) {
|
||||
fprintf (stderr,"%s is not an flv file\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!flv_write_header (out,has_audio,has_video)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
flvtag_init (&tag);
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
|
||||
if (data_ready (fd)) {
|
||||
n = read (fd, &ev, sizeof ev);
|
||||
|
||||
if (n == (ssize_t)-1) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (n != sizeof ev) {
|
||||
errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
int len = strlen (text);
|
||||
char c = (EV_KEY == ev.type && 1 == ev.value && ev.code < 64) ? charcode[ev.code] : 0;
|
||||
|
||||
if (0 < len && '\n' == c) {
|
||||
fprintf (stderr,"='%s'\n", text);
|
||||
flvtag_addcaption (&tag, text);
|
||||
memset (text,0,MAX_CAP_LENGTH+1);
|
||||
} else if (0 != c && len < MAX_CAP_LENGTH) {
|
||||
text[len] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flv_write_tag (out,&tag);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
23
deps/libcaption/examples/flv+scc.c
vendored
Normal file
23
deps/libcaption/examples/flv+scc.c
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
96
deps/libcaption/examples/flv+srt.c
vendored
Normal file
96
deps/libcaption/examples/flv+srt.c
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "srt.h"
|
||||
#include "flv.h"
|
||||
#include "avc.h"
|
||||
// #include "sei.h"
|
||||
|
||||
#define MAX_SRT_SIZE (10*1024*1024)
|
||||
#define MAX_READ_SIZE 4096
|
||||
|
||||
srt_t* srt_from_file (const char* path)
|
||||
{
|
||||
srt_t* head = 0;
|
||||
size_t read, totl = 0;
|
||||
FILE* file = fopen (path,"r");
|
||||
|
||||
if (file) {
|
||||
char* srt_data = malloc (MAX_SRT_SIZE);
|
||||
size_t srt_size = 0;
|
||||
size_t size = MAX_SRT_SIZE;
|
||||
char* data = srt_data;
|
||||
|
||||
while (0 < (read = fread (data,1,size,file))) {
|
||||
totl += read; data += read; size -= read; srt_size += read;
|
||||
}
|
||||
|
||||
head = srt_parse (srt_data,srt_size);
|
||||
free (srt_data);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
flvtag_t tag;
|
||||
FILE* flv = flv_open_read (argv[1]);
|
||||
FILE* out = flv_open_write (argv[3]);
|
||||
|
||||
int has_audio, has_video;
|
||||
flvtag_init (&tag);
|
||||
|
||||
if (!flv_read_header (flv,&has_audio,&has_video)) {
|
||||
fprintf (stderr,"%s is not an flv file\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
srt_t* head = srt_from_file (argv[2]);
|
||||
srt_t* srt = head;
|
||||
|
||||
if (! head) {
|
||||
fprintf (stderr,"%s is not an srt file\n", argv[2]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
flv_write_header (out,has_audio,has_video);
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
// TODO handle B freame!
|
||||
if (srt && flvtag_pts_seconds (&tag) >= srt->timestamp && flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
|
||||
fprintf (stderr,"%f: %s\n", srt->timestamp, srt_data (srt));
|
||||
flvtag_addcaption (&tag, srt_data (srt));
|
||||
srt = srt->next;
|
||||
}
|
||||
|
||||
flv_write_tag (out,&tag);
|
||||
// Write tag out here
|
||||
}
|
||||
|
||||
srt_free (head);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
383
deps/libcaption/examples/flv.c
vendored
Normal file
383
deps/libcaption/examples/flv.c
vendored
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "flv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void flvtag_init (flvtag_t* tag)
|
||||
{
|
||||
memset (tag,0,sizeof (flvtag_t));
|
||||
}
|
||||
|
||||
void flvtag_free (flvtag_t* tag)
|
||||
{
|
||||
if (tag->data) {
|
||||
free (tag->data);
|
||||
}
|
||||
|
||||
flvtag_init (tag);
|
||||
}
|
||||
|
||||
int flvtag_reserve (flvtag_t* tag, uint32_t size)
|
||||
{
|
||||
size += FLV_TAG_HEADER_SIZE + FLV_TAG_FOOTER_SIZE;
|
||||
|
||||
if (size > tag->aloc) {
|
||||
tag->data = realloc (tag->data,size);
|
||||
tag->aloc = size;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE* flv_open_read (const char* flv)
|
||||
{
|
||||
if (0 == flv || 0 == strcmp ("-",flv)) {
|
||||
return stdin;
|
||||
}
|
||||
|
||||
return fopen (flv,"rb");
|
||||
}
|
||||
|
||||
FILE* flv_open_write (const char* flv)
|
||||
{
|
||||
if (0 == flv || 0 == strcmp ("-",flv)) {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
return fopen (flv,"wb");
|
||||
}
|
||||
|
||||
FILE* flv_close (FILE* flv)
|
||||
{
|
||||
fclose (flv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flv_read_header (FILE* flv, int* has_audio, int* has_video)
|
||||
{
|
||||
uint8_t h[FLV_HEADER_SIZE];
|
||||
|
||||
if (FLV_HEADER_SIZE != fread (&h[0],1,FLV_HEADER_SIZE,flv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ('F' != h[0] || 'L' != h[1] || 'V' != h[2]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*has_audio) = h[4]&0x04;
|
||||
(*has_video) = h[4]&0x01;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flv_write_header (FILE* flv, int has_audio, int has_video)
|
||||
{
|
||||
uint8_t h[FLV_HEADER_SIZE] = {'F', 'L', 'V', 1, (has_audio?0x04:0x00) | (has_video?0x01:0x00), 0, 0, 0, 9, 0, 0, 0, 0 };
|
||||
return FLV_HEADER_SIZE == fwrite (&h[0],1,FLV_HEADER_SIZE,flv);
|
||||
}
|
||||
|
||||
int flv_read_tag (FILE* flv, flvtag_t* tag)
|
||||
{
|
||||
uint32_t size;
|
||||
uint8_t h[FLV_TAG_HEADER_SIZE];
|
||||
|
||||
if (FLV_TAG_HEADER_SIZE != fread (&h[0],1,FLV_TAG_HEADER_SIZE,flv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = ( (h[1]<<16) | (h[2]<<8) |h[3]);
|
||||
flvtag_reserve (tag, size);
|
||||
// copy header to buffer
|
||||
memcpy (tag->data,&h[0],FLV_TAG_HEADER_SIZE);
|
||||
|
||||
if (size+FLV_TAG_FOOTER_SIZE != fread (&tag->data[FLV_TAG_HEADER_SIZE],1,size+FLV_TAG_FOOTER_SIZE,flv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flv_write_tag (FILE* flv, flvtag_t* tag)
|
||||
{
|
||||
size_t size = flvtag_raw_size (tag);
|
||||
return size == fwrite (flvtag_raw_data (tag),1,size,flv);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t flvtag_header_size (flvtag_t* tag)
|
||||
{
|
||||
switch (flvtag_type (tag)) {
|
||||
case flvtag_type_audio:
|
||||
return FLV_TAG_HEADER_SIZE + (flvtag_soundformat_aac != flvtag_soundformat (tag) ? 1 : 2);
|
||||
|
||||
case flvtag_type_video:
|
||||
// CommandFrame does not have a compositionTime
|
||||
return FLV_TAG_HEADER_SIZE + (flvtag_codecid_avc != flvtag_codecid (tag) ? 1 : (flvtag_frametype_commandframe != flvtag_frametype (tag) ? 5 : 2));
|
||||
|
||||
default:
|
||||
return FLV_TAG_HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
size_t flvtag_payload_size (flvtag_t* tag)
|
||||
{
|
||||
return FLV_TAG_HEADER_SIZE + flvtag_size (tag) - flvtag_header_size (tag);
|
||||
}
|
||||
|
||||
uint8_t* flvtag_payload_data (flvtag_t* tag)
|
||||
{
|
||||
size_t payload_offset = flvtag_header_size (tag);
|
||||
return &tag->data[payload_offset];
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int flvtag_updatesize (flvtag_t* tag, uint32_t size)
|
||||
{
|
||||
tag->data[1] = size>>16; // DataSize
|
||||
tag->data[2] = size>>8; // DataSize
|
||||
tag->data[3] = size>>0; // DataSize
|
||||
size += 11;
|
||||
tag->data[size+0] = size>>24; // PrevTagSize
|
||||
tag->data[size+1] = size>>16; // PrevTagSize
|
||||
tag->data[size+2] = size>>8; // PrevTagSize
|
||||
tag->data[size+3] = size>>0; // PrevTagSize
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define FLVTAG_PREALOC 2048
|
||||
int flvtag_initavc (flvtag_t* tag, uint32_t dts, int32_t cts, flvtag_frametype_t type)
|
||||
{
|
||||
flvtag_init (tag);
|
||||
flvtag_reserve (tag,5+FLVTAG_PREALOC);
|
||||
tag->data[0] = flvtag_type_video;
|
||||
tag->data[4] = dts>>16;
|
||||
tag->data[5] = dts>>8;
|
||||
tag->data[6] = dts>>0;
|
||||
tag->data[7] = dts>>24;
|
||||
tag->data[8] = 0; // StreamID
|
||||
tag->data[9] = 0; // StreamID
|
||||
tag->data[10] = 0; // StreamID
|
||||
// VideoTagHeader
|
||||
tag->data[11] = ( (type<<4) %0xF0) |0x07; // CodecId
|
||||
tag->data[12] = 0x01; // AVC NALU
|
||||
tag->data[13] = cts>>16;
|
||||
tag->data[14] = cts>>8;
|
||||
tag->data[15] = cts>>0;
|
||||
flvtag_updatesize (tag,5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flvtag_initamf (flvtag_t* tag, uint32_t dts)
|
||||
{
|
||||
flvtag_init (tag);
|
||||
flvtag_reserve (tag,FLVTAG_PREALOC);
|
||||
tag->data[0] = flvtag_type_scriptdata;
|
||||
tag->data[4] = dts>>16;
|
||||
tag->data[5] = dts>>8;
|
||||
tag->data[6] = dts>>0;
|
||||
tag->data[7] = dts>>24;
|
||||
tag->data[8] = 0; // StreamID
|
||||
tag->data[9] = 0; // StreamID
|
||||
tag->data[10] = 0; // StreamID
|
||||
flvtag_updatesize (tag,0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// shamelessly taken from libtomcrypt, an public domain project
|
||||
static void base64_encode (const unsigned char* in, unsigned long inlen, unsigned char* out, unsigned long* outlen)
|
||||
{
|
||||
static const char* codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
unsigned long i, len2, leven;
|
||||
unsigned char* p;
|
||||
|
||||
/* valid output size ? */
|
||||
len2 = 4 * ( (inlen + 2) / 3);
|
||||
|
||||
if (*outlen < len2 + 1) {
|
||||
*outlen = len2 + 1;
|
||||
fprintf (stderr,"\n\nHERE\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p = out;
|
||||
leven = 3* (inlen / 3);
|
||||
|
||||
for (i = 0; i < leven; i += 3) {
|
||||
*p++ = codes[ (in[0] >> 2) & 0x3F];
|
||||
*p++ = codes[ ( ( (in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
|
||||
*p++ = codes[ ( ( (in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
|
||||
*p++ = codes[in[2] & 0x3F];
|
||||
in += 3;
|
||||
}
|
||||
|
||||
if (i < inlen) {
|
||||
unsigned a = in[0];
|
||||
unsigned b = (i+1 < inlen) ? in[1] : 0;
|
||||
|
||||
*p++ = codes[ (a >> 2) & 0x3F];
|
||||
*p++ = codes[ ( ( (a & 3) << 4) + (b >> 4)) & 0x3F];
|
||||
*p++ = (i+1 < inlen) ? codes[ ( ( (b & 0xf) << 2)) & 0x3F] : '=';
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
/* return ok */
|
||||
*outlen = p - out;
|
||||
}
|
||||
|
||||
const char onCaptionInfo708[] = { 0x02,0x00,0x0D, 'o','n','C','a','p','t','i','o','n','I','n','f','o',
|
||||
0x08, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x04, 't','y','p','e',
|
||||
0x02, 0x00, 0x03, '7','0','8',
|
||||
0x00, 0x04, 'd','a','t','a',
|
||||
0x02, 0x00,0x00
|
||||
};
|
||||
|
||||
int flvtag_amfcaption_708 (flvtag_t* tag, uint32_t timestamp, sei_message_t* msg)
|
||||
{
|
||||
flvtag_initamf (tag,timestamp);
|
||||
unsigned long size = 1 + (4 * ( (sei_message_size (msg) + 2) / 3));
|
||||
flvtag_reserve (tag, sizeof (onCaptionInfo708) + size + 3);
|
||||
memcpy (flvtag_payload_data (tag),onCaptionInfo708,sizeof (onCaptionInfo708));
|
||||
uint8_t* data = flvtag_payload_data (tag) + sizeof (onCaptionInfo708);
|
||||
base64_encode (sei_message_data (msg), sei_message_size (msg), data, &size);
|
||||
|
||||
// Update the size of the base64 string
|
||||
data[-2] = size >> 8;
|
||||
data[-1] = size >> 0;
|
||||
// write the last array element
|
||||
data[size+0] = 0x00;
|
||||
data[size+1] = 0x00;
|
||||
data[size+2] = 0x09;
|
||||
flvtag_updatesize (tag, sizeof (onCaptionInfo708) + size + 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char onCaptionInfoUTF8[] = { 0x02,0x00,0x0D, 'o','n','C','a','p','t','i','o','n','I','n','f','o',
|
||||
0x08, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x04, 't','y','p','e',
|
||||
0x02, 0x00, 0x04, 'U','T','F','8',
|
||||
0x00, 0x04, 'd','a','t','a',
|
||||
0x02, 0x00,0x00
|
||||
};
|
||||
|
||||
#define MAX_AMF_STRING 65636
|
||||
int flvtag_amfcaption_utf8 (flvtag_t* tag, uint32_t timestamp, const utf8_char_t* text)
|
||||
{
|
||||
flvtag_initamf (tag,timestamp);
|
||||
unsigned long size = strlen (text);
|
||||
|
||||
if (MAX_AMF_STRING < size) {
|
||||
size = MAX_AMF_STRING;
|
||||
}
|
||||
|
||||
flvtag_reserve (tag, sizeof (onCaptionInfoUTF8) + size + 3);
|
||||
memcpy (flvtag_payload_data (tag),onCaptionInfoUTF8,sizeof (onCaptionInfoUTF8));
|
||||
uint8_t* data = flvtag_payload_data (tag) + sizeof (onCaptionInfo708);
|
||||
memcpy (data,text,size);
|
||||
// Update the size of the string
|
||||
data[-2] = size >> 8;
|
||||
data[-1] = size >> 0;
|
||||
// write the last array element
|
||||
data[size+0] = 0x00;
|
||||
data[size+1] = 0x00;
|
||||
data[size+2] = 0x09;
|
||||
flvtag_updatesize (tag, sizeof (onCaptionInfoUTF8) + size + 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define LENGTH_SIZE 4
|
||||
|
||||
int flvtag_avcwritenal (flvtag_t* tag, uint8_t* data, size_t size)
|
||||
{
|
||||
uint32_t flvsize = flvtag_size (tag);
|
||||
flvtag_reserve (tag,flvsize+LENGTH_SIZE+size);
|
||||
uint8_t* payload = tag->data + FLV_TAG_HEADER_SIZE + flvsize;
|
||||
payload[0] = size>>24; // nalu size
|
||||
payload[1] = size>>16;
|
||||
payload[2] = size>>8;
|
||||
payload[3] = size>>0;
|
||||
memcpy (&payload[LENGTH_SIZE],data,size);
|
||||
flvtag_updatesize (tag,flvsize+LENGTH_SIZE+size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flvtag_addcaption (flvtag_t* tag, const utf8_char_t* text)
|
||||
{
|
||||
if (flvtag_avcpackettype_nalu != flvtag_avcpackettype (tag)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sei_t sei;
|
||||
caption_frame_t frame;
|
||||
|
||||
sei_init (&sei);
|
||||
caption_frame_init (&frame);
|
||||
caption_frame_from_text (&frame, text);
|
||||
sei_from_caption_frame (&sei, &frame);
|
||||
|
||||
uint8_t* sei_data = malloc (sei_render_size (&sei));
|
||||
size_t sei_size = sei_render (&sei, sei_data);
|
||||
|
||||
// rewrite tag
|
||||
flvtag_t new_tag;
|
||||
flvtag_initavc (&new_tag, flvtag_dts (tag), flvtag_cts (tag), flvtag_frametype (tag));
|
||||
uint8_t* data = flvtag_payload_data (tag);
|
||||
ssize_t size = flvtag_payload_size (tag);
|
||||
|
||||
while (0<size) {
|
||||
uint8_t* nalu_data = &data[LENGTH_SIZE];
|
||||
uint8_t nalu_type = nalu_data[0]&0x1F;
|
||||
uint32_t nalu_size = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3];
|
||||
data += LENGTH_SIZE + nalu_size;
|
||||
size -= LENGTH_SIZE + nalu_size;
|
||||
|
||||
if (0 < sei_size && 7 != nalu_type && 8 != nalu_type && 9 != nalu_type ) {
|
||||
// fprintf (stderr,"Wrote SEI %d '%d'\n\n", sei_size, sei_data[3]);
|
||||
flvtag_avcwritenal (&new_tag,sei_data,sei_size);
|
||||
sei_size = 0;
|
||||
}
|
||||
|
||||
flvtag_avcwritenal (&new_tag,nalu_data,nalu_size);
|
||||
}
|
||||
|
||||
// On the off chance we have an empty frame,
|
||||
// We still wish to append the sei
|
||||
if (0<sei_size) {
|
||||
// fprintf (stderr,"Wrote SEI %d\n\n", sei_size);
|
||||
flvtag_avcwritenal (&new_tag,sei_data,sei_size);
|
||||
sei_size = 0;
|
||||
}
|
||||
|
||||
if (sei_data) {
|
||||
free (sei_data);
|
||||
}
|
||||
|
||||
free (tag->data);
|
||||
sei_free (&sei);
|
||||
tag->data = new_tag.data;
|
||||
tag->aloc = new_tag.aloc;
|
||||
return 1;
|
||||
}
|
||||
142
deps/libcaption/examples/flv.h
vendored
Normal file
142
deps/libcaption/examples/flv.h
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#ifndef LIBCAPTION_FLV_H
|
||||
#define LIBCAPTION_FLV_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#define FLV_HEADER_SIZE 13
|
||||
#define FLV_FOOTER_SIZE 4
|
||||
#define FLV_TAG_HEADER_SIZE 11
|
||||
#define FLV_TAG_FOOTER_SIZE 4
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include "avc.h"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct {
|
||||
uint8_t* data;
|
||||
size_t aloc;
|
||||
} flvtag_t;
|
||||
|
||||
void flvtag_init (flvtag_t* tag);
|
||||
void flvtag_free (flvtag_t* tag);
|
||||
void flvtag_swap (flvtag_t* tag1, flvtag_t* tag2);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
flvtag_type_audio = 0x08,
|
||||
flvtag_type_video = 0x09,
|
||||
flvtag_type_scriptdata = 0x12,
|
||||
} flvtag_type_t;
|
||||
|
||||
static inline flvtag_type_t flvtag_type (flvtag_t* tag) { return (flvtag_type_t) tag->data[0]&0x1F; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
flvtag_soundformat_unknown = -1,
|
||||
flvtag_soundformat_linearpcmplatformendian = 0,
|
||||
flvtag_soundformat_adpcm = 1,
|
||||
flvtag_soundformat_mp3 = 2,
|
||||
flvtag_soundformat_linearpcmlittleendian = 3,
|
||||
flvtag_soundformat_nellymoser_16khzmono = 4,
|
||||
flvtag_soundformat_nellymoser_8khzmono = 5,
|
||||
flvtag_soundformat_nellymoser = 6,
|
||||
flvtag_soundformat_g711alawlogarithmicpcm = 7,
|
||||
flvtag_soundformat_g711mulawlogarithmicpcm = 8,
|
||||
flvtag_soundformat_reserved = 9,
|
||||
flvtag_soundformat_aac = 10,
|
||||
flvtag_soundformat_speex = 11,
|
||||
flvtag_soundformat_mp3_8khz = 14,
|
||||
flvtag_soundformat_devicespecificsound = 15
|
||||
} flvtag_soundformat_t;
|
||||
|
||||
static inline flvtag_soundformat_t flvtag_soundformat (flvtag_t* tag) { return (flvtag_type_audio!=flvtag_type (tag)) ?flvtag_soundformat_unknown: (flvtag_soundformat_t) (tag->data[0]>>4) &0x0F; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
flvtag_codecid_unknown = -1,
|
||||
flvtag_codecid_sorensonh263 = 2,
|
||||
flvtag_codecid_screenvideo = 3,
|
||||
flvtag_codecid_on2vp6 = 4,
|
||||
flvtag_codecid_on2vp6withalphachannel = 5,
|
||||
flvtag_codecid_screenvideoversion2 = 6,
|
||||
flvtag_codecid_avc = 7
|
||||
} flvtag_codecid_t;
|
||||
|
||||
static inline flvtag_codecid_t flvtag_codecid (flvtag_t* tag) { return (flvtag_type_video!=flvtag_type (tag)) ? (flvtag_codecid_unknown) : (tag->data[11]&0x0F); }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
flvtag_frametype_unknown = -1,
|
||||
flvtag_frametype_keyframe = 1,
|
||||
flvtag_frametype_interframe = 2,
|
||||
flvtag_frametype_disposableinterframe = 3,
|
||||
flvtag_frametype_generatedkeyframe = 4,
|
||||
flvtag_frametype_commandframe = 5
|
||||
} flvtag_frametype_t;
|
||||
|
||||
static inline flvtag_frametype_t flvtag_frametype (flvtag_t* tag) { return (flvtag_type_video!=flvtag_type (tag)) ?flvtag_frametype_keyframe: ( (tag->data[11]>>4) &0x0F); }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
flvtag_avcpackettype_unknown = -1,
|
||||
flvtag_avcpackettype_sequenceheader = 0,
|
||||
flvtag_avcpackettype_nalu = 1,
|
||||
flvtag_avcpackettype_endofsequence = 2
|
||||
} flvtag_avcpackettype_t;
|
||||
|
||||
static inline flvtag_avcpackettype_t flvtag_avcpackettype (flvtag_t* tag) { return (flvtag_codecid_avc!=flvtag_codecid (tag)) ?flvtag_avcpackettype_unknown:tag->data[12]; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static inline size_t flvtag_size (flvtag_t* tag) { return (tag->data[1]<<16) | (tag->data[2]<<8) | tag->data[3]; }
|
||||
static inline uint32_t flvtag_timestamp (flvtag_t* tag) { return (tag->data[7]<<24) | (tag->data[4]<<16) | (tag->data[5]<<8) | tag->data[6]; }
|
||||
static inline uint32_t flvtag_dts (flvtag_t* tag) { return flvtag_timestamp (tag); }
|
||||
static inline uint32_t flvtag_cts (flvtag_t* tag) { return (flvtag_avcpackettype_nalu!=flvtag_avcpackettype (tag)) ?0: (tag->data[13]<<16) | (tag->data[14]<<8) |tag->data[15]; }
|
||||
static inline uint32_t flvtag_pts (flvtag_t* tag) { return flvtag_dts (tag)+flvtag_cts (tag); }
|
||||
static inline double flvtag_dts_seconds (flvtag_t* tag) { return flvtag_dts (tag) / 1000.0; }
|
||||
static inline double flvtag_cts_seconds (flvtag_t* tag) { return flvtag_cts (tag) / 1000.0; }
|
||||
static inline double flvtag_pts_seconds (flvtag_t* tag) { return flvtag_pts (tag) / 1000.0; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t flvtag_header_size (flvtag_t* tag);
|
||||
size_t flvtag_payload_size (flvtag_t* tag);
|
||||
uint8_t* flvtag_payload_data (flvtag_t* tag);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
FILE* flv_open_read (const char* flv);
|
||||
FILE* flv_open_write (const char* flv);
|
||||
FILE* flv_close (FILE* flv);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static inline const uint8_t* flvtag_raw_data (flvtag_t* tag) { return tag->data; }
|
||||
static inline const size_t flvtag_raw_size (flvtag_t* tag) { return flvtag_size (tag)+FLV_TAG_HEADER_SIZE+FLV_TAG_FOOTER_SIZE; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int flv_read_tag (FILE* flv, flvtag_t* tag);
|
||||
int flv_write_tag (FILE* flv, flvtag_t* tag);
|
||||
int flv_read_header (FILE* flv, int* has_audio, int* has_video);
|
||||
int flv_write_header (FILE* flv, int has_audio, int has_video);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// If the tage has more that on sei message, they will be combined into one
|
||||
sei_t* flv_read_sei (FILE* flv, flvtag_t* tag);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int flvtag_initavc (flvtag_t* tag, uint32_t dts, int32_t cts, flvtag_frametype_t type);
|
||||
int flvtag_avcwritenal (flvtag_t* tag, uint8_t* data, size_t size);
|
||||
int flvtag_addcaption (flvtag_t* tag, const utf8_char_t* text);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int flvtag_amfcaption_708 (flvtag_t* tag, uint32_t timestamp, sei_message_t* msg);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This method is expermental, and not currently available on Twitch
|
||||
int flvtag_amfcaption_utf8 (flvtag_t* tag, uint32_t timestamp, const utf8_char_t* text);
|
||||
#endif
|
||||
92
deps/libcaption/examples/flv2srt.c
vendored
Normal file
92
deps/libcaption/examples/flv2srt.c
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "flv.h"
|
||||
#include "srt.h"
|
||||
#include "avc.h"
|
||||
|
||||
#define LENGTH_SIZE 4
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
const char* path = argv[1];
|
||||
|
||||
sei_t sei;
|
||||
flvtag_t tag;
|
||||
srt_t* srt = 0, *head = 0;
|
||||
int i, has_audio, has_video;
|
||||
caption_frame_t frame;
|
||||
|
||||
flvtag_init (&tag);
|
||||
caption_frame_init (&frame);
|
||||
|
||||
FILE* flv = flv_open_read (path);
|
||||
|
||||
if (!flv_read_header (flv,&has_audio,&has_video)) {
|
||||
fprintf (stderr,"'%s' Not an flv file\n", path);
|
||||
} else {
|
||||
fprintf (stderr,"Reading from '%s'\n", path);
|
||||
}
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
|
||||
ssize_t size = flvtag_payload_size (&tag);
|
||||
uint8_t* data = flvtag_payload_data (&tag);
|
||||
|
||||
while (0<size) {
|
||||
ssize_t nalu_size = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3];
|
||||
uint8_t* nalu_data = &data[4];
|
||||
uint8_t nalu_type = nalu_data[0]&0x1F;
|
||||
data += nalu_size + LENGTH_SIZE;
|
||||
size -= nalu_size + LENGTH_SIZE;
|
||||
|
||||
if (6 == nalu_type) {
|
||||
sei_init (&sei);
|
||||
sei_parse_nalu (&sei, nalu_data, nalu_size, flvtag_dts (&tag), flvtag_cts (&tag));
|
||||
|
||||
cea708_t cea708;
|
||||
sei_message_t* msg;
|
||||
cea708_init (&cea708);
|
||||
|
||||
// for (msg = sei_message_head (&sei) ; msg ; msg = sei_message_next (msg)) {
|
||||
// if (sei_type_user_data_registered_itu_t_t35 == sei_message_type (msg)) {
|
||||
// cea708_parse (sei_message_data (msg), sei_message_size (msg), &cea708);
|
||||
// cea708_dump (&cea708);
|
||||
// }
|
||||
// }
|
||||
|
||||
// sei_dump(&sei);
|
||||
sei_to_caption_frame (&sei,&frame);
|
||||
sei_free (&sei);
|
||||
|
||||
// caption_frame_dump (&frame);
|
||||
srt = srt_from_caption_frame (&frame,srt,&head);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srt_dump (head);
|
||||
srt_free (head);
|
||||
|
||||
return 1;
|
||||
}
|
||||
122
deps/libcaption/examples/party.c
vendored
Normal file
122
deps/libcaption/examples/party.c
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "flv.h"
|
||||
#include "avc.h"
|
||||
|
||||
#define CAPTION_METHOD_SEI_708 0 // embedded 708
|
||||
#define CAPTION_METHOD_AMF_708 1 // onCaptionInfo type = 708
|
||||
#define CAPTION_METHOD_AMF_UTF8 2 // onCaptionInfo type = utf8
|
||||
#define CAPTION_METHOD CAPTION_METHOD_SEI_708
|
||||
|
||||
void get_dudes (char* str)
|
||||
{
|
||||
sprintf (str, " %s%s %s(-_-)%s %s(-_-)%s.%s(-_-)%s %s%s", EIA608_CHAR_EIGHTH_NOTE, EIA608_CHAR_EIGHTH_NOTE,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
! (rand() % 2) ? EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT : EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
|
||||
EIA608_CHAR_EIGHTH_NOTE, EIA608_CHAR_EIGHTH_NOTE);
|
||||
}
|
||||
|
||||
void write_amfcaptions_708 (FILE* out, uint32_t timestamp, const char* text)
|
||||
{
|
||||
sei_t sei;
|
||||
flvtag_t tag;
|
||||
sei_message_t* msg;
|
||||
caption_frame_t frame;
|
||||
sei_init (&sei);
|
||||
flvtag_init (&tag);
|
||||
caption_frame_init (&frame);
|
||||
caption_frame_from_text (&frame, text);
|
||||
sei_from_caption_frame (&sei, &frame);
|
||||
// caption_frame_dump (&frame);
|
||||
|
||||
for (msg = sei_message_head (&sei); msg; msg=sei_message_next (msg),++timestamp) {
|
||||
flvtag_amfcaption_708 (&tag,timestamp,msg);
|
||||
flv_write_tag (out,&tag);
|
||||
}
|
||||
|
||||
sei_free (&sei);
|
||||
flvtag_free (&tag);
|
||||
}
|
||||
|
||||
|
||||
void write_amfcaptions_utf8 (FILE* out, uint32_t timestamp, const utf8_char_t* text)
|
||||
{
|
||||
flvtag_t tag;
|
||||
flvtag_init (&tag);
|
||||
flvtag_amfcaption_utf8 (&tag,timestamp,text);
|
||||
flv_write_tag (out,&tag);
|
||||
flvtag_free (&tag);
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
flvtag_t tag;
|
||||
uint32_t nextParty = 1000;
|
||||
int has_audio, has_video;
|
||||
FILE* flv = flv_open_read (argv[1]);
|
||||
FILE* out = flv_open_write (argv[2]);
|
||||
char partyDudes[64];
|
||||
|
||||
flvtag_init (&tag);
|
||||
|
||||
if (!flv_read_header (flv,&has_audio,&has_video)) {
|
||||
fprintf (stderr,"%s is not an flv file\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
flv_write_header (out,has_audio,has_video);
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
|
||||
if (flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag) && nextParty <= flvtag_timestamp (&tag)) {
|
||||
get_dudes (partyDudes);
|
||||
|
||||
if (CAPTION_METHOD == CAPTION_METHOD_SEI_708) {
|
||||
flvtag_addcaption (&tag, partyDudes);
|
||||
} else if (CAPTION_METHOD == CAPTION_METHOD_AMF_708) {
|
||||
write_amfcaptions_708 (out,nextParty,partyDudes);
|
||||
} else if (CAPTION_METHOD == CAPTION_METHOD_AMF_708) {
|
||||
write_amfcaptions_utf8 (out, nextParty, partyDudes);
|
||||
} else {
|
||||
fprintf (stderr,"Unknnow method\n");
|
||||
return EXIT_FAILURE;
|
||||
|
||||
}
|
||||
|
||||
fprintf (stderr,"%d: %s\n",nextParty, partyDudes);
|
||||
nextParty += 500; // party all the time
|
||||
}
|
||||
|
||||
flv_write_tag (out,&tag);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
95
deps/libcaption/examples/rollup.c
vendored
Normal file
95
deps/libcaption/examples/rollup.c
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "flv.h"
|
||||
#include "avc.h"
|
||||
#include "srt.h"
|
||||
#include "wonderland.h"
|
||||
|
||||
#define SECONDS_PER_LINE 3.0
|
||||
srt_t* appennd_caption (const utf8_char_t* data, srt_t* prev, srt_t** head)
|
||||
{
|
||||
|
||||
int r, c, chan = 0;
|
||||
ssize_t size = (ssize_t) strlen (data);
|
||||
size_t char_count, char_length, line_length = 0, trimmed_length = 0;
|
||||
|
||||
for (r = 0 ; 0 < size && SCREEN_ROWS > r ; ++r) {
|
||||
line_length = utf8_line_length (data);
|
||||
trimmed_length = utf8_trimmed_length (data,line_length);
|
||||
char_count = utf8_char_count (data,trimmed_length);
|
||||
|
||||
// If char_count is greater than one line can display, split it.
|
||||
if (SCREEN_COLS < char_count) {
|
||||
char_count = utf8_wrap_length (data,SCREEN_COLS);
|
||||
line_length = utf8_string_length (data,char_count+1);
|
||||
}
|
||||
|
||||
// fprintf (stderr,"%.*s\n", line_length, data);
|
||||
prev = srt_new (data, line_length, prev ? prev->timestamp + SECONDS_PER_LINE : 0, prev, head);
|
||||
|
||||
data += line_length;
|
||||
size -= (ssize_t) line_length;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
int i = 0;
|
||||
flvtag_t tag;
|
||||
srt_t* head = 0, *tail = 0;
|
||||
int has_audio, has_video;
|
||||
FILE* flv = flv_open_read (argv[1]);
|
||||
FILE* out = flv_open_write (argv[2]);
|
||||
flvtag_init (&tag);
|
||||
|
||||
for (i = 0 ; wonderland[i][0]; ++i) {
|
||||
tail = appennd_caption (wonderland[i], tail, &head);
|
||||
}
|
||||
|
||||
|
||||
if (!flv_read_header (flv,&has_audio,&has_video)) {
|
||||
fprintf (stderr,"%s is not an flv file\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
flv_write_header (out,has_audio,has_video);
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
if (head && flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag) && head->timestamp <= flvtag_pts_seconds (&tag)) {
|
||||
fprintf (stderr,"%f %s\n", flvtag_pts_seconds (&tag), srt_data (head));
|
||||
flvtag_addcaption (&tag, srt_data (head));
|
||||
head = srt_free_head (head);
|
||||
}
|
||||
|
||||
|
||||
flv_write_tag (out,&tag);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
165
deps/libcaption/examples/rtmpspit.c
vendored
Normal file
165
deps/libcaption/examples/rtmpspit.c
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include "flv.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <librtmp/log.h>
|
||||
#include <librtmp/rtmp.h>
|
||||
|
||||
|
||||
int MyRTMP_Write (RTMP* r, const char* buf, int size)
|
||||
{
|
||||
RTMPPacket* pkt = &r->m_write;
|
||||
char* enc;
|
||||
int s2 = size, ret, num;
|
||||
|
||||
pkt->m_nChannel = 0x04; /* source channel */
|
||||
pkt->m_nInfoField2 = r->m_stream_id;
|
||||
|
||||
while (s2) {
|
||||
if (!pkt->m_nBytesRead) {
|
||||
if (size < 11) {
|
||||
/* FLV pkt too small */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V') {
|
||||
buf += 13;
|
||||
s2 -= 13;
|
||||
}
|
||||
|
||||
pkt->m_packetType = *buf++;
|
||||
pkt->m_nBodySize = AMF_DecodeInt24 (buf);
|
||||
buf += 3;
|
||||
pkt->m_nTimeStamp = AMF_DecodeInt24 (buf);
|
||||
buf += 3;
|
||||
pkt->m_nTimeStamp |= *buf++ << 24;
|
||||
buf += 3;
|
||||
s2 -= 11;
|
||||
|
||||
if ( ( (pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO
|
||||
|| pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) &&
|
||||
!pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO) {
|
||||
pkt->m_headerType = RTMP_PACKET_SIZE_LARGE;
|
||||
} else {
|
||||
pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
|
||||
}
|
||||
|
||||
if (!RTMPPacket_Alloc (pkt, pkt->m_nBodySize)) {
|
||||
RTMP_Log (RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
enc = pkt->m_body;
|
||||
} else {
|
||||
enc = pkt->m_body + pkt->m_nBytesRead;
|
||||
}
|
||||
|
||||
num = pkt->m_nBodySize - pkt->m_nBytesRead;
|
||||
|
||||
if (num > s2) {
|
||||
num = s2;
|
||||
}
|
||||
|
||||
memcpy (enc, buf, num);
|
||||
pkt->m_nBytesRead += num;
|
||||
s2 -= num;
|
||||
buf += num;
|
||||
|
||||
if (pkt->m_nBytesRead == pkt->m_nBodySize) {
|
||||
ret = RTMP_SendPacket (r, pkt, FALSE);
|
||||
RTMPPacket_Free (pkt);
|
||||
pkt->m_nBytesRead = 0;
|
||||
|
||||
if (!ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf += 4;
|
||||
s2 -= 4;
|
||||
|
||||
if (s2 < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size+s2;
|
||||
}
|
||||
|
||||
int main (int argc, const char** argv)
|
||||
{
|
||||
FILE* flv;
|
||||
RTMP* rtmp;
|
||||
RTMPPacket rtmpPacket;
|
||||
|
||||
flvtag_t tag;
|
||||
int32_t timestamp = 0;
|
||||
int has_audio, has_video;
|
||||
char* url = 0;
|
||||
|
||||
if (2 >= argc) {
|
||||
fprintf (stderr,"Usage %s [input] [url]\n",argv[0]);
|
||||
}
|
||||
|
||||
url = (char*) argv[2];
|
||||
flv = flv_open_read (argv[1]);
|
||||
|
||||
if (! flv) {
|
||||
fprintf (stderr,"Could not open %s\n",argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (! flv_read_header (flv, &has_audio, &has_video)) {
|
||||
fprintf (stderr,"Not an flv file %s\n",argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
flvtag_init (&tag);
|
||||
rtmp = RTMP_Alloc();
|
||||
RTMP_Init (rtmp);
|
||||
fprintf (stderr,"Connecting to %s\n", url);
|
||||
RTMP_SetupURL (rtmp, url);
|
||||
RTMP_EnableWrite (rtmp);
|
||||
|
||||
RTMP_Connect (rtmp, NULL);
|
||||
RTMP_ConnectStream (rtmp, 0);
|
||||
memset (&rtmpPacket, 0, sizeof (RTMPPacket));
|
||||
|
||||
if (! RTMP_IsConnected (rtmp)) {
|
||||
fprintf (stderr,"RTMP_IsConnected() Error\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while (flv_read_tag (flv,&tag)) {
|
||||
if (! RTMP_IsConnected (rtmp) || RTMP_IsTimedout (rtmp)) {
|
||||
fprintf (stderr,"RTMP_IsConnected() Error\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (flvtag_timestamp (&tag) > timestamp) {
|
||||
usleep (1000 * (flvtag_timestamp (&tag) - timestamp));
|
||||
timestamp = flvtag_timestamp (&tag);
|
||||
}
|
||||
|
||||
MyRTMP_Write (rtmp, (const char*) flvtag_raw_data (&tag),flvtag_raw_size (&tag));
|
||||
|
||||
// Handle RTMP ping and such
|
||||
fd_set sockset; struct timeval timeout = {0,0};
|
||||
FD_ZERO (&sockset); FD_SET (RTMP_Socket (rtmp), &sockset);
|
||||
register int result = select (RTMP_Socket (rtmp) + 1, &sockset, NULL, NULL, &timeout);
|
||||
|
||||
if (result == 1 && FD_ISSET (RTMP_Socket (rtmp), &sockset)) {
|
||||
RTMP_ReadPacket (rtmp, &rtmpPacket);
|
||||
|
||||
if (! RTMPPacket_IsReady (&rtmpPacket)) {
|
||||
fprintf (stderr,"Received RTMP packet\n");
|
||||
RTMP_ClientPacket (rtmp,&rtmpPacket);
|
||||
RTMPPacket_Free (&rtmpPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
96
deps/libcaption/examples/scc2srt.c
vendored
Normal file
96
deps/libcaption/examples/scc2srt.c
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "srt.h"
|
||||
#include "scc.h"
|
||||
|
||||
#define MAX_SCC_SIZE (10*1024*1024)
|
||||
#define MAX_READ_SIZE 4096
|
||||
#define MAX_CC 128
|
||||
|
||||
size_t read_file (FILE* file, utf8_char_t* data, size_t size)
|
||||
{
|
||||
size_t read, totl = 0;
|
||||
|
||||
while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
|
||||
totl += read; data += read; size -= read;
|
||||
}
|
||||
|
||||
return totl;
|
||||
}
|
||||
|
||||
srt_t* scc2srt (const char* data)
|
||||
{
|
||||
double pts;
|
||||
size_t line_size = 0;
|
||||
int cc_idx, count, i;
|
||||
srt_t* srt = 0, *head = 0;
|
||||
caption_frame_t frame;
|
||||
uint16_t cc_data[MAX_CC];
|
||||
|
||||
while (0 < (line_size = utf8_line_length (data))) {
|
||||
caption_frame_init (&frame);
|
||||
int cc_count = scc_to_608 (data, &pts, (uint16_t*) &cc_data, MAX_CC);
|
||||
data += line_size;
|
||||
data += utf8_line_length (data); // skip empty line
|
||||
|
||||
// fprintf (stderr,"%f, %d| %.*s\n", pts, cc_count, (int) line_size,data);
|
||||
|
||||
for (cc_idx = 0 ; cc_idx < cc_count ; ++cc_idx) {
|
||||
// eia608_dump (cc_data[cc_idx]);
|
||||
caption_frame_decode (&frame,cc_data[cc_idx],pts);
|
||||
}
|
||||
|
||||
// utf8_char_t buff[CAPTION_FRAME_DUMP_BUF_SIZE];
|
||||
// size_t size = caption_frame_dump (&frame, buff);
|
||||
// fprintf (stderr,"%s\n", buff);
|
||||
srt = srt_from_caption_frame (&frame,srt,&head);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
char frame_buf[CAPTION_FRAME_DUMP_BUF_SIZE];
|
||||
|
||||
if (argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* file = fopen (argv[1],"r");
|
||||
|
||||
if (! file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
utf8_char_t* data = malloc (MAX_SCC_SIZE);
|
||||
read_file (file,data,MAX_SCC_SIZE);
|
||||
srt_t* srt = scc2srt (data);
|
||||
srt_dump (srt);
|
||||
srt_free (srt);
|
||||
free (data);
|
||||
}
|
||||
64
deps/libcaption/examples/srt2vtt.c
vendored
Normal file
64
deps/libcaption/examples/srt2vtt.c
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "srt.h"
|
||||
|
||||
#define MAX_SRT_SIZE (10*1024*1024)
|
||||
#define MAX_READ_SIZE 4096
|
||||
|
||||
size_t read_file (FILE* file, utf8_char_t* data, size_t size)
|
||||
{
|
||||
size_t read, totl = 0;
|
||||
|
||||
while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
|
||||
totl += read; data += read; size -= read;
|
||||
}
|
||||
|
||||
return totl;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
srt_t* srt;
|
||||
caption_frame_t frame;
|
||||
char frame_buf[CAPTION_FRAME_DUMP_BUF_SIZE];
|
||||
|
||||
if (argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* file = fopen (argv[1],"r");
|
||||
|
||||
if (! file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
utf8_char_t* data = malloc (MAX_SRT_SIZE);
|
||||
size_t size = read_file (file,data,MAX_SRT_SIZE);
|
||||
srt_t* head = srt_parse (data,size);
|
||||
vtt_dump (head);
|
||||
srt_free (head);
|
||||
}
|
||||
71
deps/libcaption/examples/srtdump.c
vendored
Normal file
71
deps/libcaption/examples/srtdump.c
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "srt.h"
|
||||
#include "avc.h"
|
||||
// #include "sei.h"
|
||||
|
||||
#define MAX_SRT_SIZE (10*1024*1024)
|
||||
#define MAX_READ_SIZE 4096
|
||||
|
||||
size_t read_file (FILE* file, utf8_char_t* data, size_t size)
|
||||
{
|
||||
size_t read, totl = 0;
|
||||
|
||||
while (0 < (read = fread (data,1,MAX_READ_SIZE<size?MAX_READ_SIZE:size,file))) {
|
||||
totl += read; data += read; size -= read;
|
||||
}
|
||||
|
||||
return totl;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
srt_t* srt;
|
||||
caption_frame_t frame;
|
||||
|
||||
if (argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* file = fopen (argv[1],"r");
|
||||
|
||||
if (! file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
utf8_char_t* data = (utf8_char_t*) malloc (MAX_SRT_SIZE);
|
||||
size_t size = read_file (file,data,MAX_SRT_SIZE);
|
||||
srt_t* head = srt_parse (data,size);
|
||||
|
||||
for (srt = head ; srt ; srt = srt->next) {
|
||||
caption_frame_init (&frame);
|
||||
srt_to_caption_frame (srt,&frame);
|
||||
caption_frame_dump (&frame);
|
||||
}
|
||||
|
||||
srt_free (head);
|
||||
}
|
||||
117
deps/libcaption/examples/ts.c
vendored
Normal file
117
deps/libcaption/examples/ts.c
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "ts.h"
|
||||
#include <string.h>
|
||||
|
||||
void ts_init (ts_t* ts)
|
||||
{
|
||||
memset (ts,0,sizeof (ts_t));
|
||||
}
|
||||
|
||||
static int64_t ts_parse_pts (const uint8_t* data)
|
||||
{
|
||||
// 0000 1110 1111 1111 1111 1110 1111 1111 1111 1110
|
||||
uint64_t pts = 0;
|
||||
pts |= (uint64_t) (data[0] & 0x0E) << 29;
|
||||
pts |= (uint64_t) (data[1] & 0xFF) << 22;
|
||||
pts |= (uint64_t) (data[2] & 0xFE) << 14;
|
||||
pts |= (uint64_t) (data[3] & 0xFF) << 7;
|
||||
pts |= (uint64_t) (data[4] & 0xFE) >> 1;
|
||||
return pts;
|
||||
}
|
||||
|
||||
int ts_parse_packet (ts_t* ts, const uint8_t* data)
|
||||
{
|
||||
size_t i = 0;
|
||||
int pusi = !! (data[i + 1] & 0x40); // Payload Unit Start Indicator
|
||||
int16_t pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2]; // PID
|
||||
int adaption_present = !! (data[i + 3] & 0x20); // Adaptation field exist
|
||||
int payload_present = !! (data[i + 3] & 0x10); // Contains payload
|
||||
i += 4;
|
||||
|
||||
ts->data = 0;
|
||||
ts->size = 0;
|
||||
|
||||
if (adaption_present) {
|
||||
uint8_t adaption_length = data[i + 0]; // adaption field length
|
||||
i += 1 + adaption_length;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
if (payload_present) {
|
||||
// Skip the payload.
|
||||
i += data[i] + 1;
|
||||
}
|
||||
|
||||
ts->pmtpid = ( (data[i + 10] & 0x1F) << 8) | data[i + 11];
|
||||
} else if (pid == ts->pmtpid) {
|
||||
// PMT
|
||||
if (payload_present) {
|
||||
// Skip the payload.
|
||||
i += data[i] + 1;
|
||||
}
|
||||
|
||||
uint16_t section_length = ( (data[i + 1] & 0x0F) << 8) | data[i + 2];
|
||||
int current = data[i + 5] & 0x01;
|
||||
int16_t program_info_length = ( (data[i + 10] & 0x0F) << 8) | data[i + 11];
|
||||
int16_t descriptor_loop_length = section_length - (9 + program_info_length + 4); // 4 for the crc
|
||||
|
||||
i += 12 + program_info_length;
|
||||
|
||||
if (current) {
|
||||
while (descriptor_loop_length >= 5) {
|
||||
uint8_t stream_type = data[i];
|
||||
int16_t elementary_pid = ( (data[i + 1] & 0x1F) << 8) | data[i + 2];
|
||||
int16_t esinfo_length = ( (data[i + 3] & 0x0F) << 8) | data[i + 4];
|
||||
|
||||
if (0x1B == stream_type) {
|
||||
ts->avcpid = elementary_pid;
|
||||
}
|
||||
|
||||
i += 5 + esinfo_length;
|
||||
descriptor_loop_length -= 5 + esinfo_length;
|
||||
}
|
||||
}
|
||||
} else if (payload_present && pid == ts->avcpid) {
|
||||
if (pusi) {
|
||||
// int data_alignment = !! (data[i + 6] & 0x04);
|
||||
int has_pts = !! (data[i + 7] & 0x80);
|
||||
int has_dts = !! (data[i + 7] & 0x40);
|
||||
uint8_t header_length = data[i + 8];
|
||||
|
||||
if (has_pts) {
|
||||
ts->pts = ts_parse_pts (&data[i + 9]);
|
||||
ts->dts = has_dts ? ts_parse_pts (&data[i + 14]) : ts->pts;
|
||||
}
|
||||
|
||||
i += 9 + header_length;
|
||||
}
|
||||
|
||||
ts->data = &data[i];
|
||||
ts->size = TS_PACKET_SIZE-i;
|
||||
return LIBCAPTION_READY;
|
||||
}
|
||||
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
49
deps/libcaption/examples/ts.h
vendored
Normal file
49
deps/libcaption/examples/ts.h
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#ifndef LIBCAPTION_TS_H
|
||||
#define LIBCAPTION_TS_H
|
||||
#include "caption.h"
|
||||
typedef struct {
|
||||
int16_t pmtpid;
|
||||
int16_t avcpid;
|
||||
int64_t pts;
|
||||
int64_t dts;
|
||||
size_t size;
|
||||
const uint8_t* data;
|
||||
} ts_t;
|
||||
|
||||
/*! \brief
|
||||
\param
|
||||
|
||||
Expects 188 byte TS packet
|
||||
*/
|
||||
#define TS_PACKET_SIZE 188
|
||||
void ts_init (ts_t* ts);
|
||||
int ts_parse_packet (ts_t* ts, const uint8_t* data);
|
||||
// return timestamp in seconds
|
||||
static inline double ts_dts_seconds (ts_t* ts) { return ts->dts / 90000.0; }
|
||||
static inline double ts_pts_seconds (ts_t* ts) { return ts->pts / 90000.0; }
|
||||
static inline double ts_cts_seconds (ts_t* ts) { return (ts->dts - ts->pts) / 90000.0; }
|
||||
|
||||
#endif
|
||||
101
deps/libcaption/examples/ts2srt.c
vendored
Normal file
101
deps/libcaption/examples/ts2srt.c
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2016 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "ts.h"
|
||||
#include "srt.h"
|
||||
#include "avc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
const char* path = argv[1];
|
||||
|
||||
ts_t ts;
|
||||
sei_t sei;
|
||||
avcnalu_t nalu;
|
||||
srt_t* srt = 0, *head = 0;
|
||||
caption_frame_t frame;
|
||||
uint8_t pkt[TS_PACKET_SIZE];
|
||||
ts_init (&ts);
|
||||
avcnalu_init (&nalu);
|
||||
caption_frame_init (&frame);
|
||||
|
||||
FILE* file = fopen (path,"rb+");
|
||||
|
||||
while (TS_PACKET_SIZE == fread (&pkt[0],1,TS_PACKET_SIZE, file)) {
|
||||
switch (ts_parse_packet (&ts,&pkt[0])) {
|
||||
case LIBCAPTION_OK:
|
||||
// fprintf (stderr,"read ts packet\n");
|
||||
break;
|
||||
|
||||
case LIBCAPTION_READY: {
|
||||
// fprintf (stderr,"read ts packet DATA\n");
|
||||
while (ts.size) {
|
||||
// fprintf (stderr,"ts.size %d (%02X%02X%02X%02X)\n",ts.size, ts.data[0], ts.data[1], ts.data[2], ts.data[3]);
|
||||
|
||||
switch (avcnalu_parse_annexb (&nalu, &ts.data, &ts.size)) {
|
||||
case LIBCAPTION_OK:
|
||||
break;
|
||||
|
||||
case LIBCAPTION_ERROR:
|
||||
// fprintf (stderr,"LIBCAPTION_ERROR == avcnalu_parse_annexb()\n");
|
||||
avcnalu_init (&nalu);
|
||||
break;
|
||||
|
||||
case LIBCAPTION_READY: {
|
||||
|
||||
if (6 == avcnalu_type (&nalu)) {
|
||||
// fprintf (stderr,"NALU %d (%d)\n", avcnalu_type (&nalu), avcnalu_size (&nalu));
|
||||
sei_init (&sei);
|
||||
sei_parse_avcnalu (&sei, &nalu, ts_dts_seconds (&ts), ts_cts_seconds (&ts));
|
||||
|
||||
// sei_dump (&sei);
|
||||
|
||||
if (LIBCAPTION_READY == sei_to_caption_frame (&sei,&frame)) {
|
||||
// caption_frame_dump (&frame);
|
||||
srt = srt_from_caption_frame (&frame,srt,&head);
|
||||
|
||||
// srt_dump (srt);
|
||||
}
|
||||
|
||||
sei_free (&sei);
|
||||
}
|
||||
|
||||
avcnalu_init (&nalu);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case LIBCAPTION_ERROR:
|
||||
// fprintf (stderr,"read ts packet ERROR\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
srt_dump (head);
|
||||
srt_free (head);
|
||||
|
||||
return 1;
|
||||
}
|
||||
2794
deps/libcaption/examples/wonderland.h
vendored
Normal file
2794
deps/libcaption/examples/wonderland.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue