New upstream version 18.0.1+dfsg1

This commit is contained in:
Sebastian Ramacher 2017-04-19 21:54:15 +02:00
parent 6efda2859e
commit f2cf6cce50
1337 changed files with 41178 additions and 84670 deletions

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff