goto have_full_frame;
}
if (value == 0xd8) {
- /* Skip this frame if we found another SOI marker */
- GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
+ GST_DEBUG ("0x%08x: SOI marker before EOI marker", offset + 2);
+
+ /* clear parse state */
+ dec->saw_header = FALSE;
dec->parse_resync = FALSE;
- size = offset + 2;
- goto drop_frame;
+ toadd = offset;
+ goto have_full_frame;
}
gboolean need_unmap = TRUE;
GstVideoCodecState *state = NULL;
gboolean release_frame = TRUE;
+ gboolean has_eoi;
+ guint8 *data;
+ gsize nbytes;
- dec->current_frame = frame;
gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
+ data = dec->current_frame_map.data;
+ nbytes = dec->current_frame_map.size;
+ has_eoi = ((data[nbytes - 2] != 0xff) || (data[nbytes - 1] != 0xd9));
+
+ /* some cameras fail to send an end-of-image marker (EOI),
+ * add it if that is the case. */
+ if (!has_eoi) {
+ GstMapInfo map;
+ GstBuffer *eoibuf = gst_buffer_new_and_alloc (2);
+
+ /* unmap, will add EOI and remap at the end */
+ gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
+
+ gst_buffer_map (eoibuf, &map, GST_MAP_WRITE);
+ map.data[0] = 0xff;
+ map.data[1] = 0xd9;
+ gst_buffer_unmap (eoibuf, &map);
+
+ /* append to input buffer, and remap */
+ frame->input_buffer = gst_buffer_append (frame->input_buffer, eoibuf);
+
+ gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
+ GST_DEBUG ("fixup EOI marker added");
+ }
+
+ dec->current_frame = frame;
dec->cinfo.src->next_input_byte = dec->current_frame_map.data;
dec->cinfo.src->bytes_in_buffer = dec->current_frame_map.size;
/* is it interlaced MJPEG? (we really don't want to scan the jpeg data
* to see if there are two SOF markers in the packet to detect this) */
if (gst_video_decoder_get_packetized (bdec) &&
+ dec->input_state->info.height > height &&
dec->input_state->info.height <= (height * 2)
&& dec->input_state->info.width == width) {
GST_LOG_OBJECT (dec,
"looks like an interlaced image: "
"input width/height of %dx%d with JPEG frame width/height of %dx%d",
- dec->input_state->info.height, dec->input_state->info.width, width,
+ dec->input_state->info.width, dec->input_state->info.height, width,
height);
output_height = dec->input_state->info.height;
height = dec->input_state->info.height / 2;
break;
}
+ GST_LOG_OBJECT (dec,
+ "got for second field of interlaced image: "
+ "input width/height of %dx%d with JPEG frame width/height of %dx%d",
+ dec->input_state->info.width, dec->input_state->info.height,
+ dec->cinfo.output_width, dec->cinfo.output_height);
+
if (dec->cinfo.output_width != GST_VIDEO_INFO_WIDTH (&state->info) ||
- dec->cinfo.output_height * 2 > GST_VIDEO_INFO_HEIGHT (&state->info) ||
+ GST_VIDEO_INFO_HEIGHT (&state->info) <= dec->cinfo.output_height ||
+ GST_VIDEO_INFO_HEIGHT (&state->info) > (dec->cinfo.output_height * 2) ||
field2_format != GST_VIDEO_INFO_FORMAT (&state->info)) {
GST_WARNING_OBJECT (dec, "second field has different format than first");
gst_video_frame_unmap (&vframe);