| @@ -28,6 +28,7 @@ · 27 unmodified lines |
| 28 | 28 | #include "libavcodec/mpeg4audio.h" |
| 29 | 29 | #include "avio.h" |
| 30 | 30 | #include "avc.h" |
| 31 | +#include "hevc.h" |
| 31 | 32 | #include "avformat.h" |
| 32 | 33 | #include "flv.h" |
| 33 | 34 | #include "internal.h" |
| @@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = { · 12 unmodified lines |
| 46 | 47 | { AV_CODEC_ID_VP6, FLV_CODECID_VP6 }, |
| 47 | 48 | { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A }, |
| 48 | 49 | { AV_CODEC_ID_H264, FLV_CODECID_H264 }, |
| 50 | + { AV_CODEC_ID_HEVC, MKBETAG('h', 'v', 'c', '1') }, |
| 49 | 51 | { AV_CODEC_ID_NONE, 0 } |
| 50 | 52 | }; |
| 51 | 53 | |
| @@ -489,7 +491,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i · 437 unmodified lines |
| 489 | 491 | FLVContext *flv = s->priv_data; |
| 490 | 492 | |
| 491 | 493 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 |
| 492 | | − || par->codec_id == AV_CODEC_ID_MPEG4) { |
| 494 | + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { |
| 493 | 495 | int64_t pos; |
| 494 | 496 | avio_w8(pb, |
| 495 | 497 | par->codec_type == AVMEDIA_TYPE_VIDEO ? |
| @@ -532,10 +534,19 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i · 36 unmodified lines |
| 532 | 534 | } |
| 533 | 535 | avio_write(pb, par->extradata, par->extradata_size); |
| 534 | 536 | } else { |
| 535 | | − avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags |
| 536 | | − avio_w8(pb, 0); // AVC sequence header |
| 537 | | − avio_wb24(pb, 0); // composition time |
| 538 | | − ff_isom_write_avcc(pb, par->extradata, par->extradata_size); |
| 537 | + if (par->codec_id == AV_CODEC_ID_HEVC) { |
| 538 | + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); // ExVideoTagHeader mode with PacketTypeSequenceStart |
| 539 | + avio_write(pb, "hvc1", 4); |
| 540 | + } else { |
| 541 | + avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags |
| 542 | + avio_w8(pb, 0); // AVC sequence header |
| 543 | + avio_wb24(pb, 0); // composition time |
| 544 | + } |
| 545 | + |
| 546 | + if (par->codec_id == AV_CODEC_ID_HEVC) |
| 547 | + ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); |
| 548 | + else |
| 549 | + ff_isom_write_avcc(pb, par->extradata, par->extradata_size); |
| 539 | 550 | } |
| 540 | 551 | data_size = avio_tell(pb) - pos; |
| 541 | 552 | avio_seek(pb, -data_size - 10, SEEK_CUR); |
| @@ -821,6 +832,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 279 unmodified lines |
| 821 | 832 | unsigned ts; |
| 822 | 833 | int size = pkt->size; |
| 823 | 834 | uint8_t *data = NULL; |
| 835 | + uint8_t frametype = pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; |
| 824 | 836 | int flags = -1, flags_size, ret = 0; |
| 825 | 837 | int64_t cur_offset = avio_tell(pb); |
| 826 | 838 | |
| @@ -832,13 +844,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 5 unmodified lines |
| 832 | 844 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A || |
| 833 | 845 | par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC) |
| 834 | 846 | flags_size = 2; |
| 835 | | − else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) |
| 847 | + else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) |
| 836 | 848 | flags_size = 5; |
| 837 | 849 | else |
| 838 | 850 | flags_size = 1; |
| 839 | 851 | |
| 840 | 852 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 |
| 841 | | − || par->codec_id == AV_CODEC_ID_MPEG4) { |
| 853 | + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { |
| 842 | 854 | size_t side_size; |
| 843 | 855 | uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); |
| 844 | 856 | if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { |
| @@ -858,7 +870,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 13 unmodified lines |
| 858 | 870 | "Packets are not in the proper order with respect to DTS\n"); |
| 859 | 871 | return AVERROR(EINVAL); |
| 860 | 872 | } |
| 861 | | − if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { |
| 873 | + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { |
| 862 | 874 | if (pkt->pts == AV_NOPTS_VALUE) { |
| 863 | 875 | av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); |
| 864 | 876 | return AVERROR(EINVAL); |
| @@ -881,7 +893,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 16 unmodified lines |
| 881 | 893 | |
| 882 | 894 | flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id); |
| 883 | 895 | |
| 884 | | − flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; |
| 896 | + flags |= frametype; |
| 885 | 897 | break; |
| 886 | 898 | case AVMEDIA_TYPE_AUDIO: |
| 887 | 899 | flags = get_audio_flags(s, par); |
| @@ -903,6 +915,10 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 15 unmodified lines |
| 903 | 915 | if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) |
| 904 | 916 | if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0) |
| 905 | 917 | return ret; |
| 918 | + } else if (par->codec_id == AV_CODEC_ID_HEVC) { |
| 919 | + if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) |
| 920 | + if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0) |
| 921 | + return ret; |
| 906 | 922 | } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && |
| 907 | 923 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { |
| 908 | 924 | if (!s->streams[pkt->stream_index]->nb_frames) { |
| @@ -964,7 +980,12 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) · 55 unmodified lines |
| 964 | 980 | avio_wb32(pb, data_size + 11); |
| 965 | 981 | } else { |
| 966 | 982 | av_assert1(flags>=0); |
| 967 | | − avio_w8(pb,flags); |
| 983 | + if (par->codec_id == AV_CODEC_ID_HEVC) { |
| 984 | + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFramesX | frametype); // ExVideoTagHeader mode with PacketTypeCodedFramesX |
| 985 | + avio_write(pb, "hvc1", 4); |
| 986 | + } else { |
| 987 | + avio_w8(pb, flags); |
| 988 | + } |
| 968 | 989 | if (par->codec_id == AV_CODEC_ID_VP6) |
| 969 | 990 | avio_w8(pb,0); |
| 970 | 991 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) { |