EBC Exercise 21 Running Audio and Video

From eLinux.org
Revision as of 13:41, 27 December 2011 by Yoder (Talk | contribs) (Edit main.c)

Jump to: navigation, search

Welcome to Audio and Video labs Parts a and b. In Part a, you will combine the audio loop-thru application with the video loop-thru application by running them from the Linux Bash terminal.

In Part b, you’ll programmatically combine these two applications into a single (multi-threaded) application that handles both data streams – audio and video.

Part a – Run Audio and Video in Separate Processes

Build Audio Executable

  • Change to the lab06c_audio_loopthru directory from before.
  • Build the application using “make debug”.

This will build the debug version. Note, if you have problems building at this step, try cleaning, then building:

$ make clean
$ make
$ mv app_DEBUG.Beagle ../../VideoThru/lab07d_video_loopthru/

The last command moved app_DEBUG.Beagle to app_AUDIO in the video directory.

Build Video Executable

  • Change to the lab07d_video_loopthru directory then build the application.
$ cd ../../VideoThru/lab07d_video_loopthru/
$ make clean
$ make

Run Audio and Video in Separate Processes

  • Execute the app_AUDIO application using the following command:
$ ./app_AUDIO &

Note, the trailing ampersand (&) in this command indicates that the application is to be run as a separate process. (In this case, our audio app will run in the terminal background, meaning that the terminal will remain open to new commands even while the application is executing.)

  • Execute the videoThru_DEBUG.Beagle application (the video loop-thru application) using the following command:
$ ./videoThru_DEBUG.Beagle

You should now have both audio loop-thru and video loop-thru running concurrently on the board. They are running as concurrent, but separate, processes. In Part b we will use pthreads to run the audio and video loop-thru in parallel threads within the same process or application.

  • Halt the video loop-thru (running in the terminal foreground) by pressing Ctrl-C.
  • Use the following command to determine the process jobs number of the audio loop-thru, which is running in the terminal background:
$ jobs
  • Halt the audio loop-thru using the kill command.
$ kill %1

Part a Question

  • Which scheduling policy is being used by each of the audio and video program processes (i.e. how is the thread within each process being scheduled)?

Part b - Audio and Video - same process

In this lab, we will combine lab06c_audio_loopthru, and lab07d_video_loopthru into a single, multi-threaded application.

File Management

  • Change to the VideoThru directory.
$ cd ..
  • List the lab08b_audio_video directory.

Two previously unused files have been provided for you (make sure they’re #included):

$ ls lab08b_audio_video
thread.c  thread.h
  • Examine thread.c in gedit or similar editor.

This file contains one function, launch_pthread(), which is a “wrapper” function that implements thread creation procedure which was reviewed in class. (That is, rather than making you write all this code from scratch, we chose to wrap it up for you into a single call to launch a pthread.)

Our pthread launch function takes five parameters:

pthread_t *hThread_byref
This is a pointer to a handle (i.e. a handle passed by reference) which is used as a return value. The memory location pointed to by hThread_byref will be updated with a pthread handle.
int type
Integer specifying that the created thread will either be REALTIME or TIMESLICE as per #define in thread.h
int priority
The priority assigned to the thread. (It’s only used for thread type = REALTIME)
void *(*thread_fxn)(void *env)
A pointer to the function that is the entry point for the created thread. This function takes a single pointer as an argument (although the pointer may be a pointer to a structure, effectively allowing multiple arguments.)
void *env
The pointer which will be passed as the argument to thread_fxn() as per the above

Hint: It is important to do the following three steps in this exact order. Otherwise, some of the following directions (i.e. editing main.c) will be incorrect!

Don’t worry about overwriting any files.

  • Copy the full contents of lab07a_osd_setup into lab08b_audio_video.
$ cp –rf lab07a_osd_setup/* lab08b_audio_video
  • Copy the full contents of lab06c_audio_loop-thru into lab08b_audio_video.
$ cp –rf ../AudioThru/lab06c_audio_loopthru/* lab08b_audio_video
  • Copy the full contents of lab07d_video_loopthru into lab08b_audio_video.
$ cp –rf lab07d_video_loopthru/* lab08b_audio_video

Edit main.c

  • Open lab08b_audio_video/main.c in a text editor.
  • Fill in the missing .h files, as well as the missing _env variables for the audio and osd threads to main.c.

Your main.c file should contain the following:

video_env (which is the video_thread_env variable)

You need to add the following to main.c. (Refer to lab06c for this code.)

audio_env (which is the audio_thread_env variable)
  • Make sure that video and audio while loops exit when Ctrl-C is pressed.

Recall that the signal_handler function is run whenever Ctrl-C is pressed. This signal handler sets the quit field in both of these global structures to true, signaling to the thread that it should proceed to its cleanup phase and then exit.

How do the threads know where to look for these variables? These environment structures are passed as the argument to the thread. Within the thread function, the main while loop tests on the appropriate quit variable. When the quit variable becomes true, execution drops out of the while loop and into the final (cleanup) phase of the function.

Currently the signal_handler() function sets video_env.quit to one (true). We need to add similar statements for the audio_env.quit to the signal handler below.

void signal_handler( int sig ) {
    DBG( "Ctrl-C pressed, cleaning up and exiting..\n" );
    video_env.quit = 1;
  • To make debugging easier, put a one-second delay in between *.quit=1 statements. Since we’re exiting three pthreads back-to-back, you might find that their debug messages become interleaved – which can make debugging more difficult. To this end, when building with our “debug” profile, we could delay the start of the second quit by using a Linux time function.

Insert the following code between each *.quit=1 call to cause Linux to sleep for one second. This should make debugging easier.

#ifdef _DEBUG_

Don’t forget to include the proper header file for the sleep() function: unistd.h

  • Include the <pthread.h> header file that prototypes the launch_pthread() function.

This is the header file for the code you examined a few steps above.

  • Declare two pthread handles and two return pointers needed to manage our new threads (audio, video).

At the top of main(), add two pthread handles (of type pthread_t) named audioThread and videoThread. Handles are used to refer to instantiated objects; the handle value will be set during pthread_create() below, then used again later to refer to that pthread instance.

Also, we want to add two void pointers: one named audioThreadReturn and one named videoThreadReturn. The return pointers will be used when “joining” (i.e. exiting) each thread below; they will allow you to interrogate the status after an exit.

It should end up looking like:

pthread_t audioThread, videoThread;
void *audioThreadReturn, *videoThreadReturn;
  • Replace the direct call of video_thread_fxn() with a call of launch_pthread() to create a new thread that has video_thread_fxn() as its entry point.

Currently main.c calls video_thread_fxn. Replace this direct function call with a call to launch_pthread()

Replace the following:

 /* Call video thread function */
 videoThreadReturn = video_thread_fxn((void *) &video_env);

With this starting code … you have to fill in a few details:

/* Create a thread for video loopthru */
if(launch_pthread(&thread, (type), (priority), video_function, argument) != thread_SUCCESS){
    ERR("pthread create failed for video thread\n");
    status = EXIT_FAILURE;
    goto cleanup;

We’ve given you hints, but you need to figure out the actual arguments to launch_pthread(). Don’t forget to add #defines for audio & video thread created masks.

Either REALTIME or TIMESLICE as per thread.h. As per the lecture, we want to set this field to TIMESLICE for video_thread_fxn().
This value will be ignored for TIMESLICE type, so you can set it to zero.
  • Add launch_pthread() calls to launch the audio_thread_fxn() entry points as threads with the following characteristics:
type: REALTIME, priority: 99
type: TIMESLICE, priority: 0 (unused)

At this point, you should have 2 sets of launch_pthread calls (one for video and audio). Be sure to record successful launching of the audio thread in the intiMask.