Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavcodec
msrle.c
Go to the documentation of this file.
1
/*
2
* Microsoft RLE video decoder
3
* Copyright (C) 2003 the ffmpeg project
4
*
5
* This file is part of Libav.
6
*
7
* Libav is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* Libav is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
35
#include "
avcodec.h
"
36
#include "
dsputil.h
"
37
#include "
msrledec.h
"
38
39
typedef
struct
MsrleContext
{
40
AVCodecContext
*
avctx
;
41
AVFrame
frame
;
42
43
const
unsigned
char
*
buf
;
44
int
size
;
45
46
uint32_t
pal
[256];
47
}
MsrleContext
;
48
49
static
av_cold
int
msrle_decode_init
(
AVCodecContext
*avctx)
50
{
51
MsrleContext
*s = avctx->
priv_data
;
52
53
s->
avctx
= avctx;
54
55
switch
(avctx->
bits_per_coded_sample
) {
56
case
4:
57
case
8:
58
avctx->
pix_fmt
=
PIX_FMT_PAL8
;
59
break
;
60
case
24:
61
avctx->
pix_fmt
=
PIX_FMT_BGR24
;
62
break
;
63
default
:
64
av_log
(avctx,
AV_LOG_ERROR
,
"unsupported bits per sample\n"
);
65
return
-1;
66
}
67
68
s->
frame
.
data
[0] =
NULL
;
69
70
return
0;
71
}
72
73
static
int
msrle_decode_frame
(
AVCodecContext
*avctx,
74
void
*
data
,
int
*data_size,
75
AVPacket
*avpkt)
76
{
77
const
uint8_t *buf = avpkt->
data
;
78
int
buf_size = avpkt->
size
;
79
MsrleContext
*s = avctx->
priv_data
;
80
int
istride =
FFALIGN
(avctx->
width
*avctx->
bits_per_coded_sample
, 32) / 8;
81
82
s->
buf
= buf;
83
s->
size
= buf_size;
84
85
s->
frame
.
reference
= 1;
86
s->
frame
.
buffer_hints
=
FF_BUFFER_HINTS_VALID
|
FF_BUFFER_HINTS_PRESERVE
|
FF_BUFFER_HINTS_REUSABLE
;
87
if
(avctx->
reget_buffer
(avctx, &s->
frame
)) {
88
av_log
(avctx,
AV_LOG_ERROR
,
"reget_buffer() failed\n"
);
89
return
-1;
90
}
91
92
if
(avctx->
bits_per_coded_sample
<= 8) {
93
const
uint8_t *pal =
av_packet_get_side_data
(avpkt,
AV_PKT_DATA_PALETTE
,
NULL
);
94
95
if
(pal) {
96
s->
frame
.
palette_has_changed
= 1;
97
memcpy(s->
pal
, pal,
AVPALETTE_SIZE
);
98
}
99
100
/* make the palette available */
101
memcpy(s->
frame
.
data
[1], s->
pal
,
AVPALETTE_SIZE
);
102
}
103
104
/* FIXME how to correctly detect RLE ??? */
105
if
(avctx->
height
* istride == avpkt->
size
) {
/* assume uncompressed */
106
int
linesize = avctx->
width
* avctx->
bits_per_coded_sample
/ 8;
107
uint8_t *ptr = s->
frame
.
data
[0];
108
uint8_t *buf = avpkt->
data
+ (avctx->
height
-1)*istride;
109
int
i, j;
110
111
for
(i = 0; i < avctx->
height
; i++) {
112
if
(avctx->
bits_per_coded_sample
== 4) {
113
for
(j = 0; j < avctx->
width
- 1; j += 2) {
114
ptr[j+0] = buf[j>>1] >> 4;
115
ptr[j+1] = buf[j>>1] & 0xF;
116
}
117
if
(avctx->
width
& 1)
118
ptr[j+0] = buf[j>>1] >> 4;
119
}
else
{
120
memcpy(ptr, buf, linesize);
121
}
122
buf -= istride;
123
ptr += s->
frame
.
linesize
[0];
124
}
125
}
else
{
126
ff_msrle_decode
(avctx, (
AVPicture
*)&s->
frame
, avctx->
bits_per_coded_sample
, buf, buf_size);
127
}
128
129
*data_size =
sizeof
(
AVFrame
);
130
*(
AVFrame
*)data = s->
frame
;
131
132
/* report that the buffer was completely consumed */
133
return
buf_size;
134
}
135
136
static
av_cold
int
msrle_decode_end
(
AVCodecContext
*avctx)
137
{
138
MsrleContext
*s = avctx->
priv_data
;
139
140
/* release the last frame */
141
if
(s->
frame
.
data
[0])
142
avctx->
release_buffer
(avctx, &s->
frame
);
143
144
return
0;
145
}
146
147
AVCodec
ff_msrle_decoder
= {
148
.
name
=
"msrle"
,
149
.type =
AVMEDIA_TYPE_VIDEO
,
150
.id =
CODEC_ID_MSRLE
,
151
.priv_data_size =
sizeof
(
MsrleContext
),
152
.
init
=
msrle_decode_init
,
153
.
close
=
msrle_decode_end
,
154
.
decode
=
msrle_decode_frame
,
155
.capabilities =
CODEC_CAP_DR1
,
156
.long_name=
NULL_IF_CONFIG_SMALL
(
"Microsoft RLE"
),
157
};