Monday, November 22, 2010

encoding video for the LG Neon

I like to load videos on my phone to take with me to share with others.

Since switching to a LG Neon phone, and getting the videos on the memory card accessible, I found that some of the videos would not play on this phone, and others do not play well. In response I decided to figure out how to encode good video for this phone.

To choose a good target video format for the phone I decided it would be good to check what format the phone records video in. Low resolution video had a size of 176x144 and used the h263 codec, high resolution video had a size of 320x240 and used the mpeg4 codec, the video frame rate was from 9.86 to 11.19 frames per second, the audio track was 8000 Hz 1 channel.

With this information I started trying different encoding settings.

Down sampling the audio made it sound flat, and keeping the sample rate the same as the source video did not seem to have an effect on playback, so I kept the source sample rate.

Using a video frame rate of 15 instead of 10 seemed to become jumpy on playback.

So, I settled on a video size of 320x240 using the mpeg4 coded with a frame rate of 10 frames per second and the audio rate kept the same as the source. I put this into a conversion script:
#!/bin/sh
for file in "$@"; do
   ffmpeg -i "$file" -vcodec mpeg4 -s 320x240 -r 10 -acodec libfaac "$file".3gp
done

Sunday, November 21, 2010

converting AMR audio files on the command line

I found some more ringtone restrictions on the LG Neon phone.

If you wish to use the bug to set a ring tone, then it must show up in the music player. For a file to show up in the music player is seems that it must be an MP3 file, and over 500kb in size (or 30 seconds).


The ring tone I wish to use is a 3 second amr file, so this is what I did.

Convert the amr file to a wave file for editing
ffmpeg -i josie-ring.amr josie-ring.wav

open the resulting wave file in an audio editor and duplicate the audio until it loops past 30 seconds, then save over the wav file.

Convert the wave file to a full size music mp3
ffmpeg -i josie-ring.wav -ab 128 -ac 2 -ar 44100 josie-ring.mp3

Finally send the resulting mp3 file to the phone (I use bluetooth, but I could also put it on the memory card and transfer it off that onto the phone).

Saturday, November 20, 2010

custom ringtones on LG Neon

I got a new phone last night because the screen on my current phone has partially failed. The new phone is a LG Neon TE356.

On my old phone the ring tone was one of my friends going "Ring Ring", and this is not a ring tone I could possibly download from the ring tone store, also the phone only allows DRM protected mp3 files to be used as ring tones.

After a little bit of searching I found a solution using a bug in the phone software.

  • Start the MP3 player (9. Tools -> 1. MP3 Player).
  • Start playing the default song that came with the phone (1. All songs -> Beautiful Sky).
  • While the song is playing, set the desired MP3 as the ring tone or message tone. (Options -> 3. Search -> MP3 File -> Options -> 3. Set As -> 1. Ringtone -> 1. Yes)

So now I can have my ring tone back.

Sunday, November 7, 2010

disabling idle sleep timeouts

I left the server on a shelf for a bit and tried to connect to it remotely, I found it asleep.

so I turned off the only sleep time I could find:
sudo gconftool-2 \
 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults \
 /apps/gnome-power-manager/timeout/sleep_computer_battery --set --type integer 0

and restarted gdm
sudo /etc/init.d/gdm restart

hopefully the server doesn't go to sleep any longer.

Creating a user account with a previously set password

The user accounts that will exist on the new home server already exist on the previous server, so when they get created the passwords should be copied forward, although this might be a good time to get them set again by the users.

the existing password hashes are stored in /etc/shadow:
happy:$1$xxxxxxxx$xxxxxxxxxxxxxxxxxxxxxx:14667:0:99999:7:::

To create a user account with the same password as listed there, just provide the password hash:
sudo useradd happy -p '$1$xxxxxxxx$xxxxxxxxxxxxxxxxxxxxxx' -s /bin/bash -m

The entire contents of the home directory could also be copied to bring application settings forward as well. Be sure to make sure that the copied files end up owned by the user they were copied for, the user ids will not necessarily be the same.

Ubuntu 10.10 disabling suspend on lid close

The default settings in Ubuntu on a laptop include suspending with the cover is closed, which is reasonable for normal laptop usage, however I am building a server from a laptop with a broken screen, so it will be closed and in the corner most of the time, and not being suspended would be a good thing.

The method that I used on Ubuntu 10.04 did not seem to work, and the control panel does not seem to have the options available on this laptop, so I had to figure out another way to do it.

After reading on how to change some other power manager settings, I came up with a command that changes the settings I want to change. However this just changed it when my user was logged in to the console, to change the default required the commands I had used before and a restart to gdm to load the changed settings.

# make the changes
sudo gconftool-2 \
 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults \
 /apps/gnome-power-manager/buttons/lid_ac --set --type string nothing
sudo gconftool-2 \
 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults \
 /apps/gnome-power-manager/buttons/lid_battery --set --type string nothing

# restart gdm
sudo /etc/init.d/gdm restart

The current settings can be viewed with
gconftool-2 /apps/gnome-power-manager/buttons -R

Now the laptop does not suspend when the cover is closed.

Installing Ubuntu 10.10 and verifying the hard disk in the process

I have a 160GB hard drive with some bad blocks that I wish to install ubuntu onto. The installer does not have an option to verify the disk during formatting, so I needed to boot up the live cd to do that step myself. I had actually gone through the install already on this disk without marking the bad blocks, so there is a damaged file system on the disk due to the bad blocks.

After the initial installation round I have the partition table configured, so I just re-create the root filesystem with “mkfs.ext4 /dev/sda1 -c -V” to get the blank root with all the bad blocks marked.

After making the file system, start the installer and tell it to do manual partitions, then tell it to use the freshly formatted partition as root and to not format it.

The rest of the install proceeds as normal.

Saturday, November 6, 2010

three implimentations of a stack in C

I decided to write up three implementations of the basic stack data structure in C, complete with tests.

#include <stdio.h>
#include <stdlib.h>

void check(char *message, int success) {
 printf("%s %s\n", success ? "pass" : "FAIL", message);
}

/*
 * array fixed stack. create an array of length one greater than the maximum
 * stack depth, and call aInit on it to set it up.
 */
void aInit(int *stack) {
 stack[0] = 0;
}

void aPush(int *stack, int value) {
 stack[++stack[0]] = value;
}

int aPeek(int *stack) {
 if(stack[0] == 0) {
  return 0;
 }

 return stack[stack[0]];
}

int aPop(int *stack) {
 if(stack[0] == 0) {
  return 0;
 }

 return stack[stack[0]--];
}

int aSize(int *stack) {
 return stack[0];
}

void aPrint(int *stack) {
 int i;

 /* print the stack from top to bottom */
 for(i = stack[0]; i > 0; i--) {
  printf("%d ", stack[i]);
 }
 printf("\n");
}

void test_a() {
 int stack[10];
 aInit(stack);
 check("a size", aSize(stack) == 0);

 aPush(stack, 1);
 aPush(stack, 2);
 check("a size", aSize(stack) == 2);

 check("a peek", aPeek(stack) == 2);
 check("a peek", aPeek(stack) == 2);

 check("a pop", aPop(stack) == 2);
 check("a size", aSize(stack) == 1);

 aPush(stack, 3);
 check("a size", aSize(stack) == 2);
 check("a peek", aPeek(stack) == 3);
}

/*
 * struct fixed stack
 */
struct sStack {
 int size;
 int data[10];
};

void sInit(struct sStack *stack) {
 stack->size = 0;
}

int sSize(struct sStack *stack) {
 return stack->size;
}

void sPush(struct sStack *stack, int value) {
 stack->data[stack->size] = value;
 stack->size += 1;
}

int sPeek(struct sStack *stack) {
 if(stack->size == 0) {
  return 0;
 }

 return stack->data[stack->size - 1];
}

int sPop(struct sStack *stack) {
 if(stack->size == 0) {
  return 0;
 }

 stack->size -= 1;
 return stack->data[stack->size];
}

void sPrint(struct sStack *stack) {
 int i;

 /* print the stack from top to bottom */
 for(i = stack->size; i > 0; i--) {
  printf("%d ", stack->data[i - 1]);
 }
 printf("\n");
}

void test_s() {
 struct sStack stack;
 sInit(&stack);
 check("s size", sSize(&stack) == 0);

 sPush(&stack, 1);
 sPush(&stack, 2);
 check("s size", sSize(&stack) == 2);

 check("s peek", sPeek(&stack) == 2);
 check("s peek", sPeek(&stack) == 2);

 check("s pop", sPop(&stack) == 2);
 check("s size", sSize(&stack) == 1);

 sPush(&stack, 3);
 check("s size", sSize(&stack) == 2);
 check("s peek", sPeek(&stack) == 3);
}

/*
 * linked dynamic stack
 */
struct lNode {
 struct lNode *next;
 int data;
};

struct lStack {
 struct lNode *head;
};

void lInit(struct lStack *stack) {
 stack->head = NULL;
}

int lSize(struct lStack *stack) {
 int size = 0;
 struct lNode *i;

 i = stack->head;
 while(i != NULL) {
  size += 1;
  i = i->next;
 }
 return size;
}

void lPush(struct lStack *stack, int value) {
 struct lNode *head;

 head = (struct lNode*)calloc(1, sizeof(struct lNode));
 head->data = value;
 head->next = stack->head;

 stack->head = head;
}

int lPeek(struct lStack *stack) {
 if(stack->head == NULL) {
  return 0;
 }

 return stack->head->data;
}

int lPop(struct lStack *stack) {
 struct lNode *head;
 int out;

 head = stack->head;

 if(head == NULL) {
  return 0;
 }

 stack->head = head->next;

 out = head->data;

 free(head);

 return out;
}

void lPrint(struct lStack *stack) {
 struct lNode *i;

 for(i = stack->head; i != NULL; i = i->next) {
  printf("%d ", i->data);
 }
 printf("\n");
}

void lDestroy(struct lStack *stack) {
 struct lNode *head;
 struct lNode *next;

 head = stack->head;
 while(head != NULL) {
  next = head->next;
  free(head);
  head = next;
 }
 stack->head = NULL;
}

void test_l() {
 struct lStack stack;
 lInit(&stack);
 check("l size", lSize(&stack) == 0);

 lPush(&stack, 1);
 lPush(&stack, 2);
 check("l size", lSize(&stack) == 2);

 check("l peek", lPeek(&stack) == 2);
 check("l peek", lPeek(&stack) == 2);

 check("l pop", lPop(&stack) == 2);
 check("l size", lSize(&stack) == 1);

 lPush(&stack, 3);
 check("l size", lSize(&stack) == 2);
 check("l peek", lPeek(&stack) == 3);

 lDestroy(&stack);
}

int main() {
 test_a();
 test_s();
 test_l();
 return 0;
}

I hope the code is clean and clear, but there is a good chance that is is not.