[FFmpeg-devel,v2] avformat/smoothstreamingenc:add bitrate calculate

Submitted by Jun Li on March 7, 2019, 7:55 p.m.

Details

Message ID 20190307195540.29436-1-junli1026@gmail.com
State New
Headers show

Commit Message

Jun Li March 7, 2019, 7:55 p.m.
From: jun <junli1026@gmail.com>

Calculate bitrate based on fragment size, only applied when
bitrate is not set, for example rtsp source.

Signed-off-by: Jun Li <junli1026@gmail.com>
---
 libavformat/smoothstreamingenc.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

Comments

Jun Li March 11, 2019, 4:03 a.m.
ping.

On Thu, Mar 7, 2019 at 11:55 AM Jun Li <junli1026@gmail.com> wrote:

> From: jun <junli1026@gmail.com>
>
> Calculate bitrate based on fragment size, only applied when
> bitrate is not set, for example rtsp source.
>
> Signed-off-by: Jun Li <junli1026@gmail.com>
> ---
>  libavformat/smoothstreamingenc.c | 30 +++++++++++++++++++++++++-----
>  1 file changed, 25 insertions(+), 5 deletions(-)
>
> diff --git a/libavformat/smoothstreamingenc.c
> b/libavformat/smoothstreamingenc.c
> index 094712af27..75a47a9668 100644
> --- a/libavformat/smoothstreamingenc.c
> +++ b/libavformat/smoothstreamingenc.c
> @@ -320,11 +320,12 @@ static int ism_write_header(AVFormatContext *s)
>          AVDictionary *opts = NULL;
>
>          if (!s->streams[i]->codecpar->bit_rate) {
> -            av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i);
> -            ret = AVERROR(EINVAL);
> -            goto fail;
> +            av_log(s, AV_LOG_WARNING, "No bit rate set for stream %d\n",
> i);
> +            snprintf(os->dirname, sizeof(os->dirname),
> "%s/QualityLevels(Tmp_%"PRId64")", s->url, i);
> +        } else {
> +            snprintf(os->dirname, sizeof(os->dirname),
> "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
>          }
> -        snprintf(os->dirname, sizeof(os->dirname),
> "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
> +
>          if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
>              ret = AVERROR(errno);
>              av_log(s, AV_LOG_ERROR, "mkdir failed\n");
> @@ -519,7 +520,7 @@ static int ism_flush(AVFormatContext *s, int final)
>
>      for (i = 0; i < s->nb_streams; i++) {
>          OutputStream *os = &c->streams[i];
> -        char filename[1024], target_filename[1024], header_filename[1024];
> +        char filename[1024], target_filename[1024],
> header_filename[1024], curr_dirname[1024];
>          int64_t size;
>          int64_t start_ts, duration, moof_size;
>          if (!os->packets_written)
> @@ -541,6 +542,25 @@ static int ism_flush(AVFormatContext *s, int final)
>          size = os->tail_pos - os->cur_start_pos;
>          if ((ret = parse_fragment(s, filename, &start_ts, &duration,
> &moof_size, size)) < 0)
>              break;
> +
> +        if (!s->streams[i]->codecpar->bit_rate) {
> +            int64_t bitrate = (int64_t) size * 8 * AV_TIME_BASE /
> av_rescale_q(duration, s->streams[i]->time_base, AV_TIME_BASE_Q);
> +            if (!bitrate) {
> +                av_log(s, AV_LOG_ERROR, "calculating bitrate get zero.");
> +                ret = AVERROR(EINVAL);
> +                return ret;
> +            }
> +
> +            av_log(s, AV_LOG_WARNING, "calculated bitrate: %ld\n",
> bitrate);
> +            s->streams[i]->codecpar->bit_rate = bitrate;
> +            memcpy(curr_dirname, os->dirname, sizeof(os->dirname));
> +            snprintf(os->dirname, sizeof(os->dirname),
> "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
> +            snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
> +
> +            if ((ret = ff_rename((const char*)curr_dirname,  os->dirname,
> s)) < 0)
> +                return ret;
> +        }
> +
>          snprintf(header_filename, sizeof(header_filename),
> "%s/FragmentInfo(%s=%"PRIu64")", os->dirname, os->stream_type_tag,
> start_ts);
>          snprintf(target_filename, sizeof(target_filename),
> "%s/Fragments(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
>          copy_moof(s, filename, header_filename, moof_size);
> --
> 2.17.1
>
>
Carl Eugen Hoyos March 11, 2019, 9:03 a.m.
2019-03-07 20:55 GMT+01:00, Jun Li <junli1026@gmail.com>:
> From: jun <junli1026@gmail.com>
>
> Calculate bitrate based on fragment size, only applied when
> bitrate is not set, for example rtsp source.

Could this also be done on a higher level?
Or is smoothstreaming the only thing that needs this information?

Carl Eugen
Jun Li March 11, 2019, 5:58 p.m.
Thanks Carl for review.
Smooth is not the only one need bitrate for manifest, Dash also need this
value for "Bandwidth" field:
https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L730
Although there is some difference, both the calculation are based on
fragment size, which is the result after muxing. So it might be very hard
to do it outside of Muxer.

Thanks. Regards
-Jun

On Mon, Mar 11, 2019 at 2:03 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:

> 2019-03-07 20:55 GMT+01:00, Jun Li <junli1026@gmail.com>:
> > From: jun <junli1026@gmail.com>
> >
> > Calculate bitrate based on fragment size, only applied when
> > bitrate is not set, for example rtsp source.
>
> Could this also be done on a higher level?
> Or is smoothstreaming the only thing that needs this information?
>
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Carl Eugen Hoyos March 11, 2019, 6:43 p.m.
2019-03-11 18:58 GMT+01:00, Jun Li <junli1026@gmail.com>:

> Smooth is not the only one need bitrate for manifest, Dash also need this
> value for "Bandwidth" field:
> https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L730
> Although there is some difference, both the calculation are based on
> fragment size, which is the result after muxing.

Thank you for the explanation!

Carl Eugen
Jun Li March 13, 2019, 1:24 a.m.
Hi Carl,
Thanks for review, is there any more issue I need to take care ?
or any process I need to follow before applying the patch? I am new to the
community, don't know too much.

Thanks
-Jun

On Mon, Mar 11, 2019 at 11:44 AM Carl Eugen Hoyos <ceffmpeg@gmail.com>
wrote:

> 2019-03-11 18:58 GMT+01:00, Jun Li <junli1026@gmail.com>:
>
> > Smooth is not the only one need bitrate for manifest, Dash also need this
> > value for "Bandwidth" field:
> > https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L730
> > Although there is some difference, both the calculation are based on
> > fragment size, which is the result after muxing.
>
> Thank you for the explanation!
>
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Jun Li March 14, 2019, 1:07 a.m.
On Tue, Mar 12, 2019 at 6:24 PM Jun Li <junli1026@gmail.com> wrote:

> Hi Carl,
> Thanks for review, is there any more issue I need to take care ?
> or any process I need to follow before applying the patch? I am new to the
> community, don't know too much.
>
> Thanks
> -Jun
>
> On Mon, Mar 11, 2019 at 11:44 AM Carl Eugen Hoyos <ceffmpeg@gmail.com>
> wrote:
>
>> 2019-03-11 18:58 GMT+01:00, Jun Li <junli1026@gmail.com>:
>>
>> > Smooth is not the only one need bitrate for manifest, Dash also need
>> this
>> > value for "Bandwidth" field:
>> > https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L730
>> > Although there is some difference, both the calculation are based on
>> > fragment size, which is the result after muxing.
>>
>> Thank you for the explanation!
>>
>> Carl Eugen
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>  pingx2
Jun Li March 14, 2019, 6:31 p.m.
On Wed, Mar 13, 2019 at 6:07 PM Jun Li <junli1026@gmail.com> wrote:

> On Tue, Mar 12, 2019 at 6:24 PM Jun Li <junli1026@gmail.com> wrote:
>
>> Hi Carl,
>> Thanks for review, is there any more issue I need to take care ?
>> or any process I need to follow before applying the patch? I am new to
>> the community, don't know too much.
>>
>> Thanks
>> -Jun
>>
>> On Mon, Mar 11, 2019 at 11:44 AM Carl Eugen Hoyos <ceffmpeg@gmail.com>
>> wrote:
>>
>>> 2019-03-11 18:58 GMT+01:00, Jun Li <junli1026@gmail.com>:
>>>
>>> > Smooth is not the only one need bitrate for manifest, Dash also need
>>> this
>>> > value for "Bandwidth" field:
>>> >
>>> https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L730
>>> > Although there is some difference, both the calculation are based on
>>> > fragment size, which is the result after muxing.
>>>
>>> Thank you for the explanation!
>>>
>>> Carl Eugen
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> version 3 is sent out with more comment:
https://patchwork.ffmpeg.org/patch/12307/

Patch hide | download patch | download mbox

diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index 094712af27..75a47a9668 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -320,11 +320,12 @@  static int ism_write_header(AVFormatContext *s)
         AVDictionary *opts = NULL;
 
         if (!s->streams[i]->codecpar->bit_rate) {
-            av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i);
-            ret = AVERROR(EINVAL);
-            goto fail;
+            av_log(s, AV_LOG_WARNING, "No bit rate set for stream %d\n", i);
+            snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(Tmp_%"PRId64")", s->url, i);
+        } else {
+            snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
         }
-        snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
+
         if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
             ret = AVERROR(errno);
             av_log(s, AV_LOG_ERROR, "mkdir failed\n");
@@ -519,7 +520,7 @@  static int ism_flush(AVFormatContext *s, int final)
 
     for (i = 0; i < s->nb_streams; i++) {
         OutputStream *os = &c->streams[i];
-        char filename[1024], target_filename[1024], header_filename[1024];
+        char filename[1024], target_filename[1024], header_filename[1024], curr_dirname[1024];
         int64_t size;
         int64_t start_ts, duration, moof_size;
         if (!os->packets_written)
@@ -541,6 +542,25 @@  static int ism_flush(AVFormatContext *s, int final)
         size = os->tail_pos - os->cur_start_pos;
         if ((ret = parse_fragment(s, filename, &start_ts, &duration, &moof_size, size)) < 0)
             break;
+
+        if (!s->streams[i]->codecpar->bit_rate) {
+            int64_t bitrate = (int64_t) size * 8 * AV_TIME_BASE / av_rescale_q(duration, s->streams[i]->time_base, AV_TIME_BASE_Q);
+            if (!bitrate) {
+                av_log(s, AV_LOG_ERROR, "calculating bitrate get zero.");
+                ret = AVERROR(EINVAL);
+                return ret;
+            }
+
+            av_log(s, AV_LOG_WARNING, "calculated bitrate: %ld\n", bitrate);
+            s->streams[i]->codecpar->bit_rate = bitrate;
+            memcpy(curr_dirname, os->dirname, sizeof(os->dirname));
+            snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
+            snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
+
+            if ((ret = ff_rename((const char*)curr_dirname,  os->dirname, s)) < 0)
+                return ret;
+        }
+
         snprintf(header_filename, sizeof(header_filename), "%s/FragmentInfo(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
         snprintf(target_filename, sizeof(target_filename), "%s/Fragments(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
         copy_moof(s, filename, header_filename, moof_size);