2 * Copyright (c) 2015 Ludmila Glinskih
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * draw_horiz_band test.
27 #include "libavutil/adler32.h"
28 #include "libavutil/mem.h"
29 #include "libavcodec/avcodec.h"
30 #include "libavformat/avformat.h"
31 #include "libavutil/imgutils.h"
33 uint8_t *slice_byte_buffer
;
34 int draw_horiz_band_called
;
36 static void draw_horiz_band(AVCodecContext
*ctx
, const AVFrame
*fr
, int offset
[4],
37 int slice_position
, int type
, int height
)
40 const AVPixFmtDescriptor
*pix_fmt_desc
;
41 int chroma_w
, chroma_h
;
42 int shift_slice_position
;
45 draw_horiz_band_called
= 1;
47 pix_fmt_desc
= av_pix_fmt_desc_get(ctx
->pix_fmt
);
48 chroma_w
= -((-ctx
->width
) >> pix_fmt_desc
->log2_chroma_w
);
49 chroma_h
= -((-height
) >> pix_fmt_desc
->log2_chroma_h
);
50 shift_slice_position
= -((-slice_position
) >> pix_fmt_desc
->log2_chroma_h
);
51 shift_height
= -((-ctx
->height
) >> pix_fmt_desc
->log2_chroma_h
);
53 for (i
= 0; i
< height
; i
++) {
54 memcpy(slice_byte_buffer
+ ctx
->width
* slice_position
+ i
* ctx
->width
,
55 fr
->data
[0] + offset
[0] + i
* fr
->linesize
[0], ctx
->width
);
57 for (i
= 0; i
< chroma_h
; i
++) {
58 memcpy(slice_byte_buffer
+ ctx
->width
* ctx
->height
+ chroma_w
* shift_slice_position
+ i
* chroma_w
,
59 fr
->data
[1] + offset
[1] + i
* fr
->linesize
[1], chroma_w
);
61 for (i
= 0; i
< chroma_h
; i
++) {
62 memcpy(slice_byte_buffer
+ ctx
->width
* ctx
->height
+ chroma_w
* shift_height
+ chroma_w
* shift_slice_position
+ i
* chroma_w
,
63 fr
->data
[2] + offset
[2] + i
* fr
->linesize
[2], chroma_w
);
67 static int video_decode(const char *input_filename
)
69 const AVCodec
*codec
= NULL
;
70 AVCodecContext
*ctx
= NULL
;
71 AVCodecParameters
*origin_par
= NULL
;
72 uint8_t *byte_buffer
= NULL
;
75 AVFormatContext
*fmt_ctx
= NULL
;
76 int number_of_written_bytes
;
81 draw_horiz_band_called
= 0;
83 result
= avformat_open_input(&fmt_ctx
, input_filename
, NULL
, NULL
);
85 av_log(NULL
, AV_LOG_ERROR
, "Can't open file\n");
89 result
= avformat_find_stream_info(fmt_ctx
, NULL
);
91 av_log(NULL
, AV_LOG_ERROR
, "Can't get stream info\n");
95 video_stream
= av_find_best_stream(fmt_ctx
, AVMEDIA_TYPE_VIDEO
, -1, -1, NULL
, 0);
96 if (video_stream
< 0) {
97 av_log(NULL
, AV_LOG_ERROR
, "Can't find video stream in input file\n");
101 origin_par
= fmt_ctx
->streams
[video_stream
]->codecpar
;
103 codec
= avcodec_find_decoder(origin_par
->codec_id
);
105 av_log(NULL
, AV_LOG_ERROR
, "Can't find decoder\n");
109 if (!(codec
->capabilities
& AV_CODEC_CAP_DRAW_HORIZ_BAND
)) {
110 av_log(NULL
, AV_LOG_ERROR
, "Codec does not support draw_horiz_band\n");
114 ctx
= avcodec_alloc_context3(codec
);
116 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate decoder context\n");
117 return AVERROR(ENOMEM
);
120 result
= avcodec_parameters_to_context(ctx
, origin_par
);
122 av_log(NULL
, AV_LOG_ERROR
, "Can't copy decoder context\n");
126 ctx
->draw_horiz_band
= draw_horiz_band
;
127 ctx
->thread_count
= 1;
129 result
= avcodec_open2(ctx
, codec
, NULL
);
131 av_log(ctx
, AV_LOG_ERROR
, "Can't open decoder\n");
135 fr
= av_frame_alloc();
137 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate frame\n");
138 return AVERROR(ENOMEM
);
141 pkt
= av_packet_alloc();
143 av_log(NULL
, AV_LOG_ERROR
, "Cannot allocate packet\n");
144 return AVERROR(ENOMEM
);
147 byte_buffer_size
= av_image_get_buffer_size(ctx
->pix_fmt
, ctx
->width
, ctx
->height
, 32);
148 byte_buffer
= av_malloc(byte_buffer_size
);
150 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate buffer\n");
151 return AVERROR(ENOMEM
);
154 slice_byte_buffer
= av_malloc(byte_buffer_size
);
155 if (!slice_byte_buffer
) {
156 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate buffer\n");
157 return AVERROR(ENOMEM
);
159 memset(slice_byte_buffer
, 0, byte_buffer_size
);
162 while (result
>= 0) {
163 result
= av_read_frame(fmt_ctx
, pkt
);
164 if (result
>= 0 && pkt
->stream_index
!= video_stream
) {
165 av_packet_unref(pkt
);
169 // pkt will be empty on read error/EOF
170 result
= avcodec_send_packet(ctx
, pkt
);
172 av_packet_unref(pkt
);
175 av_log(NULL
, AV_LOG_ERROR
, "Error submitting a packet for decoding\n");
179 while (result
>= 0) {
180 result
= avcodec_receive_frame(ctx
, fr
);
181 if (result
== AVERROR_EOF
)
183 else if (result
== AVERROR(EAGAIN
)) {
186 } else if (result
< 0) {
187 av_log(NULL
, AV_LOG_ERROR
, "Error decoding frame\n");
191 number_of_written_bytes
= av_image_copy_to_buffer(byte_buffer
, byte_buffer_size
,
192 (const uint8_t* const *)fr
->data
, (const int*) fr
->linesize
,
193 ctx
->pix_fmt
, ctx
->width
, ctx
->height
, 1);
194 if (number_of_written_bytes
< 0) {
195 av_log(NULL
, AV_LOG_ERROR
, "Can't copy image to buffer\n");
196 return number_of_written_bytes
;
198 if (draw_horiz_band_called
== 0) {
199 av_log(NULL
, AV_LOG_ERROR
, "draw_horiz_band haven't been called!\n");
202 if (av_adler32_update(0, (const uint8_t*)byte_buffer
, number_of_written_bytes
) !=
203 av_adler32_update(0, (const uint8_t*)slice_byte_buffer
, number_of_written_bytes
)) {
204 av_log(NULL
, AV_LOG_ERROR
, "Decoded frames with and without draw_horiz_band are not the same!\n");
212 av_packet_free(&pkt
);
214 avformat_close_input(&fmt_ctx
);
215 avcodec_free_context(&ctx
);
216 av_freep(&byte_buffer
);
217 av_freep(&slice_byte_buffer
);
221 int main(int argc
, char **argv
)
225 av_log(NULL
, AV_LOG_ERROR
, "Incorrect input: expected %s <name of a video file>\n", argv
[0]);
229 if (video_decode(argv
[1]) != 0)