FFMPeg exception setDataSource failed: status = 0xFFFFFFFF - exception

I have 175 mp4 files. When I process file from index 0 to index 65 (or 66), I get exception:
java.lang.IllegalArgumentException: setDataSource failed: status = 0xFFFFFFFF
at wseemann.media.FFmpegMediaMetadataRetriever.setDataSource(Native Method)
at com.jni.utils.Mp4ParserUsingFFMpeg.createThumbnail(Mp4ParserUsingFFMpeg.java:518)
at com.example.readmdtfile.activity.MainActivity$createMp4Async.createThumbnail(MainActivity.java:71)
at com.example.readmdtfile.activity.MainActivity$createMp4Async.doInBackground(MainActivity.java:55)
at com.example.readmdtfile.activity.MainActivity$createMp4Async.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
If I run process from index 65 (or nearby), processing file 65 is successful. But it still get exception sometimes
Here is code which i'm using:
public static Bitmap createThumbnail (String videoPath) {
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
Bitmap bitmap = null;
try {
retriever.setDataSource(videoPath); //file's path
String key;
String value;
for (int i = 0; i < MetadataKey.METADATA_KEYS.length; i++) {
key = MetadataKey.METADATA_KEYS[i];
value = retriever.extractMetadata(key);
if (value != null) {
// metadata.add(new Metadata(key, value));
Log.i(TAG, "Key: " + key + " Value: " + value);
}
}
bitmap = retriever.getFrameAtTime();
if (bitmap != null) {
Log.d(TAG, "Extracted frame");
Bitmap b2 = retriever.getFrameAtTime(4000000,
FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC);
if (b2 != null) {
bitmap = b2;
}
} else {
Log.d(TAG, "Failed to extract frame");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
retriever.release();
}
return bitmap;
}
https://github.com/wseemann/FFmpegMediaMetadataRetriever/issues/59
Please help me.

The error is simple, an IllegalArgumentException means the video URI is invalid, if this occurs an exception is thrown. Verify the URI is valid before attempting to use it with FFmpegMediaMetadataRetriever.

The error is simple, an RuntimeException means the video URI is invalid. Verify the valid Video URI with .mp4 format, before attempting to use it with FFmpegMediaMetadataRetriever.
ImageView thumbnail1 = (ImageView) findViewById(R.id.video1);
thumbnail1.setImageBitmap(retriveVideoFrameFromVideo("http://techslides.com/demos/sample-videos/small.mp4"));
public Bitmap retriveVideoFrameFromVideo(String videoPath) {
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try {
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
// mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime(1, MediaMetadataRetriever.OPTION_CLOSEST);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
} finally {
if (mediaMetadataRetriever != null) {
mediaMetadataRetriever.release();
}
}
return bitmap;
}

you just have to give setDataSource a String, save your path or url in a string like this:
String url;
mmr = new FFmpegMediaMetadataRetriever();
url = "http://www.stephaniequinn.com/Music/Commercial%20DEMO%20-%2009.mp3";
mmr.setDataSource(url, new HashMap<String, String>());
or:
mmr = new FFmpegMediaMetadataRetriever();
string s="path"
mmr.setDataSource(path);

Related

getting java.nio.BufferUnderflowException while reading dbf file after using dbaseFileWriter.write(vals);

I'm using DbaseFileReader and DBaseFileWriter to read and update records in a dbf file. When I read the file first there is no error while opening DBF file but after I write some values to DBF using below method I'm getting the following Error
I've checked the value types in Object[] array, both type and count of values are equal to dbf file fields.
public static boolean updateFeatureAtts(String shpFile, Map<String, Object> attsFeature) throws IOException {
String file = CN.getMapDataFolder() + CN.FOLDER_LAYERS + "/" + shpFile.replace(".shp", ".dbf");
DbaseFileWriter dbaseFileWriter = null;
DbaseFileReader dbaseFileReader = null;
ReadableByteChannel dbfChannel = null;
WritableByteChannel writableByteChannel = null;
FileOutputStream fileOutputStream = null;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
dbfChannel = Channels.newChannel(inputStream);
dbaseFileReader = new DbaseFileReader(dbfChannel, true, Charset.forName("Windows-1256"));
DbaseFileHeader header = dbaseFileReader.getHeader();
for (Iterator<Map.Entry<String, Object>> iterator = attsFeature.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<String, Object> entry = iterator.next();
if (entry.getKey().equals("FID")) {
iterator.remove();
}
}
fileOutputStream = new FileOutputStream(file);
writableByteChannel = Channels.newChannel(fileOutputStream);
dbaseFileWriter = new DbaseFileWriter(header, writableByteChannel, Charset.forName("UTF-8"), TimeZone.getDefault());
Object[] vals = attsFeature.values().toArray();
dbaseFileWriter.write(vals);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null)
inputStream.close();
if (fileOutputStream != null)
fileOutputStream.close();
if (dbaseFileReader != null)
dbaseFileReader.close();
if (dbaseFileWriter != null)
dbaseFileWriter.close();
}
return true;
}
this is the error
java.nio.BufferUnderflowException at
java.nio.DirectByteBuffer.get(DirectByteBuffer.java: 164)
at org.geotools.data.shapefile.dbf.DbaseFileReader.read(DbaseFileReader.java: 417)
at org.geotools.data.shapefile.dbf.DbaseFileReader.readRow(DbaseFileReader.java: 314)
at com.edsab.gedat.util.DBaseFileHandler.findRecord(DBaseFileHandler.java: 174)
at com.edsab.gedat.adapter.AttributePagerAdapter.instantiateItem(AttributePagerAdapter.java: 102)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java: 1003)
at android.support.v4.view.ViewPager.populate(ViewPager.java: 1217)
at android.support.v4.view.ViewPager.populate(ViewPager.java: 1085)
at android.support.v4.view.ViewPager$3.run(ViewPager.java: 273)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 777)
at android.view.Choreographer.doCallbacks(Choreographer.java: 590)
at android.view.Choreographer.doFrame(Choreographer.java: 559)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 763)
at android.os.Handler.handleCallback(Handler.java: 739)
at android.os.Handler.dispatchMessage(Handler.java: 95)
at android.os.Looper.loop(Looper.java: 145)
at android.app.ActivityThread.main(ActivityThread.java: 6918)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 1199)

How to work around jsch.addIdentity() in Junit test?

I use apache mina sshd to set up a mocked ssh server for Junit testing purpose. Since the documentation for apache mina is quite unclear, I cannot figure out how to deal with authentication problem in testing.
Code I would like to test, basically using Jsch to transfer file from local to remote.
public static void scpTo(String rfilePath, String lfilePath, String user, String host, String keyPath, int port) {
FileInputStream fis=null;
try {
while(true) {
String rfile = rfilePath;
String lfile = lfilePath;
JSch jsch = new JSch();
jsch.addIdentity(keyPath);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
Session session = jsch.getSession(user, host, port);
session.setConfig(config);
session.connect();
// exec 'scp -t rfile' remotely
String command = "scp " + " -t " + rfile;
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream();
channel.connect();
if (checkAck(in) != 0) {
System.exit(0);
}
File _lfile = new File(lfile);
if(!_lfile.exists()) {
System.err.println("Local file not existing");
}
//check file existing
File _rfile = new File(rfile);
if (_rfile.exists()) {
System.out.println("Remote file already existed");
break;
}
// send "C0644 filesize filename", where filename should not include '/'
long filesize = _lfile.length();
command = "C0644 " + filesize + " ";
if (lfile.lastIndexOf('/') > 0) {
command += lfile.substring(lfile.lastIndexOf('/') + 1);
} else {
command += lfile;
}
command += "\n";
out.write(command.getBytes());
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
// send a content of lfile
fis = new FileInputStream(lfile);
byte[] buf = new byte[1024];
while (true) {
int len = fis.read(buf, 0, buf.length);
if (len <= 0) break;
out.write(buf, 0, len); //out.flush();
}
fis.close();
fis = null;
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
out.close();
channel.disconnect();
session.disconnect();
//System.exit(0);
Thread.sleep(2000);
}
} catch (Exception e) {
System.out.println(e);
try {
if (fis != null) fis.close();
} catch (Exception ee) {
}
}
}
And the setUp used for testing. If I would like to authenticate all the user & host pairs by using a given key file in my resource folder, what should I do for setUp? For the current setUp, it will have Auth fail error.
#Before
public void setup() {
user = "siyangli";
host = "localhost";
//pick a port not occupied for tesing
port = 22998;
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
keyPath = "/Users/siyangli/.ssh/id_rsa";
//it will change the key file??? do not know why, how to work around the authentication key??
sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"/Users/siyangli/.ssh/id_rsa"}));
//sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(keyPath));
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(String username, String password, ServerSession session) {
return true;
}
});
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
#Override
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return true;
}
});
CommandFactory myCommandFactory = new CommandFactory() {
public Command createCommand(String command) {
System.out.println("Command: " + command);
return null;
}
};
sshd.setCommandFactory(new ScpCommandFactory(myCommandFactory));
List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<NamedFactory<UserAuth>>();
userAuthFactories.add(new UserAuthPassword.Factory());
sshd.setUserAuthFactories(userAuthFactories);
List<NamedFactory<Command>> namedFactoryList = new ArrayList<NamedFactory<Command>>();
namedFactoryList.add(new SftpSubsystem.Factory()); sshd.setSubsystemFactories(namedFactoryList);
try {
sshd.start();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("Finished setup !!! ");
}
You need to change this line:
userAuthFactories.add(new UserAuthPassword.Factory());
to
userAuthFactories.add(new UserAuthPublicKey.Factory());

Converting finalBufferData into img url to display

I am trying to extract several images url constructed from parts of a JSON to be displayed.
I was able to retrieve the JSON and then construct several url from the JSON displaying it as a text on the screen ( String ).
at the end of the AsyncTask i used the Universal Image Loader, to display a single pic, in case the JSON contain information of a single pic, but the problem is whnen construct several url from the JSON :
finalBufferData.append("http://res.cloudinary.com/CLOUD_NAME/" + fileType +
"/upload/v" + version + "/" + publicID + "." + format + "/n");
it create a string of address just in separate lines ( if displayed in a textView), but bening passed to UIL it is not acceptable.
So i am not sure how to do this, since i am trying to have an image view within a listView in a linearway or differently maybe, to display several images, depending on the JSON information .
Any suggestion on how to do this will be great .
My AsyncTask code it;
public class JsonTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("resources");
StringBuffer finalBufferData = new StringBuffer();
for(int i=0; i<parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
String publicID = finalObject.getString("public_id");
String version = finalObject.getString("version");
String format = finalObject.getString("format");
finalBufferData.append("http://res.cloudinary.com/CLOUD_NAME/" + fileType +
"/upload/v" + version + "/" + publicID + "." + format);
}
return finalBufferData.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ImageLoader.getInstance().displayImage(result, imageViewDisplayUp);
//imagesList.setText(result);
}
}
}
found a way around it, by adding another String which is not in the JSON but get created from other JASON strings.
Since the public_id, version, and format are in the JSON downloaded from Cloudinary and needed to build the right address for the images to be passed into the ImageLoader, and i couldnt not find another way to retrieve a list of images urls uploaded by the user with a specific tag to Cloudinary, without using the admin api which require writing api_secret in the program, i ended up doing the following;
public class JsonTask extends AsyncTask<String, String, List<upImgModels> > {
#Override
protected List<upImgModels> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("resources");
List<upImgModels> upImgList = new ArrayList<>();
for(int i=0; i<parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
upImgModels upImgModels = new upImgModels();
upImgModels.setPublic_id(finalObject.getString("public_id"));
upImgModels.setVersion(finalObject.getString("version"));
upImgModels.setFormat(finalObject.getString("format"));
upImgModels.setAddress("http://res.cloudinary.com/we4x4/" + fileType
+ "/upload/v" + finalObject.getString("version") + "/"
+ finalObject.getString("public_id") + "." +
finalObject.getString("format"));
upImgList.add(upImgModels);
}
return upImgList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(List<upImgModels> result) {
super.onPostExecute(result);
upImgAdapter adapter = new upImgAdapter(getApplicationContext(), R.layout.row, result);
listViewUpload.setAdapter(adapter);
//imagesList.setText(result);
}
}
public class upImgAdapter extends ArrayAdapter{
public List<upImgModels> upImgModelsList;
private int resource;
private LayoutInflater inflater;
public upImgAdapter(Context context, int resource, List<upImgModels> objects) {
super(context, resource, objects);
upImgModelsList = objects;
this.resource = resource;
inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
if(convertView == null){
convertView = inflater.inflate(R.layout.row, null);
}
ImageView imageViewDisplay;
imageViewDisplay = (ImageView)convertView.findViewById(R.id.imageViewDisplay);
ImageLoader.getInstance().displayImage(upImgModelsList.get(position).getAddress(), imageViewDisplay);
return convertView;
}
}
}
I hope someone could suggest a better way to do this if it is possible, which i am sure that is the case.

Java Service Error - webMethods

In a java service, without a function declaration, a function call is there and only compile time error comes. But the output is as expected with no run time errors. How is that possible? Can anyone please explain?
"The method functionName() is undefined" is the error it shows.
Below is the code.
public static final void documentToStringVals(IData pipeline)
throws ServiceException {
// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
String success = "false";
IData inputDoc = null;
String outputValue = "";
String headerYN = "N";
boolean headerValue = false;
String delimiter = ",";
String newline = System.getProperty("line.separator");
if (pipelineCursor.first("inputDocument") ) {
inputDoc = (IData) pipelineCursor.getValue();
}
else {
throw new ServiceException("inputDocument is a required parameter");
}
if (pipelineCursor.first("delimiter") ) {
delimiter = (String) pipelineCursor.getValue();
}
if (pipelineCursor.first("headerYN") ) {
headerYN = (String) pipelineCursor.getValue();
}
if (headerYN.equalsIgnoreCase("Y")) {
headerValue = true;
}
try {
outputValue = docValuesToString(inputDoc, headerValue, delimiter);
outputValue += newline;
success = "true";
}
catch (Exception e) {
System.out.println("Exception in getting string from document: " + e.getMessage());
pipelineCursor.insertAfter("errorMessage", e.getMessage());
}
pipelineCursor.insertAfter("success", success);
pipelineCursor.insertAfter("outputValue", outputValue);
pipelineCursor.destroy();
}
The code you posted has no reference to "functionName", so I suspect there's a reference to it either in the shared code section or in another Java service in the same folder. Given that all Java services in a folder get compiled into a single class, and therefore all those services need to be compiled together, this could cause the error message when you're compiling the service above.

Drawing a route between 2 locations Google Maps API Android V2

I was playing around with the Google Maps API V2 on android.
Trying to get a path between 2 locations and doing this with the JSON Parsing.
I am getting a route. and the route starts out how it should be. but then at one point it goes the wrong way.
My end destination ends up wrong. And with some other locations my app just gets terminated.
This is what i have done
Here is my makeURL method
public String makeUrl(){
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.googleapis.com/maps/api/directions/json");
urlString.append("?origin="); //start positie
urlString.append(Double.toString(source.latitude));
urlString.append(",");
urlString.append(Double.toString(source.longitude));
urlString.append("&destination="); //eind positie
urlString.append(Double.toString(dest.latitude));
urlString.append(",");
urlString.append(Double.toString(dest.longitude));
urlString.append("&sensor=false&mode=driving");
return urlString.toString();
}
my JSON parser
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public JSONParser() {
// TODO Auto-generated constructor stub
}
public String getJSONFromURL(String url){
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch(UnsupportedEncodingException e){
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null){
sb.append(line + "\n");
//Log.e("test: ", sb.toString());
}
json = sb.toString();
is.close();
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("buffer error", "Error converting result " + e.toString());
}
return json;
}
I draw my Path with this method
public void drawPath(String result){
try{
final JSONObject json = new JSONObject(result);
JSONArray routeArray = json.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
Log.d("test: ", encodedString);
List<LatLng> list = decodePoly(encodedString);
LatLng last = null;
for (int i = 0; i < list.size()-1; i++) {
LatLng src = list.get(i);
LatLng dest = list.get(i+1);
last = dest;
Log.d("Last latLng:", last.latitude + ", " + last.longitude );
Polyline line = googleMap.addPolyline(new PolylineOptions().add(
new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude, dest.longitude))
.width(2)
.color(Color.BLUE));
}
Log.d("Last latLng:", last.latitude + ", " + last.longitude );
}catch (JSONException e){
e.printStackTrace();
}
}
And I decode my JSON with
private List<LatLng> decodePoly(String encoded){
List<LatLng> poly = new ArrayList<LatLng>();
int index = 0;
int length = encoded.length();
int latitude = 0;
int longitude = 0;
while(index < length){
int b;
int shift = 0;
int result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int destLat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
latitude += destLat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b > 0x20);
int destLong = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
longitude += destLong;
poly.add(new LatLng((latitude / 1E5),(longitude / 1E5) ));
}
return poly;
}
And then coded with an AsyncTask
Thanks in advance.
Sorry for the long wait.. i have fixed it a while ago but i hadn't put my solution on here yet.
It was basically a typo...
In my Json decoder i use 2 Do while statements with
while (b >= 0x20);
In the second Do While statement i forgot the "=".
Therefore it wasn't rendering correctly...
thanks
I believe that you are creating your LatLng objects from overview_polyline. This, according to Google documentation "contains an object holding an array of encoded points that represent an approximate (smoothed) path of the resulting directions.".
I'm pretty sure that you can get a more detailed route building your LatLng object based on legs[] and steps[] data as the official documentation states that A step is the most atomic unit of a direction's route, containing a single step describing a specific, single instruction on the journey.
Take a look at:
https://developers.google.com/maps/documentation/directions/#Routes
Tmichel,
the Michael has the correctly wave, because on legs and steps on your route plot the line out of the street.
Legs and steps, has informations around coordinates for informations to alert the user.
Polylines are the correct and precise points over the street.
Sorry my bad english