1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.gallery3d.util;
18 
19 import android.content.ContentResolver;
20 import android.content.ContentValues;
21 import android.database.Cursor;
22 import android.media.MediaMetadataRetriever;
23 import android.net.Uri;
24 import android.os.Environment;
25 import android.provider.MediaStore.Video;
26 import android.provider.MediaStore.Video.VideoColumns;
27 
28 import com.android.gallery3d.filtershow.tools.SaveImage.ContentResolverQueryCallback;
29 
30 import java.io.File;
31 import java.io.IOException;
32 import java.text.SimpleDateFormat;
33 import java.util.Date;
34 
35 public class SaveVideoFileUtils {
36     // This function can decide which folder to save the video file, and generate
37     // the needed information for the video file including filename.
getDstMp4FileInfo(String fileNameFormat, ContentResolver contentResolver, Uri uri, String defaultFolderName)38     public static SaveVideoFileInfo getDstMp4FileInfo(String fileNameFormat,
39             ContentResolver contentResolver, Uri uri, String defaultFolderName) {
40         SaveVideoFileInfo dstFileInfo = new SaveVideoFileInfo();
41         // Use the default save directory if the source directory cannot be
42         // saved.
43         dstFileInfo.mDirectory = getSaveDirectory(contentResolver, uri);
44         if ((dstFileInfo.mDirectory == null) || !dstFileInfo.mDirectory.canWrite()) {
45             dstFileInfo.mDirectory = new File(Environment.getExternalStorageDirectory(),
46                     BucketNames.DOWNLOAD);
47             dstFileInfo.mFolderName = defaultFolderName;
48         } else {
49             dstFileInfo.mFolderName = dstFileInfo.mDirectory.getName();
50         }
51         dstFileInfo.mFileName = new SimpleDateFormat(fileNameFormat).format(
52                 new Date(System.currentTimeMillis()));
53 
54         dstFileInfo.mFile = new File(dstFileInfo.mDirectory, dstFileInfo.mFileName + ".mp4");
55         return dstFileInfo;
56     }
57 
querySource(ContentResolver contentResolver, Uri uri, String[] projection, ContentResolverQueryCallback callback)58     private static void querySource(ContentResolver contentResolver, Uri uri,
59             String[] projection, ContentResolverQueryCallback callback) {
60         Cursor cursor = null;
61         try {
62             cursor = contentResolver.query(uri, projection, null, null, null);
63             if ((cursor != null) && cursor.moveToNext()) {
64                 callback.onCursorResult(cursor);
65             }
66         } catch (Exception e) {
67             // Ignore error for lacking the data column from the source.
68         } finally {
69             if (cursor != null) {
70                 cursor.close();
71             }
72         }
73     }
74 
getSaveDirectory(ContentResolver contentResolver, Uri uri)75     private static File getSaveDirectory(ContentResolver contentResolver, Uri uri) {
76         final File[] dir = new File[1];
77         querySource(contentResolver, uri,
78                 new String[] { VideoColumns.DATA },
79                 new ContentResolverQueryCallback() {
80             @Override
81             public void onCursorResult(Cursor cursor) {
82                 dir[0] = new File(cursor.getString(0)).getParentFile();
83             }
84         });
85         return dir[0];
86     }
87 
88 
89     /**
90      * Insert the content (saved file) with proper video properties.
91      */
insertContent(SaveVideoFileInfo mDstFileInfo, ContentResolver contentResolver, Uri uri )92     public static Uri insertContent(SaveVideoFileInfo mDstFileInfo,
93             ContentResolver contentResolver, Uri uri ) {
94         long nowInMs = System.currentTimeMillis();
95         long nowInSec = nowInMs / 1000;
96         final ContentValues values = new ContentValues(13);
97         values.put(Video.Media.TITLE, mDstFileInfo.mFileName);
98         values.put(Video.Media.DISPLAY_NAME, mDstFileInfo.mFile.getName());
99         values.put(Video.Media.MIME_TYPE, "video/mp4");
100         values.put(Video.Media.DATE_TAKEN, nowInMs);
101         values.put(Video.Media.DATE_MODIFIED, nowInSec);
102         values.put(Video.Media.DATE_ADDED, nowInSec);
103         values.put(Video.Media.DATA, mDstFileInfo.mFile.getAbsolutePath());
104         values.put(Video.Media.SIZE, mDstFileInfo.mFile.length());
105         int durationMs = retrieveVideoDurationMs(mDstFileInfo.mFile.getPath());
106         values.put(Video.Media.DURATION, durationMs);
107         // Copy the data taken and location info from src.
108         String[] projection = new String[] {
109                 VideoColumns.DATE_TAKEN,
110                 VideoColumns.LATITUDE,
111                 VideoColumns.LONGITUDE,
112                 VideoColumns.RESOLUTION,
113         };
114 
115         // Copy some info from the source file.
116         querySource(contentResolver, uri, projection,
117                 new ContentResolverQueryCallback() {
118                 @Override
119                     public void onCursorResult(Cursor cursor) {
120                         long timeTaken = cursor.getLong(0);
121                         if (timeTaken > 0) {
122                             values.put(Video.Media.DATE_TAKEN, timeTaken);
123                         }
124                         double latitude = cursor.getDouble(1);
125                         double longitude = cursor.getDouble(2);
126                         // TODO: Change || to && after the default location
127                         // issue is
128                         // fixed.
129                         if ((latitude != 0f) || (longitude != 0f)) {
130                             values.put(Video.Media.LATITUDE, latitude);
131                             values.put(Video.Media.LONGITUDE, longitude);
132                         }
133                         values.put(Video.Media.RESOLUTION, cursor.getString(3));
134 
135                     }
136                 });
137 
138         return contentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, values);
139     }
140 
retrieveVideoDurationMs(String path)141     private static int retrieveVideoDurationMs(String path) {
142         int durationMs = 0;
143         // Calculate the duration of the destination file.
144         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
145         retriever.setDataSource(path);
146         String duration = retriever.extractMetadata(
147                 MediaMetadataRetriever.METADATA_KEY_DURATION);
148         if (duration != null) {
149             durationMs = Integer.parseInt(duration);
150         }
151         try {
152             retriever.release();
153         } catch (IOException e) {
154             // Ignore errors occurred while releasing the retriever.
155         }
156         return durationMs;
157     }
158 
159 }
160