EBC Exercise 21 Running Audio and Video

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.

Build Audio Executable

 * Change to the lab06c_audio_loopthru directory from before.

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/
 * Build the application using “make debug”.

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

Build Video Executable
$ cd ../../VideoThru/lab07d_video_loopthru/ $ make clean $ make
 * Change to the lab07d_video_loopthru directory then build the application.

Run Audio and Video in Separate Processes
$ ./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 app_AUDIO 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.
 * Execute the videoThru_DEBUG.Beagle application (the video loop-thru application) using the following command:

$ jobs
 * 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:

$ kill %1
 * Halt the audio loop-thru using the kill command.

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
$ cd ..
 * Change to the VideoThru directory.

Two previously unused files have been provided for you (make sure they’re #included): $ ls lab08b_audio_video thread.c thread.h 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.)
 * List the lab08b_audio_video directory.
 * Examine thread.c in gedit or similar editor.

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.

$ cp –rf lab07a_osd_setup/* lab08b_audio_video
 * Copy the full contents of lab07a_osd_setup into lab08b_audio_video.

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

$ cp –rf lab07d_video_loopthru/* lab08b_audio_video
 * Copy the full contents of lab07d_video_loopthru into lab08b_audio_video.

Edit main.c

 * Open lab08b_audio_video/main.c in a text editor.

Your main.c file should contain the following: video_thread.h 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_thread.h audio_env (which is the audio_thread_env variable) as well as (Refer to lab07a for this code.) osd_thread.h osd_env (which is the audio_thread_env variable)
 * Fill in the missing .h files, as well as the missing _env variables for the audio and osd threads to main.c.

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.
 * Make sure that video, audio and osd while loops exit when Ctrl-C is pressed.

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 and osd_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. sleep(1); Don’t forget to include the proper header file for the sleep function: unistd.h
 * 1) ifdef _DEBUG_
 * 1) endif

This is the header file for the code you examined a few steps above.
 * Include the  header file that prototypes the launch_pthread function.


 * Declare three pthread handles and three return pointers needed to manage our new threads (audio, video, osd).

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

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

It should end up looking like: pthread_t audioThread, osdThread, videoThread; void *audioThreadReturn, *osdThreadReturn, *videoThreadReturn;