diff options
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | ext/metadata/TODO | 3 | ||||
-rw-r--r-- | ext/metadata/gstmetadatademux.c | 16 | ||||
-rw-r--r-- | ext/metadata/metadata.c | 6 | ||||
-rw-r--r-- | ext/metadata/metadata.h | 9 | ||||
-rw-r--r-- | ext/metadata/metadataparsejpeg.c | 76 | ||||
-rw-r--r-- | ext/metadata/metadataparsejpeg.h | 5 | ||||
-rw-r--r-- | ext/metadata/metadataparsepng.c | 21 | ||||
-rw-r--r-- | ext/metadata/metadataparsepng.h | 6 | ||||
-rw-r--r-- | ext/metadata/test/MetadataEditorMain.glade | 15 | ||||
-rw-r--r-- | ext/metadata/test/metadata_editor.c | 137 |
11 files changed, 255 insertions, 57 deletions
@@ -1,3 +1,17 @@ +2007-12-17 Edgard Lima <edgard.lima@indt.org.br> + + * ext/metadata/TODO: + * ext/metadata/gstmetadatademux.c: + * ext/metadata/metadata.c: + * ext/metadata/metadata.h: + * ext/metadata/metadataparsejpeg.c: + * ext/metadata/metadataparsejpeg.h: + * ext/metadata/metadataparsepng.c: + * ext/metadata/metadataparsepng.h: + * ext/metadata/test/MetadataEditorMain.glade: + * ext/metadata/test/metadata_editor.c: + Added "parse-only" property to metadatademux. + 2007-12-16 David Schleef <ds@schleef.org> * sys/glsink/glimagesink.c: @@ -70,7 +84,7 @@ * sys/glsink/gstopengl.c: Use the new video-common.h stuff. Readd support for RGB video. -2007-12-14 Edgard Lima,,,, <edgard.lima@indt.org.br> +2007-12-14 Edgard Lima <edgard.lima@indt.org.br> * ext/metadata/Makefile.am: * ext/metadata/TODO: @@ -1344,7 +1358,7 @@ Now sending iptc tag in whole chunk. Ready to also send exif and xmp in the same way (look at bug #486659). -2007-10-31 Thijs Vermeir,,, <thijsvermeir@gmail.com> +2007-10-31 Thijs Vermeir <thijsvermeir@gmail.com> * gst/librfb/rfbdecoder.c: Some refactoring in RAW encoding diff --git a/ext/metadata/TODO b/ext/metadata/TODO index d44c2f33..b85e38dc 100644 --- a/ext/metadata/TODO +++ b/ext/metadata/TODO @@ -15,6 +15,5 @@ OPEN ISSUES: ex: file.jpeg has XMP, then we do filesrc ! metadataparse ! jpegdec ! pngenc ! metadatamux ! files is the metadata still valid? which fields are no valid anymore? 3- Add GST_TYPE_FRACTION support for GStreamer TAGS -4- Have parse, demux and mux? (or just demux and must) see issue (5) -5- After decided issue (4) put more things to gstmetadatacommon (or else create a Class) +4- After decided issue (4) put more things to gstmetadatacommon (or else create a Class) diff --git a/ext/metadata/gstmetadatademux.c b/ext/metadata/gstmetadatademux.c index 9e53be54..b0d09950 100644 --- a/ext/metadata/gstmetadatademux.c +++ b/ext/metadata/gstmetadatademux.c @@ -88,7 +88,8 @@ enum ARG_0, ARG_EXIF, ARG_IPTC, - ARG_XMP + ARG_XMP, + ARG_PARSE_ONLY }; static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -211,6 +212,10 @@ gst_metadata_demux_class_init (GstMetadataDemuxClass * klass) g_param_spec_boolean ("xmp", "XMP", "Send XMP metadata ?", TRUE, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_PARSE_ONLY, + g_param_spec_boolean ("parse-only", "parse-only", + "If TRUE, don't strip out any chunk", FALSE, G_PARAM_READWRITE)); + gstelement_class->change_state = gst_metadata_demux_change_state; } @@ -300,6 +305,12 @@ gst_metadata_demux_set_property (GObject * object, guint prop_id, else filter->options &= ~META_OPT_XMP; break; + case ARG_PARSE_ONLY: + if (g_value_get_boolean (value)) + filter->options |= META_OPT_PARSE_ONLY; + else + filter->options &= ~META_OPT_PARSE_ONLY; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -322,6 +333,9 @@ gst_metadata_demux_get_property (GObject * object, guint prop_id, case ARG_XMP: g_value_set_boolean (value, filter->options & META_OPT_XMP); break; + case ARG_PARSE_ONLY: + g_value_set_boolean (value, filter->options & META_OPT_PARSE_ONLY); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/ext/metadata/metadata.c b/ext/metadata/metadata.c index 4fcd7c1c..7909db23 100644 --- a/ext/metadata/metadata.c +++ b/ext/metadata/metadata.c @@ -295,7 +295,8 @@ metadata_parse_none (MetaData * meta_data, const guint8 * buf, if (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF) { if (G_LIKELY (meta_data->parse)) metadataparse_jpeg_init (&meta_data->format_data.jpeg_parse, exif, iptc, - xmp, &meta_data->strip_chunks, &meta_data->inject_chunks); + xmp, &meta_data->strip_chunks, &meta_data->inject_chunks, + meta_data->options & META_OPT_PARSE_ONLY); else metadatamux_jpeg_init (&meta_data->format_data.jpeg_mux, &meta_data->strip_chunks, &meta_data->inject_chunks); @@ -315,7 +316,8 @@ metadata_parse_none (MetaData * meta_data, const guint8 * buf, buf[4] == 0x0D && buf[5] == 0x0A && buf[6] == 0x1A && buf[7] == 0x0A) { if (G_LIKELY (meta_data->parse)) metadataparse_png_init (&meta_data->format_data.png_parse, exif, iptc, - xmp, &meta_data->strip_chunks, &meta_data->inject_chunks); + xmp, &meta_data->strip_chunks, &meta_data->inject_chunks, + meta_data->options & META_OPT_PARSE_ONLY); else metadatamux_png_init (&meta_data->format_data.png_mux, &meta_data->strip_chunks, &meta_data->inject_chunks); diff --git a/ext/metadata/metadata.h b/ext/metadata/metadata.h index 2a5329a6..2853136d 100644 --- a/ext/metadata/metadata.h +++ b/ext/metadata/metadata.h @@ -58,10 +58,11 @@ G_BEGIN_DECLS typedef enum _tag_MetaOption { - META_OPT_EXIF = (1 << 0), - META_OPT_IPTC = (1 << 1), - META_OPT_XMP = (1 << 2), - META_OPT_ALL = (1 << 3) - 1 + META_OPT_EXIF = (1 << 0), + META_OPT_IPTC = (1 << 1), + META_OPT_XMP = (1 << 2), + META_OPT_PARSE_ONLY = (1 << 3), + META_OPT_ALL = (1 << 4) - 1 } MetaOption; /* *INDENT-ON* */ diff --git a/ext/metadata/metadataparsejpeg.c b/ext/metadata/metadataparsejpeg.c index 54d9b26d..f2482c72 100644 --- a/ext/metadata/metadataparsejpeg.c +++ b/ext/metadata/metadataparsejpeg.c @@ -83,7 +83,8 @@ metadataparse_jpeg_lazy_update (JpegParseData * jpeg_data) void metadataparse_jpeg_init (JpegParseData * jpeg_data, GstAdapter ** exif_adpt, GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, - MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks) + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks, + gboolean parse_only) { jpeg_data->state = JPEG_PARSE_NULL; jpeg_data->exif_adapter = exif_adpt; @@ -95,6 +96,8 @@ metadataparse_jpeg_init (JpegParseData * jpeg_data, GstAdapter ** exif_adpt, jpeg_data->strip_chunks = strip_chunks; jpeg_data->inject_chunks = inject_chunks; + jpeg_data->parse_only = parse_only; + } void @@ -258,12 +261,17 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, if (0 == memcmp (ExifHeader, *buf, 6)) { MetadataChunk chunk; - memset (&chunk, 0x00, sizeof (MetadataChunk)); - chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ - chunk.size = chunk_size + 2; /* chunk size plus app marker */ - chunk.type = MD_CHUNK_EXIF; + if (!jpeg_data->parse_only) { + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + chunk.type = MD_CHUNK_EXIF; - metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, &chunk); + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, + &chunk); + + } if (!jpeg_data->jfif_found) { /* only inject if no JFIF has been found */ @@ -275,16 +283,19 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, 0x00, 0x00 }; + if (!jpeg_data->parse_only) { - memset (&chunk, 0x00, sizeof (MetadataChunk)); - chunk.offset_orig = 2; - chunk.size = 18; - chunk.type = MD_CHUNK_UNKNOWN; - chunk.data = g_new (guint8, 18); - memcpy (chunk.data, segment, 18); + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = 2; + chunk.size = 18; + chunk.type = MD_CHUNK_UNKNOWN; + chunk.data = g_new (guint8, 18); + memcpy (chunk.data, segment, 18); - metadata_chunk_array_append_sorted (jpeg_data->inject_chunks, - &chunk); + metadata_chunk_array_append_sorted (jpeg_data->inject_chunks, + &chunk); + + } } @@ -304,15 +315,20 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, } if (0 == memcmp (XmpHeader, *buf, 29)) { - MetadataChunk chunk; - memset (&chunk, 0x00, sizeof (MetadataChunk)); - chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ - chunk.size = chunk_size + 2; /* chunk size plus app marker */ - chunk.type = MD_CHUNK_XMP; + if (!jpeg_data->parse_only) { - metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, - &chunk); + MetadataChunk chunk; + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + chunk.type = MD_CHUNK_XMP; + + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, + &chunk); + + } /* if adapter has been provided, prepare to hold chunk */ if (jpeg_data->xmp_adapter) { @@ -339,14 +355,20 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, if (0 == memcmp (IptcHeader, *buf, 14)) { - MetadataChunk chunk; - memset (&chunk, 0x00, sizeof (MetadataChunk)); - chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ - chunk.size = chunk_size + 2; /* chunk size plus app marker */ - chunk.type = MD_CHUNK_IPTC; + if (!jpeg_data->parse_only) { + + MetadataChunk chunk; - metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, &chunk); + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + chunk.type = MD_CHUNK_IPTC; + + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, + &chunk); + + } /* if adapter has been provided, prepare to hold chunk */ if (jpeg_data->iptc_adapter) { diff --git a/ext/metadata/metadataparsejpeg.h b/ext/metadata/metadataparsejpeg.h index d4e6bcdd..e00095d9 100644 --- a/ext/metadata/metadataparsejpeg.h +++ b/ext/metadata/metadataparsejpeg.h @@ -73,6 +73,8 @@ typedef struct _tag_JpegParseData MetadataChunkArray * strip_chunks; MetadataChunkArray * inject_chunks; + gboolean parse_only; + guint32 read; gboolean jfif_found; } JpegParseData; @@ -81,7 +83,8 @@ typedef struct _tag_JpegParseData extern void metadataparse_jpeg_init (JpegParseData * jpeg_data, GstAdapter ** exif_adpt, GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, - MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks); + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks, + gboolean parse_only); extern void metadataparse_jpeg_dispose (JpegParseData * jpeg_data); diff --git a/ext/metadata/metadataparsepng.c b/ext/metadata/metadataparsepng.c index 32595ad4..a5de4dbe 100644 --- a/ext/metadata/metadataparsepng.c +++ b/ext/metadata/metadataparsepng.c @@ -69,14 +69,16 @@ metadataparse_png_lazy_update (PngParseData * jpeg_data) void metadataparse_png_init (PngParseData * png_data, GstAdapter ** exif_adpt, GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, - MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks) + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks, + gboolean parse_only) { png_data->state = PNG_PARSE_NULL; png_data->xmp_adapter = xmp_adpt; png_data->read = 0; png_data->strip_chunks = strip_chunks; - png_data->inject_chunks = inject_chunks; + + png_data->parse_only = parse_only; } @@ -205,14 +207,17 @@ metadataparse_png_reading (PngParseData * png_data, guint8 ** buf, } if (0 == memcmp (XmpHeader, *buf, 18)) { - MetadataChunk chunk; - memset (&chunk, 0x00, sizeof (MetadataChunk)); - chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */ - chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */ - chunk.type = MD_CHUNK_XMP; + if (!png_data->parse_only) { + MetadataChunk chunk; + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */ + chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */ + chunk.type = MD_CHUNK_XMP; - metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk); + metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk); + } /* if adapter has been provided, prepare to hold chunk */ if (png_data->xmp_adapter) { diff --git a/ext/metadata/metadataparsepng.h b/ext/metadata/metadataparsepng.h index 224b48f7..26f87294 100644 --- a/ext/metadata/metadataparsepng.h +++ b/ext/metadata/metadataparsepng.h @@ -67,7 +67,8 @@ typedef struct _tag_PngParseData GstAdapter ** xmp_adapter; MetadataChunkArray * strip_chunks; - MetadataChunkArray * inject_chunks; + + gboolean parse_only; guint32 read; } PngParseData; @@ -76,7 +77,8 @@ typedef struct _tag_PngParseData extern void metadataparse_png_init (PngParseData * png_data, GstAdapter ** exif_adpt, GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, - MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks); + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks, + gboolean parse_only); extern void metadataparse_png_dispose (PngParseData * png_data); diff --git a/ext/metadata/test/MetadataEditorMain.glade b/ext/metadata/test/MetadataEditorMain.glade index ecd09be5..871d8e6b 100644 --- a/ext/metadata/test/MetadataEditorMain.glade +++ b/ext/metadata/test/MetadataEditorMain.glade @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--Generated with glade3 3.2.0 on Wed Dec 12 14:07:03 2007 by edlima@feisty-laptop--> +<!--Generated with glade3 3.2.0 on Mon Dec 17 11:42:47 2007 by edlima@feisty-laptop--> <glade-interface> <widget class="GtkWindow" id="windowMain"> <property name="width_request">800</property> @@ -123,6 +123,19 @@ <property name="position">1</property> </packing> </child> + <child> + <widget class="GtkCheckButton" id="checkbuttonCapture"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Capture image from camera</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_checkbuttonCapture_toggled"/> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> diff --git a/ext/metadata/test/metadata_editor.c b/ext/metadata/test/metadata_editor.c index e3b1cee5..0479e785 100644 --- a/ext/metadata/test/metadata_editor.c +++ b/ext/metadata/test/metadata_editor.c @@ -77,6 +77,9 @@ static void me_gst_cleanup_elements (); static int me_gst_setup_view_pipeline (const gchar * filename, GdkWindow * window); static int +me_gst_setup_capture_pipeline (const gchar * src_file, const gchar * dest_file, + gint * encode_status); +static int me_gst_setup_encode_pipeline (const gchar * src_file, const gchar * dest_file, gint * encode_status); @@ -92,6 +95,7 @@ GstElement *gst_source = NULL; GstElement *gst_metadata_demux = NULL; GstElement *gst_metadata_mux = NULL; GstElement *gst_image_dec = NULL; +GstElement *gst_image_enc = NULL; GstElement *gst_video_scale = NULL; GstElement *gst_video_convert = NULL; GstElement *gst_video_sink = NULL; @@ -108,6 +112,8 @@ GtkWidget *ui_tree = NULL; GtkEntry *ui_entry_insert_tag = NULL; GtkEntry *ui_entry_insert_value = NULL; +GtkToggleButton *ui_chk_bnt_capture = NULL; + GString *filename = NULL; /* @@ -278,6 +284,29 @@ on_buttonInsert_clicked (GtkButton * button, gpointer user_data) } +static void +setup_new_filename (GString * str, const gchar * ext) +{ + int i = 0; + + for (i = str->len - 1; i > 0; --i) { + if (str->str[i] == '/') { + ++i; + break; + } + } + g_string_insert (str, i, "_new_"); + if (ext) { + int len = strlen (ext); + + if (len > str->len) + g_string_append (str, ext); + else if (strcasecmp (ext, &str->str[str->len - len])) + g_string_append (str, ext); + + } +} + void on_buttonSaveFile_clicked (GtkButton * button, gpointer user_data) { @@ -290,14 +319,22 @@ on_buttonSaveFile_clicked (GtkButton * button, gpointer user_data) src_file = g_string_new (filename->str); - g_string_prepend (filename, "_new_"); - remove (filename->str); + if (gtk_toggle_button_get_active (ui_chk_bnt_capture)) { + setup_new_filename (filename, ".jpg"); + if (me_gst_setup_capture_pipeline (src_file->str, filename->str, + &enc_status)) { + goto done; + } + } else { + setup_new_filename (filename, NULL); + if (me_gst_setup_encode_pipeline (src_file->str, filename->str, + &enc_status)) { + goto done; + } + } ui_refresh (); - - if (me_gst_setup_encode_pipeline (src_file->str, filename->str, &enc_status)) { - goto done; - } + remove (filename->str); if (tag_list && gst_metadata_mux) { GstTagSetter *setter = GST_TAG_SETTER (gst_metadata_mux); @@ -342,6 +379,14 @@ done: } +void +on_checkbuttonCapture_toggled (GtkToggleButton * togglebutton, + gpointer user_data) +{ + if (gtk_toggle_button_get_active (togglebutton)) { + } +} + /* * UI handling functions */ @@ -498,8 +543,12 @@ ui_create () ui_entry_insert_value = GTK_ENTRY (glade_xml_get_widget (ui_glade_xml, "entryValue")); + ui_chk_bnt_capture = + GTK_TOGGLE_BUTTON (glade_xml_get_widget (ui_glade_xml, + "checkbuttonCapture")); + if (!(ui_main_window && ui_drawing && ui_tree && ui_entry_insert_tag - && ui_entry_insert_value)) { + && ui_entry_insert_value && ui_chk_bnt_capture)) { fprintf (stderr, "Some widgets couldn't be created\n"); ret = -105; goto done; @@ -648,6 +697,10 @@ me_gst_cleanup_elements () gst_object_unref (gst_image_dec); gst_image_dec = NULL; } + if (gst_image_enc) { + gst_object_unref (gst_image_enc); + gst_image_enc = NULL; + } if (gst_video_scale) { gst_object_unref (gst_video_scale); gst_video_scale = NULL; @@ -697,6 +750,76 @@ done: } static int +me_gst_setup_capture_pipeline (const gchar * src_file, const gchar * dest_file, + gint * encode_status) +{ + int ret = 0; + GstBus *bus = NULL; + gboolean linked; + + *encode_status = ENC_ERROR; + + me_gst_cleanup_elements (); + + /* create elements */ + gst_source = gst_element_factory_make ("v4l2src", NULL); + gst_video_convert = gst_element_factory_make ("ffmpegcolorspace", NULL); + gst_image_enc = gst_element_factory_make ("jpegenc", NULL); + gst_metadata_mux = gst_element_factory_make ("metadatamux", NULL); + gst_file_sink = gst_element_factory_make ("filesink", NULL); + + if (!(gst_source && gst_video_convert && gst_image_enc && gst_metadata_mux + && gst_file_sink)) { + fprintf (stderr, "An element couldn't be created for ecoding\n"); + ret = -300; + goto done; + } + + /* create gst_pipeline */ + gst_pipeline = gst_pipeline_new (NULL); + + if (NULL == gst_pipeline) { + fprintf (stderr, "Pipeline couldn't be created\n"); + ret = -305; + goto done; + } + + /* set elements's properties */ + g_object_set (gst_source, "num-buffers", 1, NULL); + g_object_set (gst_file_sink, "location", dest_file, NULL); + + /* adding and linking elements */ + gst_bin_add_many (GST_BIN (gst_pipeline), gst_source, gst_video_convert, + gst_image_enc, gst_metadata_mux, gst_file_sink, NULL); + + linked = + gst_element_link_many (gst_source, gst_video_convert, gst_image_enc, + gst_metadata_mux, gst_file_sink, NULL); + + /* now element are owned by pipeline (for videosink we keep a extra ref) */ + gst_source = gst_video_convert = gst_image_enc = gst_file_sink = NULL; + gst_object_ref (gst_metadata_mux); + + if (!linked) { + fprintf (stderr, "Elements couldn't be linked\n"); + ret = -310; + goto done; + } + + *encode_status = ENC_UNKNOWN; + + /* adding message bus */ + bus = gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline)); + gst_bus_add_watch (bus, me_gst_bus_callback_encode, encode_status); + gst_object_unref (bus); + +done: + + return ret; + +} + +static int me_gst_setup_encode_pipeline (const gchar * src_file, const gchar * dest_file, gint * encode_status) { |