bethsoftvideo.c
Go to the documentation of this file.
1 /*
2  * Bethesda VID video decoder
3  * Copyright (C) 2007 Nicholas Tung
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * @brief Bethesda Softworks VID Video Decoder
25  * @author Nicholas Tung [ntung (at. ntung com] (2007-03)
26  * @see http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
27  * @see http://www.svatopluk.com/andux/docs/dfvid.html
28  */
29 
30 #include "libavutil/common.h"
31 #include "avcodec.h"
32 #include "bethsoftvideo.h"
33 #include "bytestream.h"
34 #include "internal.h"
35 
36 typedef struct BethsoftvidContext {
40 
42 {
43  BethsoftvidContext *vid = avctx->priv_data;
45  avctx->pix_fmt = AV_PIX_FMT_PAL8;
46  return 0;
47 }
48 
50 {
51  uint32_t *palette = (uint32_t *)ctx->frame.data[1];
52  int a;
53 
54  if (bytestream2_get_bytes_left(&ctx->g) < 256*3)
55  return AVERROR_INVALIDDATA;
56 
57  for(a = 0; a < 256; a++){
58  palette[a] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->g) * 4;
59  palette[a] |= palette[a] >> 6 & 0x30303;
60  }
61  ctx->frame.palette_has_changed = 1;
62  return 0;
63 }
64 
66  void *data, int *got_frame,
67  AVPacket *avpkt)
68 {
69  BethsoftvidContext * vid = avctx->priv_data;
70  char block_type;
71  uint8_t * dst;
72  uint8_t * frame_end;
73  int remaining = avctx->width; // number of bytes remaining on a line
74  int wrap_to_next_line;
75  int code, ret;
76  int yoffset;
77 
78  if ((ret = ff_reget_buffer(avctx, &vid->frame)) < 0)
79  return ret;
80  wrap_to_next_line = vid->frame.linesize[0] - avctx->width;
81 
82  if (avpkt->side_data_elems > 0 &&
83  avpkt->side_data[0].type == AV_PKT_DATA_PALETTE) {
84  bytestream2_init(&vid->g, avpkt->side_data[0].data,
85  avpkt->side_data[0].size);
86  if ((ret = set_palette(vid)) < 0)
87  return ret;
88  }
89 
90  bytestream2_init(&vid->g, avpkt->data, avpkt->size);
91  dst = vid->frame.data[0];
92  frame_end = vid->frame.data[0] + vid->frame.linesize[0] * avctx->height;
93 
94  switch(block_type = bytestream2_get_byte(&vid->g)){
95  case PALETTE_BLOCK: {
96  *got_frame = 0;
97  if ((ret = set_palette(vid)) < 0) {
98  av_log(avctx, AV_LOG_ERROR, "error reading palette\n");
99  return ret;
100  }
101  return bytestream2_tell(&vid->g);
102  }
103  case VIDEO_YOFF_P_FRAME:
104  yoffset = bytestream2_get_le16(&vid->g);
105  if(yoffset >= avctx->height)
106  return AVERROR_INVALIDDATA;
107  dst += vid->frame.linesize[0] * yoffset;
108  }
109 
110  // main code
111  while((code = bytestream2_get_byte(&vid->g))){
112  int length = code & 0x7f;
113 
114  // copy any bytes starting at the current position, and ending at the frame width
115  while(length > remaining){
116  if(code < 0x80)
117  bytestream2_get_buffer(&vid->g, dst, remaining);
118  else if(block_type == VIDEO_I_FRAME)
119  memset(dst, bytestream2_peek_byte(&vid->g), remaining);
120  length -= remaining; // decrement the number of bytes to be copied
121  dst += remaining + wrap_to_next_line; // skip over extra bytes at end of frame
122  remaining = avctx->width;
123  if(dst == frame_end)
124  goto end;
125  }
126 
127  // copy any remaining bytes after / if line overflows
128  if(code < 0x80)
129  bytestream2_get_buffer(&vid->g, dst, length);
130  else if(block_type == VIDEO_I_FRAME)
131  memset(dst, bytestream2_get_byte(&vid->g), length);
132  remaining -= length;
133  dst += length;
134  }
135  end:
136 
137  if ((ret = av_frame_ref(data, &vid->frame)) < 0)
138  return ret;
139 
140  *got_frame = 1;
141 
142  return avpkt->size;
143 }
144 
146 {
147  BethsoftvidContext * vid = avctx->priv_data;
148  av_frame_unref(&vid->frame);
149  return 0;
150 }
151 
153  .name = "bethsoftvid",
154  .type = AVMEDIA_TYPE_VIDEO,
156  .priv_data_size = sizeof(BethsoftvidContext),
160  .capabilities = CODEC_CAP_DR1,
161  .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"),
162 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static av_always_inline unsigned int bytestream2_get_be24u(GetByteContext *g)
Definition: bytestream.h:90
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
AVCodec ff_bethsoftvid_decoder
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
#define av_cold
Definition: attributes.h:78
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
end end
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
uint8_t * data[8]
pointer to the picture/channel planes.
Definition: frame.h:87
#define U(x)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:258
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
void av_log(void *avcl, int level, const char *fmt,...)
Send the specified message to the log if the level is less than or equal to the current av_log_level...
Definition: log.c:246
const char * name
Name of the codec implementation.
static int bethsoftvid_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: bethsoftvideo.c:65
external API header
struct BethsoftvidContext BethsoftvidContext
static av_always_inline unsigned int bytestream2_get_le16(GetByteContext *g)
Definition: bytestream.h:87
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
Identical in function to av_frame_make_writable(), except it uses ff_get_buffer() to allocate the buf...
ret
Definition: avfilter.c:821
int width
picture width / height.
static av_always_inline unsigned int bytestream2_peek_byte(GetByteContext *g)
Definition: bytestream.h:92
static int set_palette(BethsoftvidContext *ctx)
Definition: bethsoftvideo.c:49
float a
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:183
or the Software in violation of any applicable export control laws in any jurisdiction Except as provided by mandatorily applicable UPF has no obligation to provide you with source code to the Software In the event Software contains any source code
static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx)
static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx)
Definition: bethsoftvideo.c:41
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void avcodec_get_frame_defaults(AVFrame *frame)
Set the fields of the given AVFrame to default values.
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:280
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:330
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
int palette
Definition: v4l.c:61
common internal api header.
common internal and external API header
int linesize[8]
For video, size in bytes of each picture line.
Definition: frame.h:101
struct AVPacket::@35 * side_data
Additional packet data that can be provided by the container.
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
enum AVPacketSideDataType type
const char int length
Definition: avisynth_c.h:668
This structure stores compressed data.
GetByteContext g
Definition: bethsoftvideo.c:38
static av_always_inline unsigned int bytestream2_get_byte(GetByteContext *g)
Definition: bytestream.h:92