Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/262 #31

Merged
merged 16 commits into from
Jun 20, 2018
Prev Previous commit
Next Next commit
out of order frame handeling in flv2srt
  • Loading branch information
Matthew Szatmary committed Jun 19, 2018
commit 2682de8796876a0bbca5b8a5eaef52501f328c3e
2 changes: 1 addition & 1 deletion caption/cea708.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ int cea708_add_cc_data(cea708_t* cea708, int valid, cea708_cc_type_t type, uint1
\param
*/
int cea708_render(cea708_t* cea708, uint8_t* data, size_t size);
/*! \brief sorts a vector of cea708_t objects by timestamp
/*! \brief
\param
*/
void cea708_dump(cea708_t* cea708);
Expand Down
27 changes: 12 additions & 15 deletions caption/mpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
/* THE SOFTWARE. */
/**********************************************************************************************/
#ifndef LIBCAPTION_AVC_H
#define LIBCAPTION_AVC_H
#ifndef LIBCAPTION_MPEG_H
#define LIBCAPTION_MPEG_H
#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -55,8 +55,14 @@ typedef struct {

void mpeg_bitstream_init(mpeg_bitstream_t* packet);
////////////////////////////////////////////////////////////////////////////////
// Returns number of bytes read;. zero is not an error
// TODO make convenience functions for flv/mp4
/*! \brief
\param
*/
size_t mpeg_bitstream_parse(mpeg_bitstream_t* packet, caption_frame_t* frame, const uint8_t* data, size_t size, unsigned stream_type, double dts, double cts);
/*! \brief
\param
*/
static inline libcaption_stauts_t mpeg_bitstream_status(mpeg_bitstream_t* packet) { return packet->status; }
/*! \brief
Flushes latent packets caused by out or order frames.
Expand All @@ -65,8 +71,6 @@ static inline libcaption_stauts_t mpeg_bitstream_status(mpeg_bitstream_t* packet
*/
size_t mpeg_bitstream_flush(mpeg_bitstream_t* packet, caption_frame_t* frame);
////////////////////////////////////////////////////////////////////////////////
int h262_parse(mpeg_bitstream_t* nalu, const uint8_t** data, size_t* size);
////////////////////////////////////////////////////////////////////////////////
typedef struct _sei_message_t sei_message_t;

typedef enum {
Expand Down Expand Up @@ -96,16 +100,15 @@ typedef enum {
////////////////////////////////////////////////////////////////////////////////
// time in seconds
typedef struct {
double dts;
double cts;
double timestamp;
sei_message_t* head;
sei_message_t* tail;
} sei_t;

/*! \brief
\param
*/
void sei_init(sei_t* sei);
void sei_init(sei_t* sei, double timestamp);
/*! \brief
\param
*/
Expand All @@ -121,13 +124,7 @@ void sei_message_append(sei_t* sei, sei_message_t* msg);
/*! \brief
\param
*/
static inline double sei_dts(sei_t* sei) { return sei->dts; }
static inline double sei_cts(sei_t* sei) { return sei->cts; }
static inline double sei_pts(sei_t* sei) { return sei->dts + sei->cts; }
/*! \brief
\param
*/
libcaption_stauts_t sei_parse(sei_t* sei, const uint8_t* data, size_t size, double dts, double cts);
libcaption_stauts_t sei_parse(sei_t* sei, const uint8_t* data, size_t size, double timestamp);
/*! \brief
\param
*/
Expand Down
6 changes: 3 additions & 3 deletions examples/flv.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ int flvtag_addsei(flvtag_t* tag, sei_t* sei)
}

sei_t new_sei;
sei_init(&new_sei);
sei_init(&new_sei, flvtag_pts(tag));
sei_cat(&new_sei, sei, 1);

flvtag_t new_tag;
Expand Down Expand Up @@ -386,7 +386,7 @@ int flvtag_addsei(flvtag_t* tag, sei_t* sei)
int flvtag_addcaption_text(flvtag_t* tag, const utf8_char_t* text)
{
sei_t sei;
sei_init(&sei);
sei_init(&sei, flvtag_pts(tag));

if (text) {
caption_frame_t frame;
Expand All @@ -405,7 +405,7 @@ int flvtag_addcaption_text(flvtag_t* tag, const utf8_char_t* text)
int flvtag_addcaption_scc(flvtag_t* tag, const scc_t* scc)
{
sei_t sei;
sei_init(&sei);
sei_init(&sei, flvtag_pts(tag));
sei_from_scc(&sei, scc);
int ret = flvtag_addsei(tag, &sei);
sei_free(&sei);
Expand Down
42 changes: 23 additions & 19 deletions examples/flv2srt.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,22 @@
#include "mpeg.h"
#include "flv.h"
#include "srt.h"
#include <stdlib.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;
int has_audio, has_video;
caption_frame_t frame;
mpeg_bitstream_t mpegbs;
const char* path = argv[1];

flvtag_init(&tag);
caption_frame_init(&frame);

mpeg_bitstream_init(&mpegbs);

FILE* flv = flv_open_read(path);
srt = srt_new();

Expand All @@ -54,24 +55,27 @@ int main(int argc, char** argv)
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;
size_t nalu_size = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
mpeg_bitstream_parse(&mpegbs, &frame, (const uint8_t*)"\0\0\1", 3, STREAM_TYPE_H264, flvtag_dts_seconds(&tag), flvtag_cts_seconds(&tag));
mpeg_bitstream_parse(&mpegbs, &frame, &data[LENGTH_SIZE], nalu_size, STREAM_TYPE_H264, flvtag_dts_seconds(&tag), flvtag_cts_seconds(&tag));
data += nalu_size + LENGTH_SIZE, size -= nalu_size + LENGTH_SIZE;
switch (mpeg_bitstream_status(&mpegbs)) {
default:
case LIBCAPTION_ERROR:
fprintf(stderr, "LIBCAPTION_ERROR == mpeg_bitstream_parse()\n");
mpeg_bitstream_init(&mpegbs);
return EXIT_FAILURE;
break;

if (6 == nalu_type) {
sei_init(&sei);
sei_parse(&sei, nalu_data, nalu_size, flvtag_dts_seconds(&tag), flvtag_cts_seconds(&tag));
// sei_dump(&sei);
case LIBCAPTION_OK:
break;

if (LIBCAPTION_READY == sei_to_caption_frame(&sei, &frame)) {
srt_cue_from_caption_frame(&frame, srt);
}
case LIBCAPTION_READY: {
caption_frame_dump(&frame);
srt_cue_from_caption_frame(&frame, srt);
} break;
} //switch

// caption_frame_dump(&frame);
sei_free(&sei);
}
}
}
}
Expand Down
1 change: 0 additions & 1 deletion examples/party.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ void write_amfcaptions_708(FILE* out, uint32_t timestamp, const char* text)
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);
Expand Down
2 changes: 1 addition & 1 deletion src/eia608_from_utf8.c.cached
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Generated by re2c 1.0.1 on Tue Jun 19 14:19:12 2018 */
/* Generated by re2c 1.0.1 on Tue Jun 19 14:55:23 2018 */
/**********************************************************************************************/
/* The MIT License */
/* */
Expand Down
31 changes: 14 additions & 17 deletions src/mpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,11 @@ sei_message_t* sei_message_new(sei_msgtype_t type, uint8_t* data, size_t size)
return (sei_message_t*)msg;
}
////////////////////////////////////////////////////////////////////////////////
void sei_init(sei_t* sei)
void sei_init(sei_t* sei, double timestamp)
{
sei->dts = -1;
sei->cts = -1;
sei->head = 0;
sei->tail = 0;
sei->timestamp = timestamp;
}

void sei_message_append(sei_t* sei, sei_message_t* msg)
Expand Down Expand Up @@ -212,13 +211,13 @@ void sei_free(sei_t* sei)
sei->head = tail;
}

sei_init(sei);
sei_init(sei,0);
}

void sei_dump(sei_t* sei)
{
fprintf(stderr, "SEI %p\n", sei);
sei_dump_messages(sei->head, sei->dts + sei->cts);
sei_dump_messages(sei->head, sei->timestamp);
}

void sei_dump_messages(sei_message_t* head, double timestamp)
Expand Down Expand Up @@ -329,11 +328,9 @@ uint8_t* sei_render_alloc(sei_t* sei, size_t* size)
}

////////////////////////////////////////////////////////////////////////////////
libcaption_stauts_t sei_parse(sei_t* sei, const uint8_t* data, size_t size, double dts, double cts)
libcaption_stauts_t sei_parse(sei_t* sei, const uint8_t* data, size_t size, double timestamp)
{
sei_init(sei);
sei->dts = dts;
sei->cts = cts;
sei_init(sei, timestamp);
int ret = 0;

// SEI may contain more than one payload
Expand Down Expand Up @@ -401,7 +398,7 @@ libcaption_stauts_t sei_to_caption_frame(sei_t* sei, caption_frame_t* frame)
}

if (LIBCAPTION_READY == status) {
frame->timestamp = sei_pts(sei);
frame->timestamp = sei->timestamp;
}

return status;
Expand All @@ -414,7 +411,7 @@ void sei_append_708(sei_t* sei, cea708_t* cea708)
sei_message_t* msg = sei_message_new(sei_type_user_data_registered_itu_t_t35, 0, CEA608_MAX_SIZE);
msg->size = cea708_render(cea708, sei_message_data(msg), sei_message_size(msg));
sei_message_append(sei, msg);
cea708_init(cea708, sei->dts + sei->cts); // will confgure using HLS compatiable defaults
cea708_init(cea708, sei->timestamp); // will confgure using HLS compatiable defaults
}

// This should be moved to 708.c
Expand Down Expand Up @@ -451,7 +448,8 @@ libcaption_stauts_t sei_from_caption_frame(sei_t* sei, caption_frame_t* frame)
uint16_t prev_cc_data;
eia608_style_t styl, prev_styl;

cea708_init(&cea708, sei->dts + sei->cts); // set up a new popon frame
sei_init(sei, frame->timestamp);
cea708_init(&cea708, frame->timestamp); // set up a new popon frame
cea708_add_cc_data(&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command(eia608_control_erase_non_displayed_memory, DEFAULT_CHANNEL));
cea708_add_cc_data(&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command(eia608_control_resume_caption_loading, DEFAULT_CHANNEL));

Expand Down Expand Up @@ -530,7 +528,7 @@ libcaption_stauts_t sei_from_caption_frame(sei_t* sei, caption_frame_t* frame)
}

sei_encode_eia608(sei, &cea708, 0); // flush
sei->dts = frame->timestamp; // assumes in order frames
sei->timestamp = frame->timestamp; // assumes in order frames
// sei_dump (sei);
return LIBCAPTION_OK;
}
Expand All @@ -539,7 +537,7 @@ libcaption_stauts_t sei_from_scc(sei_t* sei, const scc_t* scc)
{
unsigned int i;
cea708_t cea708;
cea708_init(&cea708, sei->dts + sei->cts); // set up a new popon frame
cea708_init(&cea708, sei->timestamp); // set up a new popon frame

for (i = 0; i < scc->cc_size; ++i) {
if (31 == cea708.user_data.cc_count) {
Expand All @@ -559,7 +557,7 @@ libcaption_stauts_t sei_from_scc(sei_t* sei, const scc_t* scc)
libcaption_stauts_t sei_from_caption_clear(sei_t* sei)
{
cea708_t cea708;
cea708_init(&cea708, sei->dts + sei->cts); // set up a new popon frame
cea708_init(&cea708, sei->timestamp); // set up a new popon frame
cea708_add_cc_data(&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command(eia608_control_end_of_caption, DEFAULT_CHANNEL));
cea708_add_cc_data(&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command(eia608_control_end_of_caption, DEFAULT_CHANNEL));
cea708_add_cc_data(&cea708, 1, cc_type_ntsc_cc_field_1, eia608_control_command(eia608_control_erase_non_displayed_memory, DEFAULT_CHANNEL));
Expand Down Expand Up @@ -712,8 +710,7 @@ size_t mpeg_bitstream_parse(mpeg_bitstream_t* packet, caption_frame_t* frame, co
case H265_SEI_PACKET:
header_size = STREAM_TYPE_H264 == stream_type ? 4 : STREAM_TYPE_H265 == stream_type ? 5 : 0;
if (header_size && scpos > header_size) {
sei_init(&sei);
packet->status = libcaption_status_update(packet->status, sei_parse(&sei, &packet->data[header_size], scpos - header_size, dts, cts));
packet->status = libcaption_status_update(packet->status, sei_parse(&sei, &packet->data[header_size], scpos - header_size, dts + cts));
for (sei_message_t* 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_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts);
Expand Down