You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
avformat/srtdec: UTF-16 support
This commit is contained in:
@@ -31,20 +31,21 @@ typedef struct {
|
|||||||
|
|
||||||
static int srt_probe(AVProbeData *p)
|
static int srt_probe(AVProbeData *p)
|
||||||
{
|
{
|
||||||
const unsigned char *ptr = p->buf;
|
|
||||||
int i, v, num = 0;
|
int i, v, num = 0;
|
||||||
|
FFTextReader tr;
|
||||||
|
|
||||||
if (AV_RB24(ptr) == 0xEFBBBF)
|
ff_text_init_buf(&tr, p->buf, p->buf_size);
|
||||||
ptr += 3; /* skip UTF-8 BOM */
|
|
||||||
|
|
||||||
while (*ptr == '\r' || *ptr == '\n')
|
while (ff_text_peek_r8(&tr) == '\r' || ff_text_peek_r8(&tr) == '\n')
|
||||||
ptr++;
|
ff_text_r8(&tr);
|
||||||
for (i=0; i<2; i++) {
|
for (i=0; i<2; i++) {
|
||||||
|
char buf[128];
|
||||||
|
if (ff_subtitles_read_line(&tr, buf, sizeof(buf)) < 0)
|
||||||
|
break;
|
||||||
if ((num == i || num + 1 == i)
|
if ((num == i || num + 1 == i)
|
||||||
&& sscanf(ptr, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1)
|
&& sscanf(buf, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1)
|
||||||
return AVPROBE_SCORE_MAX;
|
return AVPROBE_SCORE_MAX;
|
||||||
num = atoi(ptr);
|
num = atoi(buf);
|
||||||
ptr += ff_subtitles_next_line(ptr);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -79,6 +80,8 @@ static int srt_read_header(AVFormatContext *s)
|
|||||||
AVBPrint buf;
|
AVBPrint buf;
|
||||||
AVStream *st = avformat_new_stream(s, NULL);
|
AVStream *st = avformat_new_stream(s, NULL);
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
FFTextReader tr;
|
||||||
|
ff_text_init_avio(&tr, s->pb);
|
||||||
|
|
||||||
if (!st)
|
if (!st)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
@@ -88,11 +91,11 @@ static int srt_read_header(AVFormatContext *s)
|
|||||||
|
|
||||||
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
|
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
|
||||||
|
|
||||||
while (!avio_feof(s->pb)) {
|
while (!ff_text_eof(&tr)) {
|
||||||
ff_subtitles_read_chunk(s->pb, &buf);
|
ff_subtitles_read_text_chunk(&tr, &buf);
|
||||||
|
|
||||||
if (buf.len) {
|
if (buf.len) {
|
||||||
int64_t pos = avio_tell(s->pb);
|
int64_t pos = ff_text_pos(&tr);
|
||||||
int64_t pts;
|
int64_t pts;
|
||||||
int duration;
|
int duration;
|
||||||
const char *ptr = buf.str;
|
const char *ptr = buf.str;
|
||||||
|
@@ -86,6 +86,25 @@ void ff_text_read(FFTextReader *r, char *buf, size_t size)
|
|||||||
*buf++ = ff_text_r8(r);
|
*buf++ = ff_text_r8(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_text_eof(FFTextReader *r)
|
||||||
|
{
|
||||||
|
return r->buf_pos >= r->buf_len && avio_feof(r->pb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_text_peek_r8(FFTextReader *r)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
if (r->buf_pos < r->buf_len)
|
||||||
|
return r->buf[r->buf_pos];
|
||||||
|
c = ff_text_r8(r);
|
||||||
|
if (!avio_feof(r->pb)) {
|
||||||
|
r->buf_pos = 0;
|
||||||
|
r->buf_len = 1;
|
||||||
|
r->buf[0] = c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
|
AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
|
||||||
const uint8_t *event, int len, int merge)
|
const uint8_t *event, int len, int merge)
|
||||||
{
|
{
|
||||||
@@ -303,7 +322,7 @@ static inline int is_eol(char c)
|
|||||||
return c == '\r' || c == '\n';
|
return c == '\r' || c == '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
|
void ff_subtitles_read_text_chunk(FFTextReader *tr, AVBPrint *buf)
|
||||||
{
|
{
|
||||||
char eol_buf[5], last_was_cr = 0;
|
char eol_buf[5], last_was_cr = 0;
|
||||||
int n = 0, i = 0, nb_eol = 0;
|
int n = 0, i = 0, nb_eol = 0;
|
||||||
@@ -311,7 +330,7 @@ void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
|
|||||||
av_bprint_clear(buf);
|
av_bprint_clear(buf);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = avio_r8(pb);
|
char c = ff_text_r8(tr);
|
||||||
|
|
||||||
if (!c)
|
if (!c)
|
||||||
break;
|
break;
|
||||||
@@ -344,3 +363,33 @@ void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
|
||||||
|
{
|
||||||
|
FFTextReader tr;
|
||||||
|
tr.buf_pos = tr.buf_len = 0;
|
||||||
|
tr.type = 0;
|
||||||
|
tr.pb = pb;
|
||||||
|
ff_subtitles_read_text_chunk(&tr, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
size_t cur = 0;
|
||||||
|
if (!size)
|
||||||
|
return 0;
|
||||||
|
while (cur + 1 < size) {
|
||||||
|
unsigned char c = ff_text_r8(tr);
|
||||||
|
if (!c)
|
||||||
|
return ff_text_eof(tr) ? cur : AVERROR_INVALIDDATA;
|
||||||
|
if (c == '\r' || c == '\n')
|
||||||
|
break;
|
||||||
|
buf[cur++] = c;
|
||||||
|
buf[cur] = '\0';
|
||||||
|
}
|
||||||
|
if (ff_text_peek_r8(tr) == '\r')
|
||||||
|
ff_text_r8(tr);
|
||||||
|
if (ff_text_peek_r8(tr) == '\n')
|
||||||
|
ff_text_r8(tr);
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#define AVFORMAT_SUBTITLES_H
|
#define AVFORMAT_SUBTITLES_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "libavutil/bprint.h"
|
#include "libavutil/bprint.h"
|
||||||
|
|
||||||
@@ -80,6 +81,16 @@ int64_t ff_text_pos(FFTextReader *r);
|
|||||||
*/
|
*/
|
||||||
int ff_text_r8(FFTextReader *r);
|
int ff_text_r8(FFTextReader *r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return non-zero if EOF was reached.
|
||||||
|
*/
|
||||||
|
int ff_text_eof(FFTextReader *r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like ff_text_r8(), but don't remove the byte from the buffer.
|
||||||
|
*/
|
||||||
|
int ff_text_peek_r8(FFTextReader *r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the given number of bytes (in UTF-8). On error or EOF, \0 bytes are
|
* Read the given number of bytes (in UTF-8). On error or EOF, \0 bytes are
|
||||||
* written.
|
* written.
|
||||||
@@ -144,19 +155,24 @@ int ff_smil_extract_next_chunk(AVIOContext *pb, AVBPrint *buf, char *c);
|
|||||||
const char *ff_smil_get_attr_ptr(const char *s, const char *attr);
|
const char *ff_smil_get_attr_ptr(const char *s, const char *attr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read a subtitles chunk.
|
* @brief Same as ff_subtitles_read_text_chunk(), but read from an AVIOContext.
|
||||||
|
*/
|
||||||
|
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a subtitles chunk from FFTextReader.
|
||||||
*
|
*
|
||||||
* A chunk is defined by a multiline "event", ending with a second line break.
|
* A chunk is defined by a multiline "event", ending with a second line break.
|
||||||
* The trailing line breaks are trimmed. CRLF are supported.
|
* The trailing line breaks are trimmed. CRLF are supported.
|
||||||
* Example: "foo\r\nbar\r\n\r\nnext" will print "foo\r\nbar" into buf, and pb
|
* Example: "foo\r\nbar\r\n\r\nnext" will print "foo\r\nbar" into buf, and pb
|
||||||
* will focus on the 'n' of the "next" string.
|
* will focus on the 'n' of the "next" string.
|
||||||
*
|
*
|
||||||
* @param pb I/O context
|
* @param tr I/O context
|
||||||
* @param buf an initialized buf where the chunk is written
|
* @param buf an initialized buf where the chunk is written
|
||||||
*
|
*
|
||||||
* @note buf is cleared before writing into it.
|
* @note buf is cleared before writing into it.
|
||||||
*/
|
*/
|
||||||
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf);
|
void ff_subtitles_read_text_chunk(FFTextReader *tr, AVBPrint *buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of characters to increment to jump to the next line, or to
|
* Get the number of characters to increment to jump to the next line, or to
|
||||||
@@ -177,4 +193,16 @@ static av_always_inline int ff_subtitles_next_line(const char *ptr)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a line of text. Discards line ending characters.
|
||||||
|
* The function handles the following line breaks schemes:
|
||||||
|
* LF, CRLF (MS), or standalone CR (old MacOS).
|
||||||
|
*
|
||||||
|
* Returns the number of bytes written to buf. Always writes a terminating 0,
|
||||||
|
* similar as with snprintf.
|
||||||
|
*
|
||||||
|
* @note returns a negative error code if a \0 byte is found
|
||||||
|
*/
|
||||||
|
ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size);
|
||||||
|
|
||||||
#endif /* AVFORMAT_SUBTITLES_H */
|
#endif /* AVFORMAT_SUBTITLES_H */
|
||||||
|
Reference in New Issue
Block a user