+/**
+ * Encodes and outputs the entire frame in the JPEG format.
+ *
+ * @param s The MpegEncContext.
+ */
+void ff_mjpeg_encode_picture_frame(MpegEncContext *s)
+{
+ int i, nbits, code, table_id;
+ MJpegContext *m = s->mjpeg_ctx;
+ uint8_t *huff_size[4] = {m->huff_size_dc_luminance,
+ m->huff_size_dc_chrominance,
+ m->huff_size_ac_luminance,
+ m->huff_size_ac_chrominance};
+ uint16_t *huff_code[4] = {m->huff_code_dc_luminance,
+ m->huff_code_dc_chrominance,
+ m->huff_code_ac_luminance,
+ m->huff_code_ac_chrominance};
+ size_t total_bits = 0;
+ size_t bytes_needed;
+
+ s->header_bits = get_bits_diff(s);
+ // Estimate the total size first
+ for (i = 0; i < m->huff_ncode; i++) {
+ table_id = m->huff_buffer[i].table_id;
+ code = m->huff_buffer[i].code;
+ nbits = code & 0xf;
+
+ total_bits += huff_size[table_id][code] + nbits;
+ }
+
+ bytes_needed = (total_bits + 7) / 8;
+ ff_mpv_reallocate_putbitbuffer(s, bytes_needed, bytes_needed);
+
+ for (i = 0; i < m->huff_ncode; i++) {
+ table_id = m->huff_buffer[i].table_id;
+ code = m->huff_buffer[i].code;
+ nbits = code & 0xf;
+
+ put_bits(&s->pb, huff_size[table_id][code], huff_code[table_id][code]);
+ if (nbits != 0) {
+ put_sbits(&s->pb, nbits, m->huff_buffer[i].mant);
+ }
+ }
+
+ m->huff_ncode = 0;
+ s->i_tex_bits = get_bits_diff(s);
+}
+
+/**
+ * Add code and table_id to the JPEG buffer.
+ *
+ * @param s The MJpegContext which contains the JPEG buffer.
+ * @param table_id Which Huffman table the code belongs to.
+ * @param code The encoded exponent of the coefficients and the run-bits.
+ */
+static inline void ff_mjpeg_encode_code(MJpegContext *s, uint8_t table_id, int code)
+{
+ MJpegHuffmanCode *c = &s->huff_buffer[s->huff_ncode++];
+ c->table_id = table_id;
+ c->code = code;
+}
+
+/**
+ * Add the coefficient's data to the JPEG buffer.
+ *
+ * @param s The MJpegContext which contains the JPEG buffer.
+ * @param table_id Which Huffman table the code belongs to.
+ * @param val The coefficient.
+ * @param run The run-bits.
+ */
+static void ff_mjpeg_encode_coef(MJpegContext *s, uint8_t table_id, int val, int run)
+{
+ int mant, code;
+
+ if (val == 0) {
+ av_assert0(run == 0);
+ ff_mjpeg_encode_code(s, table_id, 0);
+ } else {
+ mant = val;
+ if (val < 0) {
+ val = -val;
+ mant--;
+ }
+
+ code = (run << 4) | (av_log2_16bit(val) + 1);
+
+ s->huff_buffer[s->huff_ncode].mant = mant;
+ ff_mjpeg_encode_code(s, table_id, code);
+ }
+}
+
+/**
+ * Add the block's data into the JPEG buffer.
+ *
+ * @param s The MJpegEncContext that contains the JPEG buffer.
+ * @param block The block.
+ * @param n The block's index or number.
+ */
+static void record_block(MpegEncContext *s, int16_t *block, int n)
+{
+ int i, j, table_id;
+ int component, dc, last_index, val, run;
+ MJpegContext *m = s->mjpeg_ctx;
+
+ /* DC coef */
+ component = (n <= 3 ? 0 : (n&1) + 1);
+ table_id = (n <= 3 ? 0 : 1);
+ dc = block[0]; /* overflow is impossible */
+ val = dc - s->last_dc[component];
+
+ ff_mjpeg_encode_coef(m, table_id, val, 0);
+
+ s->last_dc[component] = dc;
+
+ /* AC coefs */
+
+ run = 0;
+ last_index = s->block_last_index[n];
+ table_id |= 2;
+
+ for(i=1;i<=last_index;i++) {
+ j = s->intra_scantable.permutated[i];
+ val = block[j];
+
+ if (val == 0) {
+ run++;
+ } else {
+ while (run >= 16) {
+ ff_mjpeg_encode_code(m, table_id, 0xf0);
+ run -= 16;
+ }
+ ff_mjpeg_encode_coef(m, table_id, val, run);
+ run = 0;
+ }
+ }
+
+ /* output EOB only if not already 64 values */
+ if (last_index < 63 || run != 0)
+ ff_mjpeg_encode_code(m, table_id, 0);
+}
+