Message ID | 20190211235345.3812-1-cus@passwd.hu |
---|---|
State | New |
Headers | show |
On Tue, 12 Feb 2019, Marton Balint wrote: > Signed-off-by: Marton Balint <cus@passwd.hu> > --- > 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(&q, 0xffff); /* metadata application format */ > - putstr8(&q, tag, 0); > + putbuf(&q, tag, strlen(tag)); > *q++ = 0xff; /* metadata format */ > - putstr8(&q, tag, 0); > + putbuf(&q, 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(&q, service->provider_name, 1); > - putstr8(&q, service->name, 1); > + putbuf(&q, service->provider_name, service->provider_name[0] + 1); > + putbuf(&q, 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(&buf[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(&buf[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 (av_dynarray_add_nofree(&ts->services, &ts->nb_services, service) < 0) > goto fail; > > return service; > fail: > - av_freep(&service->provider_name); > - av_freep(&service->name); > av_free(service); > return NULL; > } > @@ -790,7 +810,7 @@ static int mpegts_init(AVFormatContext *s) > service_name = title ? title->value : DEFAULT_SERVICE_NAME; > provider = av_dict_get(s->metadata, "service_provider", NULL, 0); > provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; > - service = mpegts_add_service(ts, ts->service_id, > + service = mpegts_add_service(s, ts->service_id, > provider_name, service_name); > > if (!service) > @@ -809,7 +829,7 @@ static int mpegts_init(AVFormatContext *s) > service_name = title ? title->value : DEFAULT_SERVICE_NAME; > provider = av_dict_get(program->metadata, "service_provider", NULL, 0); > provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; > - service = mpegts_add_service(ts, program->id, > + service = mpegts_add_service(s, program->id, > provider_name, service_name); > > if (!service) > @@ -1839,8 +1859,6 @@ static void mpegts_deinit(AVFormatContext *s) > > for (i = 0; i < ts->nb_services; i++) { > service = ts->services[i]; > - av_freep(&service->provider_name); > - av_freep(&service->name); > av_freep(&service); > } > av_freep(&ts->services); > -- > 2.16.4 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
On Tue, 19 Feb 2019, Marton Balint wrote: > > > On Tue, 12 Feb 2019, Marton Balint wrote: > >> Signed-off-by: Marton Balint <cus@passwd.hu> >> --- >> libavformat/mpegtsenc.c | 88 > +++++++++++++++++++++++++++++-------------------- >> 1 file changed, 53 insertions(+), 35 deletions(-) > > Ping, will push soon. > Pushed. 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(&q, 0xffff); /* metadata application format */ - putstr8(&q, tag, 0); + putbuf(&q, tag, strlen(tag)); *q++ = 0xff; /* metadata format */ - putstr8(&q, tag, 0); + putbuf(&q, 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(&q, service->provider_name, 1); - putstr8(&q, service->name, 1); + putbuf(&q, service->provider_name, service->provider_name[0] + 1); + putbuf(&q, 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(&buf[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(&buf[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 (av_dynarray_add_nofree(&ts->services, &ts->nb_services, service) < 0) goto fail; return service; fail: - av_freep(&service->provider_name); - av_freep(&service->name); av_free(service); return NULL; } @@ -790,7 +810,7 @@ static int mpegts_init(AVFormatContext *s) service_name = title ? title->value : DEFAULT_SERVICE_NAME; provider = av_dict_get(s->metadata, "service_provider", NULL, 0); provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; - service = mpegts_add_service(ts, ts->service_id, + service = mpegts_add_service(s, ts->service_id, provider_name, service_name); if (!service) @@ -809,7 +829,7 @@ static int mpegts_init(AVFormatContext *s) service_name = title ? title->value : DEFAULT_SERVICE_NAME; provider = av_dict_get(program->metadata, "service_provider", NULL, 0); provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; - service = mpegts_add_service(ts, program->id, + service = mpegts_add_service(s, program->id, provider_name, service_name); if (!service) @@ -1839,8 +1859,6 @@ static void mpegts_deinit(AVFormatContext *s) for (i = 0; i < ts->nb_services; i++) { service = ts->services[i]; - av_freep(&service->provider_name); - av_freep(&service->name); av_freep(&service); } av_freep(&ts->services);
Signed-off-by: Marton Balint <cus@passwd.hu> --- libavformat/mpegtsenc.c | 88 +++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 35 deletions(-)