Discussion:
[Libav-user] streaming raw H.264 to HLS
Evan Odabashian
2018-10-09 00:38:21 UTC
Permalink
I'm trying to use libavformat to write a stream of H.264 data (coming from
the NvCodec API) directly (without re-encoding) to an HLS playlist. I'm
sending the packets returned by the encoder through av_parser_parse2 until
I get a complete frame, and then writing the resulting frame with
av_interleaved_write_frames. This is mostly working in that I get an m3u8
playlist + .ts segments that plays back successfully if it starts from the
first .ts segment (and can play through any number of subsequent segments).

I'm not able to start playback directly from any segment after the first
one however. Viewing the file details in Windows explorer for the first .ts
segment shows correct values for the frame dimensions, bitrate, and frame
rate. For all other segments however these values are wrong (and not
consistent from one file to the next). I'm pretty sure each new segment is
beginning on a keyframe (in that I see the new .ts file appear right after
the parser detects a keyframe and I write the output frame with
the AV_PKT_FLAG_KEY flag). I can change the segment duration to any value I
want (1 second, 10 seconds, etc) and see the same behavior I don't think
this is an issue with the incoming sample themselves.

Can anyone guess what might be the problem here, or have some ideas to try
and diagnose the problem further?

Thanks!
Evan
He Lei
2018-10-09 11:42:24 UTC
Permalink
Many frames are keyframes. such as SPS/PPS and I frames, If you generate the hls_list file yourself, and mux as ts file. It has to start with SPS and PPS, and then I frame;


Another way, you can mux as hls, that would be easier():
avformat_alloc_output_context2(&format_ctx, xxx, ¡°hls¡±, xxx);

and set the hls_list_size to 0:
av_opt_set_int(format_ctx, ¡°hls_list_size¡±, 0, 0);

If you want to format the list,also use av_opt_set.
This command tells you something you can set: ¡°ffmpeg -h muxer=hls¡±


LeiHe
***@hotmail.com<mailto:***@hotmail.com>



ÔÚ 2018Äê10ÔÂ9ÈÕ£¬ÉÏÎç8:38£¬Evan Odabashian <***@gmail.com<mailto:***@gmail.com>> ÐŽµÀ£º

I'm trying to use libavformat to write a stream of H.264 data (coming from the NvCodec API) directly (without re-encoding) to an HLS playlist. I'm sending the packets returned by the encoder through av_parser_parse2 until I get a complete frame, and then writing the resulting frame with av_interleaved_write_frames. This is mostly working in that I get an m3u8 playlist + .ts segments that plays back successfully if it starts from the first .ts segment (and can play through any number of subsequent segments).

I'm not able to start playback directly from any segment after the first one however. Viewing the file details in Windows explorer for the first .ts segment shows correct values for the frame dimensions, bitrate, and frame rate. For all other segments however these values are wrong (and not consistent from one file to the next). I'm pretty sure each new segment is beginning on a keyframe (in that I see the new .ts file appear right after the parser detects a keyframe and I write the output frame with the AV_PKT_FLAG_KEY flag). I can change the segment duration to any value I want (1 second, 10 seconds, etc) and see the same behavior I don't think this is an issue with the incoming sample themselves.

Can anyone guess what might be the problem here, or have some ideas to try and diagnose the problem further?
Evan Odabashian
2018-10-09 17:30:32 UTC
Permalink
Well that is basically what I'm doing already, using the built-in HLS muxer
not manually creating the ts segments and playlist. I'm using the h264
parser because the samples I'm receiving from nvenc are not complete frames
so I'm using the parser to assemble the full frames then give them to the
muxer via av_interleaved_write_frame.

Presumably the HLS muxer (which I believe is the code located in hlsenc.c
right?) knows how to build valid HLS segments so I can only assume I'm
misrepresenting something to it about the frames I'm providing.
Post by He Lei
Many frames are keyframes. such as SPS/PPS and I frames, If you generate
the hls_list file yourself, and mux as ts file. It has to start with SPS
and PPS, and then I frame;
avformat_alloc_output_context2(&format_ctx, xxx, “hls”, xxx);
av_opt_set_int(format_ctx, “hls_list_size”, 0, 0);
If you want to format the list,also use av_opt_set.
This command tells you something you can set: “ffmpeg -h muxer=hls”
LeiHe
I'm trying to use libavformat to write a stream of H.264 data (coming from
the NvCodec API) directly (without re-encoding) to an HLS playlist. I'm
sending the packets returned by the encoder through av_parser_parse2 until
I get a complete frame, and then writing the resulting frame with
av_interleaved_write_frames. This is mostly working in that I get an m3u8
playlist + .ts segments that plays back successfully if it starts from the
first .ts segment (and can play through any number of subsequent segments).
I'm not able to start playback directly from any segment after the first
one however. Viewing the file details in Windows explorer for the first .ts
segment shows correct values for the frame dimensions, bitrate, and frame
rate. For all other segments however these values are wrong (and not
consistent from one file to the next). I'm pretty sure each new segment is
beginning on a keyframe (in that I see the new .ts file appear right after
the parser detects a keyframe and I write the output frame with
the AV_PKT_FLAG_KEY flag). I can change the segment duration to any value I
want (1 second, 10 seconds, etc) and see the same behavior I don't think
this is an issue with the incoming sample themselves.
Can anyone guess what might be the problem here, or have some ideas to try
and diagnose the problem further?
_______________________________________________
Libav-user mailing list
http://ffmpeg.org/mailman/listinfo/libav-user
Evan Odabashian
2018-10-09 22:58:04 UTC
Permalink
It appears my problem was due to lack of IDR frames - playing the segments
with ffplay gave me some more error messages to google ;-) I was able to
get it working by forcing nvenc to emit an IDR frame at the beginning of
each GOP. I can't figure out if there's a way to tell from the parser
whether the current frame is an IDR frame or just a regular I frame though,
should this be possible to detect?
Post by Evan Odabashian
Well that is basically what I'm doing already, using the built-in HLS
muxer not manually creating the ts segments and playlist. I'm using the
h264 parser because the samples I'm receiving from nvenc are not complete
frames so I'm using the parser to assemble the full frames then give them
to the muxer via av_interleaved_write_frame.
Presumably the HLS muxer (which I believe is the code located in hlsenc.c
right?) knows how to build valid HLS segments so I can only assume I'm
misrepresenting something to it about the frames I'm providing.
Post by He Lei
Many frames are keyframes. such as SPS/PPS and I frames, If you generate
the hls_list file yourself, and mux as ts file. It has to start with SPS
and PPS, and then I frame;
avformat_alloc_output_context2(&format_ctx, xxx, “hls”, xxx);
av_opt_set_int(format_ctx, “hls_list_size”, 0, 0);
If you want to format the list,also use av_opt_set.
This command tells you something you can set: “ffmpeg -h muxer=hls”
LeiHe
I'm trying to use libavformat to write a stream of H.264 data (coming
from the NvCodec API) directly (without re-encoding) to an HLS playlist.
I'm sending the packets returned by the encoder through av_parser_parse2
until I get a complete frame, and then writing the resulting frame with
av_interleaved_write_frames. This is mostly working in that I get an m3u8
playlist + .ts segments that plays back successfully if it starts from the
first .ts segment (and can play through any number of subsequent segments).
I'm not able to start playback directly from any segment after the first
one however. Viewing the file details in Windows explorer for the first .ts
segment shows correct values for the frame dimensions, bitrate, and frame
rate. For all other segments however these values are wrong (and not
consistent from one file to the next). I'm pretty sure each new segment is
beginning on a keyframe (in that I see the new .ts file appear right after
the parser detects a keyframe and I write the output frame with
the AV_PKT_FLAG_KEY flag). I can change the segment duration to any value I
want (1 second, 10 seconds, etc) and see the same behavior I don't think
this is an issue with the incoming sample themselves.
Can anyone guess what might be the problem here, or have some ideas to
try and diagnose the problem further?
_______________________________________________
Libav-user mailing list
http://ffmpeg.org/mailman/listinfo/libav-user
He Lei
2018-10-10 04:08:10 UTC
Permalink
The first byte of each nalu is the header, and the lower 5 bits of this byte are of nalu type:

type_value = head_byte & 0x1F;

switch( type_value){
5: // idr.
7: //sps
8: //pps
}

LeiHe
***@hotmail.com<mailto:***@hotmail.com>



ÔÚ 2018Äê10ÔÂ10ÈÕ£¬ÉÏÎç6:58£¬Evan Odabashian <***@gmail.com<mailto:***@gmail.com>> ÐŽµÀ£º

It appears my problem was due to lack of IDR frames - playing the segments with ffplay gave me some more error messages to google ;-) I was able to get it working by forcing nvenc to emit an IDR frame at the beginning of each GOP. I can't figure out if there's a way to tell from the parser whether the current frame is an IDR frame or just a regular I frame though, should this be possible to detect?
Loading...