Re: [FFmpeg-devel] [PATCHv2 3/3] avformat/mpegtsenc: add support for service and provider names with utf8 encoding

2019-02-21 Thread Marton Balint



On Tue, 19 Feb 2019, Marton Balint wrote:




On Tue, 12 Feb 2019, Marton Balint wrote:


Signed-off-by: Marton Balint 
---
libavformat/mpegtsenc.c | 88 

+

1 file changed, 53 insertions(+), 35 deletions(-)


Ping, will push soon.



Pushed.

Regards,
Marton
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCHv2 3/3] avformat/mpegtsenc: add support for service and provider names with utf8 encoding

2019-02-19 Thread Marton Balint



On Tue, 12 Feb 2019, Marton Balint wrote:


Signed-off-by: Marton Balint 
---
libavformat/mpegtsenc.c | 88 +
1 file changed, 53 insertions(+), 35 deletions(-)


Ping, will push soon.

Regards,
Marton



diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 4470b7120c..523ac65d55 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -54,8 +54,8 @@ typedef struct MpegTSSection {
typedef struct MpegTSService {
MpegTSSection pmt; /* MPEG-2 PMT table context */
int sid;   /* service ID */
-char *name;
-char *provider_name;
+uint8_t name[256];
+uint8_t provider_name[256];
int pcr_pid;
int pcr_packet_count;
int pcr_packet_period;
@@ -264,26 +264,10 @@ static void mpegts_write_pat(AVFormatContext *s)
  data, q - data);
}

-/* NOTE: !str is accepted for an empty string */
-static void putstr8(uint8_t **q_ptr, const char *str, int write_len)
+static void putbuf(uint8_t **q_ptr, const uint8_t *buf, int len)
{
-uint8_t *q;
-int len;
-
-q = *q_ptr;
-if (!str)
-len = 0;
-else
-len = strlen(str);
-if (write_len)
-*q++ = len;
-if (!str) {
-*q_ptr = q;
-return;
-}
-memcpy(q, str, len);
-q += len;
-*q_ptr = q;
+memcpy(*q_ptr, buf, len);
+*q_ptr += len;
}

static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
@@ -646,9 +630,9 @@ static int mpegts_write_pmt(AVFormatContext *s, 
MpegTSService *service)
*q++ = 0x26; /* metadata descriptor */
*q++ = 13;
put16(, 0x);/* metadata application format */
-putstr8(, tag, 0);
+putbuf(, tag, strlen(tag));
*q++ = 0xff;/* metadata format */
-putstr8(, tag, 0);
+putbuf(, tag, strlen(tag));
*q++ = 0;/* metadata service ID */
*q++ = 0xF;  /* 
metadata_locator_record_flag|MPEG_carriage_flags|reserved */
}
@@ -695,8 +679,8 @@ static void mpegts_write_sdt(AVFormatContext *s)
desc_len_ptr = q;
q++;
*q++ = ts->service_type;
-putstr8(, service->provider_name, 1);
-putstr8(, service->name, 1);
+putbuf(, service->provider_name, service->provider_name[0] + 1);
+putbuf(, service->name, service->name[0] + 1);
desc_len_ptr[0] = q - desc_len_ptr - 1;

/* fill descriptor length */
@@ -709,10 +693,47 @@ static void mpegts_write_sdt(AVFormatContext *s)
  data, q - data);
}

-static MpegTSService *mpegts_add_service(MpegTSWrite *ts, int sid,
+/* This stores a string in buf with the correct encoding and also sets the
+ * first byte as the length. !str is accepted for an empty string.
+ * If the string is already encoded, invalid UTF-8 or has no multibyte sequence
+ * then we keep it as is, otherwise we signal UTF-8 encoding. */
+static int encode_str8(uint8_t *buf, const char *str)
+{
+size_t str_len;
+if (!str)
+str = "";
+str_len = strlen(str);
+if (str[0] && (unsigned)str[0] >= 0x20) {   /* Make sure the string is not 
already encoded. */
+const uint8_t *q = str;
+int has_multibyte = 0;
+while (*q) {
+uint32_t code;
+GET_UTF8(code, *q++, goto invalid;) /* Is it valid UTF-8? */
+has_multibyte |= (code > 127);  /* Does it have multibyte 
UTF-8 chars in it? */
+}
+if (has_multibyte) {/* If we have multibyte chars 
and valid UTF-8, then encode as such! */
+if (str_len > 254)
+return AVERROR(EINVAL);
+buf[0] = str_len + 1;
+buf[1] = 0x15;
+memcpy([2], str, str_len);
+return 0;
+}
+}
+invalid:
+/* Otherwise let's just encode the string as is! */
+if (str_len > 255)
+return AVERROR(EINVAL);
+buf[0] = str_len;
+memcpy([1], str, str_len);
+return 0;
+}
+
+static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid,
 const char *provider_name,
 const char *name)
{
+MpegTSWrite *ts = s->priv_data;
MpegTSService *service;

service = av_mallocz(sizeof(MpegTSService));
@@ -721,17 +742,16 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts, 
int sid,
service->pmt.pid   = ts->pmt_start_pid + ts->nb_services;
service->sid   = sid;
service->pcr_pid   = 0x1fff;
-service->provider_name = av_strdup(provider_name);
-service->name  = av_strdup(name);
-if (!service->provider_name || !service->name)
+if (encode_str8(service->provider_name, provider_name) < 0 ||
+encode_str8(service->name, name) < 0) {
+av_log(s, AV_LOG_ERROR, "Too long service or provider 

[FFmpeg-devel] [PATCHv2 3/3] avformat/mpegtsenc: add support for service and provider names with utf8 encoding

2019-02-11 Thread Marton Balint
Signed-off-by: Marton Balint 
---
 libavformat/mpegtsenc.c | 88 +
 1 file changed, 53 insertions(+), 35 deletions(-)

diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 4470b7120c..523ac65d55 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -54,8 +54,8 @@ typedef struct MpegTSSection {
 typedef struct MpegTSService {
 MpegTSSection pmt; /* MPEG-2 PMT table context */
 int sid;   /* service ID */
-char *name;
-char *provider_name;
+uint8_t name[256];
+uint8_t provider_name[256];
 int pcr_pid;
 int pcr_packet_count;
 int pcr_packet_period;
@@ -264,26 +264,10 @@ static void mpegts_write_pat(AVFormatContext *s)
   data, q - data);
 }
 
-/* NOTE: !str is accepted for an empty string */
-static void putstr8(uint8_t **q_ptr, const char *str, int write_len)
+static void putbuf(uint8_t **q_ptr, const uint8_t *buf, int len)
 {
-uint8_t *q;
-int len;
-
-q = *q_ptr;
-if (!str)
-len = 0;
-else
-len = strlen(str);
-if (write_len)
-*q++ = len;
-if (!str) {
-*q_ptr = q;
-return;
-}
-memcpy(q, str, len);
-q += len;
-*q_ptr = q;
+memcpy(*q_ptr, buf, len);
+*q_ptr += len;
 }
 
 static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
@@ -646,9 +630,9 @@ static int mpegts_write_pmt(AVFormatContext *s, 
MpegTSService *service)
 *q++ = 0x26; /* metadata descriptor */
 *q++ = 13;
 put16(, 0x);/* metadata application format */
-putstr8(, tag, 0);
+putbuf(, tag, strlen(tag));
 *q++ = 0xff;/* metadata format */
-putstr8(, tag, 0);
+putbuf(, tag, strlen(tag));
 *q++ = 0;/* metadata service ID */
 *q++ = 0xF;  /* 
metadata_locator_record_flag|MPEG_carriage_flags|reserved */
 }
@@ -695,8 +679,8 @@ static void mpegts_write_sdt(AVFormatContext *s)
 desc_len_ptr = q;
 q++;
 *q++ = ts->service_type;
-putstr8(, service->provider_name, 1);
-putstr8(, service->name, 1);
+putbuf(, service->provider_name, service->provider_name[0] + 1);
+putbuf(, service->name, service->name[0] + 1);
 desc_len_ptr[0] = q - desc_len_ptr - 1;
 
 /* fill descriptor length */
@@ -709,10 +693,47 @@ static void mpegts_write_sdt(AVFormatContext *s)
   data, q - data);
 }
 
-static MpegTSService *mpegts_add_service(MpegTSWrite *ts, int sid,
+/* This stores a string in buf with the correct encoding and also sets the
+ * first byte as the length. !str is accepted for an empty string.
+ * If the string is already encoded, invalid UTF-8 or has no multibyte sequence
+ * then we keep it as is, otherwise we signal UTF-8 encoding. */
+static int encode_str8(uint8_t *buf, const char *str)
+{
+size_t str_len;
+if (!str)
+str = "";
+str_len = strlen(str);
+if (str[0] && (unsigned)str[0] >= 0x20) {   /* Make sure the string is not 
already encoded. */
+const uint8_t *q = str;
+int has_multibyte = 0;
+while (*q) {
+uint32_t code;
+GET_UTF8(code, *q++, goto invalid;) /* Is it valid UTF-8? */
+has_multibyte |= (code > 127);  /* Does it have multibyte 
UTF-8 chars in it? */
+}
+if (has_multibyte) {/* If we have multibyte chars 
and valid UTF-8, then encode as such! */
+if (str_len > 254)
+return AVERROR(EINVAL);
+buf[0] = str_len + 1;
+buf[1] = 0x15;
+memcpy([2], str, str_len);
+return 0;
+}
+}
+invalid:
+/* Otherwise let's just encode the string as is! */
+if (str_len > 255)
+return AVERROR(EINVAL);
+buf[0] = str_len;
+memcpy([1], str, str_len);
+return 0;
+}
+
+static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid,
  const char *provider_name,
  const char *name)
 {
+MpegTSWrite *ts = s->priv_data;
 MpegTSService *service;
 
 service = av_mallocz(sizeof(MpegTSService));
@@ -721,17 +742,16 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts, 
int sid,
 service->pmt.pid   = ts->pmt_start_pid + ts->nb_services;
 service->sid   = sid;
 service->pcr_pid   = 0x1fff;
-service->provider_name = av_strdup(provider_name);
-service->name  = av_strdup(name);
-if (!service->provider_name || !service->name)
+if (encode_str8(service->provider_name, provider_name) < 0 ||
+encode_str8(service->name, name) < 0) {
+av_log(s, AV_LOG_ERROR, "Too long service or provider name\n");
 goto fail;
+}
 if