FFmpeg
media100_to_mjpegb.c
Go to the documentation of this file.
1 /*
2  * Media 100 to MJPEGB bitstream filter
3  * Copyright (c) 2023 Paul B Mahol
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  * Media 100 to MJPEGB bitstream filter.
25  */
26 
27 #include "libavutil/intreadwrite.h"
28 #include "bsf.h"
29 #include "bsf_internal.h"
30 #include "bytestream.h"
31 
33 {
34  ctx->par_out->codec_id = AV_CODEC_ID_MJPEGB;
35  return 0;
36 }
37 
39 {
40  unsigned second_field_offset = 0;
41  unsigned next_field = 0;
42  unsigned dht_offset[2];
43  unsigned dqt_offset[2];
44  unsigned sod_offset[2];
45  unsigned sof_offset[2];
46  unsigned sos_offset[2];
47  unsigned field = 0;
48  GetByteContext gb;
49  PutByteContext pb;
50  AVPacket *in;
51  int ret;
52 
53  ret = ff_bsf_get_packet(ctx, &in);
54  if (ret < 0)
55  return ret;
56 
57  ret = av_new_packet(out, in->size + 1024);
58  if (ret < 0)
59  goto fail;
60 
61  bytestream2_init(&gb, in->data, in->size);
62  bytestream2_init_writer(&pb, out->data, out->size);
63 
64 second_field:
65  bytestream2_put_be32(&pb, 0);
66  bytestream2_put_be32(&pb, AV_RB32("mjpg"));
67  bytestream2_put_be32(&pb, 0);
68  bytestream2_put_be32(&pb, 0);
69  for (int i = 0; i < 6; i++)
70  bytestream2_put_be32(&pb, 0);
71 
72  sof_offset[field] = bytestream2_tell_p(&pb);
73  bytestream2_put_be16(&pb, 17);
74  bytestream2_put_byte(&pb, 8);
75  bytestream2_put_be16(&pb, ctx->par_in->height / 2);
76  bytestream2_put_be16(&pb, ctx->par_in->width);
77  bytestream2_put_byte(&pb, 3);
78  bytestream2_put_byte(&pb, 1);
79  bytestream2_put_byte(&pb, 0x21);
80  bytestream2_put_byte(&pb, 0);
81  bytestream2_put_byte(&pb, 2);
82  bytestream2_put_byte(&pb, 0x11);
83  bytestream2_put_byte(&pb, 1);
84  bytestream2_put_byte(&pb, 3);
85  bytestream2_put_byte(&pb, 0x11);
86  bytestream2_put_byte(&pb, 1);
87 
88  sos_offset[field] = bytestream2_tell_p(&pb);
89  bytestream2_put_be16(&pb, 12);
90  bytestream2_put_byte(&pb, 3);
91  bytestream2_put_byte(&pb, 1);
92  bytestream2_put_byte(&pb, 0);
93  bytestream2_put_byte(&pb, 2);
94  bytestream2_put_byte(&pb, 0x11);
95  bytestream2_put_byte(&pb, 3);
96  bytestream2_put_byte(&pb, 0x11);
97  bytestream2_put_byte(&pb, 0);
98  bytestream2_put_byte(&pb, 0);
99  bytestream2_put_byte(&pb, 0);
100 
101  dqt_offset[field] = bytestream2_tell_p(&pb);
102  bytestream2_put_be16(&pb, 132);
103  bytestream2_put_byte(&pb, 0);
104  bytestream2_skip(&gb, 4);
105  for (int i = 0; i < 64; i++)
106  bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
107  bytestream2_put_byte(&pb, 1);
108  for (int i = 0; i < 64; i++)
109  bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
110 
111  dht_offset[field] = 0;
112  sod_offset[field] = bytestream2_tell_p(&pb);
113 
114  for (int i = bytestream2_tell(&gb) + 8; next_field == 0 && i < in->size - 4; i++) {
115  if (AV_RB32(in->data + i) == 0x00000001) {
116  next_field = i;
117  break;
118  }
119  }
120 
121  bytestream2_skip(&gb, 8);
122  bytestream2_copy_buffer(&pb, &gb, next_field - bytestream2_tell(&gb));
123  bytestream2_put_be64(&pb, 0);
124 
125  if (field == 0) {
126  field = 1;
127  second_field_offset = bytestream2_tell_p(&pb);
128  next_field = in->size;
129  goto second_field;
130  }
131 
132  AV_WB32(out->data + 8, second_field_offset);
133  AV_WB32(out->data + 12, second_field_offset);
134  AV_WB32(out->data + 16, second_field_offset);
135  AV_WB32(out->data + 20, dqt_offset[0]);
136  AV_WB32(out->data + 24, dht_offset[0]);
137  AV_WB32(out->data + 28, sof_offset[0]);
138  AV_WB32(out->data + 32, sos_offset[0]);
139  AV_WB32(out->data + 36, sod_offset[0]);
140 
141  AV_WB32(out->data + second_field_offset + 8, bytestream2_tell_p(&pb) - second_field_offset);
142  AV_WB32(out->data + second_field_offset + 12, bytestream2_tell_p(&pb) - second_field_offset);
143  AV_WB32(out->data + second_field_offset + 16, 0);
144  AV_WB32(out->data + second_field_offset + 20, dqt_offset[1] - second_field_offset);
145  AV_WB32(out->data + second_field_offset + 24, dht_offset[1]);
146  AV_WB32(out->data + second_field_offset + 28, sof_offset[1] - second_field_offset);
147  AV_WB32(out->data + second_field_offset + 32, sos_offset[1] - second_field_offset);
148  AV_WB32(out->data + second_field_offset + 36, sod_offset[1] - second_field_offset);
149 
150  out->size = bytestream2_tell_p(&pb);
151  memset(out->data + out->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
152 
154  if (ret < 0)
155  goto fail;
156 
157 fail:
158  if (ret < 0)
160  av_packet_free(&in);
161  return ret;
162 }
163 
165  .p.name = "media100_to_mjpegb",
166  .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_MEDIA100, AV_CODEC_ID_NONE },
167  .init = init,
168  .filter = filter,
169 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:429
bsf_internal.h
ff_media100_to_mjpegb_bsf
const FFBitStreamFilter ff_media100_to_mjpegb_bsf
Definition: media100_to_mjpegb.c:164
out
FILE * out
Definition: movenc.c:55
GetByteContext
Definition: bytestream.h:33
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
AVPacket::data
uint8_t * data
Definition: packet.h:539
bytestream2_tell_p
static av_always_inline int bytestream2_tell_p(PutByteContext *p)
Definition: bytestream.h:197
AV_CODEC_ID_MEDIA100
@ AV_CODEC_ID_MEDIA100
Definition: codec_id.h:318
ff_bsf_get_packet
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
Definition: bsf.c:235
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
bsf.h
fail
#define fail()
Definition: checkasm.h:188
av_cold
#define av_cold
Definition: attributes.h:90
bytestream2_init_writer
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:147
intreadwrite.h
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: packet.c:98
ctx
AVFormatContext * ctx
Definition: movenc.c:49
field
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
Definition: writing_filters.txt:78
FFBitStreamFilter
Definition: bsf_internal.h:27
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
AV_CODEC_ID_MJPEGB
@ AV_CODEC_ID_MJPEGB
Definition: codec_id.h:60
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:415
PutByteContext
Definition: bytestream.h:37
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
AVPacket::size
int size
Definition: packet.h:540
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
init
static av_cold int init(AVBSFContext *ctx)
Definition: media100_to_mjpegb.c:32
av_packet_copy_props
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition: packet.c:392
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ret
ret
Definition: filter_design.txt:187
bytestream2_copy_buffer
static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, GetByteContext *g, unsigned int size)
Definition: bytestream.h:347
filter
static int filter(AVBSFContext *ctx, AVPacket *out)
Definition: media100_to_mjpegb.c:38
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
AVPacket
This structure stores compressed data.
Definition: packet.h:516
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137