]> git.sesse.net Git - ffmpeg/blob - libavcodec/hevc_parser.c
hevc: fixing TSCL_A_VIDYO_5 decoding output order(cherry picked from commit 19c5d9ed2...
[ffmpeg] / libavcodec / hevc_parser.c
1 /*
2  * HEVC Annex B format parser
3  *
4  * Copyright (C) 2012 - 2013 Guillaume Martres
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "libavutil/common.h"
24 #include "parser.h"
25 #include "hevc.h"
26
27 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
28
29 /**
30  * Find the end of the current frame in the bitstream.
31  * @return the position of the first byte of the next frame, or END_NOT_FOUND
32  */
33 static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, int buf_size)
34 {
35     int i;
36     ParseContext *pc = s->priv_data;
37
38     for (i = 0; i < buf_size; i++) {
39         int nut;
40
41         pc->state64 = (pc->state64 << 8) | buf[i];
42
43         if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE)
44             continue;
45
46         nut = (pc->state64 >> 2 * 8 + 1) & 0x3F;
47         // Beginning of access unit
48         if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX ||
49             (nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) {
50             if (pc->frame_start_found) {
51                 pc->frame_start_found = 0;
52                 return i - 5;
53             }
54         } else if (nut <= NAL_RASL_R ||
55                    (nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) {
56             int first_slice_segment_in_pic_flag = buf[i] >> 7;
57             if (first_slice_segment_in_pic_flag) {
58                 if (!pc->frame_start_found) {
59                     pc->frame_start_found = 1;
60                     s->key_frame = nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT;
61                 } else { // First slice of next frame found
62                     pc->frame_start_found = 0;
63                     return i - 5;
64                 }
65             }
66         }
67     }
68
69     return END_NOT_FOUND;
70 }
71
72 static int hevc_parse(AVCodecParserContext *s,
73                       AVCodecContext *avctx,
74                       const uint8_t **poutbuf, int *poutbuf_size,
75                       const uint8_t *buf, int buf_size)
76 {
77     int next;
78     ParseContext *pc = s->priv_data;
79
80     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
81         next = buf_size;
82     } else {
83         next = hevc_find_frame_end(s, buf, buf_size);
84         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
85             *poutbuf = NULL;
86             *poutbuf_size = 0;
87             return buf_size;
88         }
89     }
90
91     *poutbuf = buf;
92     *poutbuf_size = buf_size;
93     return next;
94 }
95
96 // Split after the parameter sets at the beginning of the stream if they exist.
97 static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
98 {
99     int i;
100     uint32_t state = -1;
101     int has_ps = 0;
102
103     for (i = 0; i < buf_size; i++) {
104         state = (state << 8) | buf[i];
105         if (((state >> 8) & 0xFFFFFF) == START_CODE) {
106             int nut = (state >> 1) & 0x3F;
107             if (nut >= NAL_VPS && nut <= NAL_PPS) {
108                 has_ps = 1;
109             } else if (has_ps) {
110                 return i - 3;
111             } else { // no parameter set at the beginning of the stream
112                 return 0;
113             }
114         }
115     }
116     return 0;
117 }
118
119 AVCodecParser ff_hevc_parser = {
120     .codec_ids      = { AV_CODEC_ID_HEVC },
121     .priv_data_size = sizeof(ParseContext),
122     .parser_parse   = hevc_parse,
123     .parser_close   = ff_parse_close,
124     .split          = hevc_split,
125 };