docs: update plugin docs
[platform/upstream/gst-plugins-good.git] / ext / jpeg / gstjpegdec.c
index 6f9477e..d88b258 100644 (file)
@@ -376,11 +376,13 @@ gst_jpeg_dec_parse (GstVideoDecoder * bdec, GstVideoCodecFrame * frame,
       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;
     }
 
 
@@ -1192,10 +1194,38 @@ gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * 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;
 
@@ -1220,12 +1250,13 @@ gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
   /* 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;
@@ -1301,8 +1332,15 @@ gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
         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);